From 2dc5d044a88fd64e11e35886e78b54a4a9fc2b23 Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?=
Date: Sat, 25 Jan 2014 01:14:29 +0000
Subject: [PATCH] df: also deduplicate virtual file systems
* src/df.c (filter_mountlist): Remove the constraint that
a '/' needs to be in the device name for a mount entry to
be considered for deduplication. Virtual file systems also
have storage associated with them (like tmpfs for example),
and thus need to be deduplicated since they will be shown
in the default df output and subject to --total processing also.
* test/df/skip-duplicates.sh: Add a test to ensure we deduplicate
all entries, even for virtual file systems. Also avoid possible
length operations on many remote file systems in the initial
check of df operation. Also avoid the assumption that "/root"
is on the same file system as "/".
* NEWS: Mention the change in behavior.
---
NEWS | 2 ++
src/df.c | 31 +++++++++++-------------
tests/df/skip-duplicates.sh | 47 +++++++++++++++++++++++++++----------
3 files changed, 50 insertions(+), 30 deletions(-)
diff --git a/NEWS b/NEWS
index 4efd60d2ef..c204b680dc 100644
--- a/NEWS
+++ b/NEWS
@@ -44,6 +44,8 @@ GNU coreutils NEWS -*- outline -*-
[These dd bugs were present in "the beginning".]
+ df now correctly elides duplicates for virtual file systems like tmpfs.
+
head --bytes=-N and --lines=-N now handles devices more
consistently, not ignoring data from virtual devices like /dev/zero,
or on BSD systems data from tty devices.
diff --git a/src/df.c b/src/df.c
index e7639434e6..2b5a54e4a1 100644
--- a/src/df.c
+++ b/src/df.c
@@ -630,26 +630,23 @@ filter_mount_list (void)
}
else
{
- /* If the device name is a real path name ... */
- if (strchr (me->me_devname, '/'))
+ /* If we've already seen this device... */
+ for (devlist = devlist_head; devlist; devlist = devlist->next)
+ if (devlist->dev_num == buf.st_dev)
+ break;
+
+ if (devlist)
{
- /* ... try to find its device number in the devlist. */
- for (devlist = devlist_head; devlist; devlist = devlist->next)
- if (devlist->dev_num == buf.st_dev)
- break;
+ discard_me = me;
- if (devlist)
+ /* ...let the shorter mountdir win. */
+ if ((strchr (me->me_devname, '/')
+ && ! strchr (devlist->me->me_devname, '/'))
+ || (strlen (devlist->me->me_mountdir)
+ > strlen (me->me_mountdir)))
{
- discard_me = me;
-
- /* Let the shorter mountdir win. */
- if (! strchr (devlist->me->me_devname, '/')
- || (strlen (devlist->me->me_mountdir)
- > strlen (me->me_mountdir)))
- {
- discard_me = devlist->me;
- devlist->me = me;
- }
+ discard_me = devlist->me;
+ devlist->me = me;
}
}
}
diff --git a/tests/df/skip-duplicates.sh b/tests/df/skip-duplicates.sh
index 266520aa65..d872f27fc7 100755
--- a/tests/df/skip-duplicates.sh
+++ b/tests/df/skip-duplicates.sh
@@ -21,19 +21,28 @@
print_ver_ df
require_gcc_shared_
-df || skip_ "df fails"
+# We use --local here so as to not activate
+# potentially very many remote mounts.
+df --local || skip_ "df fails"
-# Simulate an mtab file with two entries of the same device number.
-# Also add entries with unstatable mount dirs to ensure that's handled.
+export CU_NONROOT_FS=$(df --local --output=target 2>&1 | grep /. | head -n1)
+test -z "$CU_NONROOT_FS" && unique_entries=1 || unique_entries=2
+
+# Simulate an mtab file to test various cases.
cat > k.c <<'EOF' || framework_failure_
#include