summaryrefslogtreecommitdiffstats
path: root/sys-utils
diff options
context:
space:
mode:
authorKarel Zak2018-07-31 16:38:59 +0200
committerKarel Zak2018-07-31 16:38:59 +0200
commitc5b8909f13d29d066ee9882fe0e3129d2f3bcffc (patch)
tree3c4fc5b94f41cd2225fc3befe2b547bb50f0b6f8 /sys-utils
parentfstrim: add control struct (diff)
downloadkernel-qcow2-util-linux-c5b8909f13d29d066ee9882fe0e3129d2f3bcffc.tar.gz
kernel-qcow2-util-linux-c5b8909f13d29d066ee9882fe0e3129d2f3bcffc.tar.xz
kernel-qcow2-util-linux-c5b8909f13d29d066ee9882fe0e3129d2f3bcffc.zip
fstrim: add -A|--fstab to trim according to /etc/fstab
Addresses: https://github.com/karelzak/util-linux/issues/673 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils')
-rw-r--r--sys-utils/fstrim.810
-rw-r--r--sys-utils/fstrim.c63
2 files changed, 59 insertions, 14 deletions
diff --git a/sys-utils/fstrim.8 b/sys-utils/fstrim.8
index f86dda984..4e052a546 100644
--- a/sys-utils/fstrim.8
+++ b/sys-utils/fstrim.8
@@ -3,7 +3,7 @@
fstrim \- discard unused blocks on a mounted filesystem
.SH SYNOPSIS
.B fstrim
-.RB [ \-a ]
+.RB [ \-Aa ]
.RB [ \-o
.IR offset ]
.RB [ \-l
@@ -46,6 +46,14 @@ MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB"
is optional, e.g., "K" has the same meaning as "KiB") or the suffixes
KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB.
+.IP "\fB\-A, \-\-fstab\fP"
+Trim all mounted filesystems mentioned in \fI/etc/fstab\fR on devices that support the
+discard operation.
+The other supplied options, like \fB\-\-offset\fR, \fB\-\-length\fR and
+\fB-\-minimum\fR, are applied to all these devices.
+Errors from filesystems that do not support the discard operation are silently
+ignored.
+
.IP "\fB\-a, \-\-all\fP"
Trim all mounted filesystems on devices that support the discard operation.
The other supplied options, like \fB\-\-offset\fR, \fB\-\-length\fR and
diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c
index 92045f851..624ffa309 100644
--- a/sys-utils/fstrim.c
+++ b/sys-utils/fstrim.c
@@ -60,11 +60,12 @@ struct fstrim_control {
struct fstrim_range range;
unsigned int verbose : 1,
+ fstab : 1,
dryrun : 1;
};
/* returns: 0 = success, 1 = unsupported, < 0 = error */
-static int fstrim_filesystem(struct fstrim_control *ctl, const char *path)
+static int fstrim_filesystem(struct fstrim_control *ctl, const char *path, const char *devname)
{
int fd, rc;
struct stat sb;
@@ -91,7 +92,10 @@ static int fstrim_filesystem(struct fstrim_control *ctl, const char *path)
}
if (ctl->dryrun) {
- printf(_("%s (dry run)\n"), path);
+ if (devname)
+ printf(_("%s: 0 B (dry run) trimmed on %s\n"), path, devname);
+ else
+ printf(_("%s: 0 B (dry run) trimmed\n"), path);
rc = 0;
goto done;
}
@@ -109,9 +113,15 @@ static int fstrim_filesystem(struct fstrim_control *ctl, const char *path)
char *str = size_to_human_string(
SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
(uint64_t) range.len);
- /* TRANSLATORS: The standard value here is a very large number. */
- printf(_("%s: %s (%" PRIu64 " bytes) trimmed\n"),
+ if (devname)
+ /* TRANSLATORS: The standard value here is a very large number. */
+ printf(_("%s: %s (%" PRIu64 " bytes) trimmed on %s\n"),
+ path, str, (uint64_t) range.len, devname);
+ else
+ /* TRANSLATORS: The standard value here is a very large number. */
+ printf(_("%s: %s (%" PRIu64 " bytes) trimmed\n"),
path, str, (uint64_t) range.len);
+
free(str);
}
@@ -206,8 +216,10 @@ static int fstrim_all(struct fstrim_control *ctl)
struct libmnt_fs *fs;
struct libmnt_iter *itr;
struct libmnt_table *tab;
+ struct libmnt_cache *cache = NULL;
struct path_cxt *wholedisk = NULL;
int cnt = 0, cnt_err = 0;
+ const char *filename = _PATH_PROC_MOUNTINFO;
mnt_init_debug(0);
ul_path_init_debug();
@@ -216,9 +228,12 @@ static int fstrim_all(struct fstrim_control *ctl)
if (!itr)
err(MNT_EX_FAIL, _("failed to initialize libmount iterator"));
- tab = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);
+ if (ctl->fstab)
+ filename = mnt_get_fstab_path();
+
+ tab = mnt_new_table_from_file(filename);
if (!tab)
- err(MNT_EX_FAIL, _("failed to parse %s"), _PATH_PROC_MOUNTINFO);
+ err(MNT_EX_FAIL, _("failed to parse %s"), filename);
/* de-duplicate by mountpoints */
mnt_table_uniq_fs(tab, 0, uniq_fs_target_cmp);
@@ -226,15 +241,31 @@ static int fstrim_all(struct fstrim_control *ctl)
/* de-duplicate by source */
mnt_table_uniq_fs(tab, MNT_UNIQ_FORWARD, uniq_fs_source_cmp);
+ if (ctl->fstab) {
+ cache = mnt_new_cache();
+ if (!cache)
+ err(MNT_EX_FAIL, _("failed to initialize libmount cache"));
+ }
+
while (mnt_table_next_fs(tab, itr, &fs) == 0) {
const char *src = mnt_fs_get_srcpath(fs),
*tgt = mnt_fs_get_target(fs);
char *path;
int rc = 1;
- if (!src || !tgt || *src != '/' ||
- mnt_fs_is_pseudofs(fs) ||
- mnt_fs_is_netfs(fs))
+ if (!tgt || mnt_fs_is_pseudofs(fs) || mnt_fs_is_netfs(fs))
+ continue;
+
+ if (!src && cache) {
+ /* convert LABEL= (etc.) from fstab to paths */
+ const char *spec = mnt_fs_get_source(fs);
+
+ if (!spec)
+ continue;
+ src = mnt_resolve_spec(spec, cache);
+ }
+
+ if (!src || *src != '/')
continue;
/* Is it really accessible mountpoint? Not all mountpoints are
@@ -258,13 +289,14 @@ static int fstrim_all(struct fstrim_control *ctl)
* This is reason why we ignore EOPNOTSUPP and ENOTTY errors
* from discard ioctl.
*/
- if (fstrim_filesystem(ctl, tgt) < 0)
+ if (fstrim_filesystem(ctl, tgt, src) < 0)
cnt_err++;
}
ul_unref_path(wholedisk);
mnt_unref_table(tab);
mnt_free_iter(itr);
+ mnt_unref_cache(cache);
if (cnt && cnt == cnt_err)
return MNT_EX_FAIL; /* all failed */
@@ -285,7 +317,8 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_("Discard unused blocks on a mounted filesystem.\n"), out);
fputs(USAGE_OPTIONS, out);
- fputs(_(" -a, --all trim all mounted filesystems that are supported\n"), out);
+ fputs(_(" -a, --all trim all supported mounted filesystems\n"), out);
+ fputs(_(" -A, --fstab trim all supported mounted filesystems from /etc/fstab\n"), out);
fputs(_(" -o, --offset <num> the offset in bytes to start discarding from\n"), out);
fputs(_(" -l, --length <num> the number of bytes to discard\n"), out);
fputs(_(" -m, --minimum <num> the minimum extent length to discard\n"), out);
@@ -308,6 +341,7 @@ int main(int argc, char **argv)
static const struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
+ { "fstab", no_argument, NULL, 'A' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "offset", required_argument, NULL, 'o' },
@@ -323,8 +357,11 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
atexit(close_stdout);
- while ((c = getopt_long(argc, argv, "adhVo:l:m:v", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "AadhVo:l:m:v", longopts, NULL)) != -1) {
switch(c) {
+ case 'A':
+ ctl.fstab = 1;
+ /* fallthrough */
case 'a':
all = 1;
break;
@@ -372,7 +409,7 @@ int main(int argc, char **argv)
if (all)
return fstrim_all(&ctl); /* MNT_EX_* codes */
- rc = fstrim_filesystem(&ctl, path);
+ rc = fstrim_filesystem(&ctl, path, NULL);
if (rc == 1)
warnx(_("%s: the discard operation is not supported"), path);