]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
df: only suppress remote mounts of separate exports with --total
authorPádraig Brady <P@draigBrady.com>
Wed, 29 Oct 2014 02:49:17 +0000 (02:49 +0000)
committerPádraig Brady <P@draigBrady.com>
Mon, 24 Nov 2014 09:04:54 +0000 (09:04 +0000)
* src/df.c (filter_mount_list): Separate remote locations are
generally explicitly mounted, so list each even if they share
the same remote device and thus storage.  However with --total
keep the suppression to give a more accurate value for the
total storage available.
(usage): Expand on the new implications of --total and move
it in the options list according to alphabetic order.
doc/coreutils.texi (df invocation): Mention that --total impacts
on deduplication of remote file systems and also move location
according to alphabetic order.
* tests/df/skip-duplicates.sh: Add remote test cases.
* NEWS: Mention the change in behavior.

Reported in http://bugs.debian.org/737399
Reported in http://bugzilla.redhat.com/920806
Reported in http://bugzilla.opensuse.org/866010
Reported in http://bugzilla.opensuse.org/901905

NEWS
doc/coreutils.texi
src/df.c
tests/df/skip-duplicates.sh

diff --git a/NEWS b/NEWS
index 5d3bc58bd195d22faf719e036b5229c2a9f6a0b1..2c7e590e080f6eec4fccebd0cdfe40b6fc186da2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,11 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Changes in behavior
 
+  df no longer suppresses separate exports of the same remote device, as
+  these are generally explicitly mounted.  The --total option does still
+  suppress duplicate remote file systems.
+  [suppression was introduced in coreutils-8.21]
+
   mv no longer supports moving a file to a hardlink, instead issuing an error.
   The implementation was susceptible to races in the presence of multiple mv
   instances, which could result in both hardlinks being deleted.  Also on case
index db24a75dd60e373ffd7830e92e85f4e35eaafb5d..e9008c0189733e3b08236334841a92ac23395221 100644 (file)
@@ -11205,8 +11205,7 @@ Non-integer quantities are rounded up to the next higher unit.
 For bind mounts and without arguments, @command{df} only outputs the statistics
 for that device with the shortest mount point name in the list of file systems
 (@var{mtab}), i.e., it hides duplicate entries, unless the @option{-a} option is
-specified.  Remote file systems, such as NFS, are treated the same way as local
-ones; only one mount entry per remote file system is shown by default.
+specified.
 
 With the same logic, @command{df} elides a mount entry of a dummy pseudo device
 if there is another mount entry of a real block device for that mount point with
@@ -11248,19 +11247,6 @@ due to permissions of the mount point etc.
 Scale sizes by @var{size} before printing them (@pxref{Block size}).
 For example, @option{-BG} prints sizes in units of 1,073,741,824 bytes.
 
-@item --total
-@opindex --total
-@cindex grand total of disk size, usage and available space
-Print a grand total of all arguments after all arguments have
-been processed.  This can be used to find out the total disk size, usage
-and available space of all listed devices.
-
-For the grand total line, @command{df} prints @samp{"total"} into the
-@var{source} column, and @samp{"-"} into the @var{target} column.
-If there is no @var{source} column (see @option{--output}), then
-@command{df} prints @samp{"total"} into the @var{target} column,
-if present.
-
 @optHumanReadable
 
 @item -H
@@ -11401,6 +11387,21 @@ some systems (notably SunOS), doing this yields more up to date results,
 but in general this option makes @command{df} much slower, especially when
 there are many or very busy file systems.
 
+@item --total
+@opindex --total
+@cindex grand total of disk size, usage and available space
+Print a grand total of all arguments after all arguments have
+been processed.  This can be used to find out the total disk size, usage
+and available space of all listed devices.  If no arguments are specified
+df will try harder to elide file systems insignificant to the total
+available space, by suppressing duplicate remote file systems.
+
+For the grand total line, @command{df} prints @samp{"total"} into the
+@var{source} column, and @samp{"-"} into the @var{target} column.
+If there is no @var{source} column (see @option{--output}), then
+@command{df} prints @samp{"total"} into the @var{target} column,
+if present.
+
 @item -t @var{fstype}
 @itemx --type=@var{fstype}
 @opindex -t
index a52afc4d5ee1cbe3de95bc82087a8fdd58f73b5f..7bac18423f9c9a34d490ff6755074781bde2c175 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -640,18 +640,28 @@ filter_mount_list (bool devices_only)
 
           if (devlist)
             {
-                  /* let "real" devices with '/' in the name win.  */
-              if ((strchr (me->me_devname, '/')
-                   && ! strchr (devlist->me->me_devname, '/'))
-                  /* let a shorter mountdir win.  */
-                  || (strlen (devlist->me->me_mountdir)
-                      > strlen (me->me_mountdir))
-                  /* let an entry overmounted on a different device win...  */
-                  || (! STREQ (devlist->me->me_devname, me->me_devname)
-                      /* ... but only when matching an existing mount point, to
-                      avoid problematic replacement when given inaccurate mount
-                      lists, seen with some chroot environments for example.  */
-                      && STREQ (me->me_mountdir, devlist->me->me_mountdir)))
+              if (! print_grand_total && me->me_remote && devlist->me->me_remote
+                  && ! STREQ (devlist->me->me_devname, me->me_devname))
+                {
+                  /* Don't discard remote entries with different locations,
+                     as these are more likely to be explicitly mounted.
+                     However avoid this when producing a total to give
+                     a more accurate value in that case.  */
+                }
+              else if ((strchr (me->me_devname, '/')
+                       /* let "real" devices with '/' in the name win.  */
+                        && ! strchr (devlist->me->me_devname, '/'))
+                       /* let a shorter mountdir win.  */
+                       || (strlen (devlist->me->me_mountdir)
+                           > strlen (me->me_mountdir))
+                       /* let an entry overmounted on a new device win...  */
+                       || (! STREQ (devlist->me->me_devname, me->me_devname)
+                           /* ... but only when matching an existing mnt point,
+                              to avoid problematic replacement when given
+                              inaccurate mount lists, seen with some chroot
+                              environments for example.  */
+                           && STREQ (me->me_mountdir,
+                                     devlist->me->me_mountdir)))
                 {
                   /* Discard mount entry for existing device.  */
                   discard_me = devlist->me;
@@ -1403,7 +1413,6 @@ or all file systems by default.\n\
   -B, --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,\n\
                            '-BM' prints sizes in units of 1,048,576 bytes;\n\
                            see SIZE format below\n\
-      --total           produce a grand total\n\
   -h, --human-readable  print sizes in powers of 1024 (e.g., 1023M)\n\
   -H, --si              print sizes in powers of 1000 (e.g., 1.1G)\n\
 "), stdout);
@@ -1419,6 +1428,12 @@ or all file systems by default.\n\
                                or print all fields if FIELD_LIST is omitted.\n\
   -P, --portability     use the POSIX output format\n\
       --sync            invoke sync before getting usage info\n\
+"), stdout);
+      fputs (_("\
+      --total           elide all entries insignificant to available space,\n\
+                          and produce a grand total\n\
+"), stdout);
+      fputs (_("\
   -t, --type=TYPE       limit listing to file systems of type TYPE\n\
   -T, --print-type      print file system type\n\
   -x, --exclude-type=TYPE   limit listing to file systems not of type TYPE\n\
index 52b9014a366324f9201fbb5fbe48fd6eccbc1eeb..6b984ad21d3ed67e1ca70c6497fbcc4619632e40 100755 (executable)
@@ -26,7 +26,12 @@ require_gcc_shared_
 df --local || skip_ "df fails"
 
 export CU_NONROOT_FS=$(df --local --output=target 2>&1 | grep /. | head -n1)
-test -z "$CU_NONROOT_FS" && unique_entries=1 || unique_entries=2
+export CU_REMOTE_FS=$(df --local --output=target 2>&1 | grep /. |
+                      tail -n+2 | head -n1)
+
+unique_entries=1
+test -z "$CU_NONROOT_FS" || unique_entries=$(expr $unique_entries + 1)
+test -z "$CU_REMOTE_FS" || unique_entries=$(expr $unique_entries + 2)
 
 grep '^#define HAVE_MNTENT_H 1' $CONFIG_HEADER > /dev/null \
       || skip_ "no mntent.h available to confirm the interface"
@@ -46,6 +51,7 @@ cat > k.c <<'EOF' || framework_failure_
 struct mntent *getmntent (FILE *fp)
 {
   static char *nonroot_fs;
+  static char *remote_fs;
   static int done;
 
   /* Prove that LD_PRELOAD works. */
@@ -63,6 +69,9 @@ struct mntent *getmntent (FILE *fp)
     {.mnt_fsname="virtfs",  .mnt_dir="/NONROOT", .mnt_type="fstype1"},
     {.mnt_fsname="virtfs2", .mnt_dir="/NONROOT", .mnt_type="fstype2"},
     {.mnt_fsname="netns",   .mnt_dir="net:[1234567]"},
+    {.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE"},
+    {.mnt_fsname="rem:ote1",.mnt_dir="/REMOTE"},
+    {.mnt_fsname="rem:ote2",.mnt_dir="/REMOTE"},
   };
 
   if (done == 1)
@@ -70,17 +79,26 @@ struct mntent *getmntent (FILE *fp)
       nonroot_fs = getenv ("CU_NONROOT_FS");
       if (!nonroot_fs || !*nonroot_fs)
         nonroot_fs = "/"; /* merge into / entries.  */
+
+      remote_fs = getenv ("CU_REMOTE_FS");
     }
 
   if (done == 1 && !getenv ("CU_TEST_DUPE_INVALID"))
     done++;  /* skip the first entry.  */
 
-  while (done++ <= 7)
+  while (done++ <= 10)
     {
       if (!mntents[done-2].mnt_type)
         mntents[done-2].mnt_type = "-";
       if (STREQ (mntents[done-2].mnt_dir, "/NONROOT"))
         mntents[done-2].mnt_dir = nonroot_fs;
+      if (STREQ (mntents[done-2].mnt_dir, "/REMOTE"))
+        {
+          if (!remote_fs || !*remote_fs)
+            continue;
+          else
+            mntents[done-2].mnt_dir = remote_fs;
+        }
       return &mntents[done-2];
     }
 
@@ -102,6 +120,12 @@ test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?"
 LD_PRELOAD=./k.so df -T >out || fail=1
 test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; }
 
+# With --total we should suppress the duplicate but separate remote file system
+LD_PRELOAD=./k.so df --total >out || fail=1
+test "$CU_REMOTE_FS" && elide_remote=1 || elide_remote=0
+test $(wc -l <out) -eq $(expr 2 + $unique_entries - $elide_remote) ||
+  { fail=1; cat out; }
+
 # Ensure we don't fail when unable to stat (currently) unavailable entries
 LD_PRELOAD=./k.so CU_TEST_DUPE_INVALID=1 df -T >out || fail=1
 test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; }
@@ -118,7 +142,8 @@ test $(grep -c 'virtfs2.*fstype2' <out) -eq 1 || { fail=1; cat out; }
 
 # Ensure that filtering duplicates does not affect -a processing.
 LD_PRELOAD=./k.so df -a >out || fail=1
-test $(wc -l <out) -eq 6 || { fail=1; cat out; }
+total_fs=6; test "$CU_REMOTE_FS" && total_fs=$(expr $total_fs + 3)
+test $(wc -l <out) -eq $total_fs || { fail=1; cat out; }
 # Ensure placeholder "-" values used for the eclipsed "virtfs"
 test $(grep -c 'virtfs *-' <out) -eq 1 || { fail=1; cat out; }