summaryrefslogtreecommitdiffstats
path: root/sys-utils/fstrim.c
diff options
context:
space:
mode:
authorKarel Zak2015-06-10 14:19:45 +0200
committerKarel Zak2015-06-10 14:19:45 +0200
commit8dd51c183396c4bf6344d08b01fb84658e0a8eb4 (patch)
treea9474cce6b6c9ec89e81f3aa544080a0a3d31595 /sys-utils/fstrim.c
parentfdisk: differentiate between +<sector> and +<size>{M,G,...} (diff)
downloadkernel-qcow2-util-linux-8dd51c183396c4bf6344d08b01fb84658e0a8eb4.tar.gz
kernel-qcow2-util-linux-8dd51c183396c4bf6344d08b01fb84658e0a8eb4.tar.xz
kernel-qcow2-util-linux-8dd51c183396c4bf6344d08b01fb84658e0a8eb4.zip
fstrim: de-duplicate by mount source too
Now fstrim de-duplicates by target (mountpoint). This patch adds de-duplication according to mount source (device) to avoid bind mounts or devices mounted more than once. Note that the patch also check FS root, the different FS roots of the same multi-root FS (e.g. btrfs) maybe mounted on different places. # mount --bind /home/wine /mnt/test old version: # fstrim -av /mnt/test: 0 B (0 bytes) trimmed <--- /home/wine: 0 B (0 bytes) trimmed <--- /boot: 0 B (0 bytes) trimmed /home: 0 B (0 bytes) trimmed /: 0 B (0 bytes) trimmed new version: # fstrim -av /mnt/test: 0 B (0 bytes) trimmed <--- /boot: 0 B (0 bytes) trimmed /home: 171.8 MiB (180113408 bytes) trimmed /: 0 B (0 bytes) trimmed Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1162213 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/fstrim.c')
-rw-r--r--sys-utils/fstrim.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/sys-utils/fstrim.c b/sys-utils/fstrim.c
index 847b81924..02ab106a0 100644
--- a/sys-utils/fstrim.c
+++ b/sys-utils/fstrim.c
@@ -147,6 +147,30 @@ static int uniq_fs_target_cmp(
return !mnt_fs_streq_target(a, mnt_fs_get_target(b));
}
+static int uniq_fs_source_cmp(
+ struct libmnt_table *tb __attribute__((__unused__)),
+ struct libmnt_fs *a,
+ struct libmnt_fs *b)
+{
+ int eq;
+
+ if (mnt_fs_is_pseudofs(a) || mnt_fs_is_netfs(a) ||
+ mnt_fs_is_pseudofs(b) || mnt_fs_is_netfs(b))
+ return 1;
+
+ eq = mnt_fs_streq_srcpath(a, mnt_fs_get_srcpath(b));
+ if (eq) {
+ const char *aroot = mnt_fs_get_root(a),
+ *broot = mnt_fs_get_root(b);
+ if (!aroot || !broot)
+ eq = 0;
+ else if (strcmp(aroot, broot) != 0)
+ eq = 0;
+ }
+
+ return !eq;
+}
+
/*
* fstrim --all follows "mount -a" return codes:
*
@@ -172,9 +196,12 @@ static int fstrim_all(struct fstrim_range *rangetpl, int verbose)
if (!tab)
err(MOUNT_EX_FAIL, _("failed to parse %s"), _PATH_PROC_MOUNTINFO);
- /* de-duplicate the table */
+ /* de-duplicate by mountpoints */
mnt_table_uniq_fs(tab, 0, uniq_fs_target_cmp);
+ /* de-duplicate by source and root */
+ mnt_table_uniq_fs(tab, 0, uniq_fs_source_cmp);
+
while (mnt_table_next_fs(tab, itr, &fs) == 0) {
const char *src = mnt_fs_get_srcpath(fs),
*tgt = mnt_fs_get_target(fs);