]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
df: use the last device name provided by the system
authorPádraig Brady <P@draigBrady.com>
Thu, 29 May 2014 14:30:46 +0000 (15:30 +0100)
committerPádraig Brady <P@draigBrady.com>
Thu, 29 May 2014 15:01:30 +0000 (16:01 +0100)
The device name reported for a particular mount entry
may no longer be valid if the mount point was subsequently
mounted on a different device.  Therefore honor the order
of the mount list returned by the system and use the last
reported device name.

* src/df.c (filter_mount_list): When discarding the current
mount entry, ensure that a new device name is not also discarded.
* tests/df/skip-duplicates.sh: Add a test case.  Also fix
a false failure in the edge case of a system with only a
single file system.
* NEWS: Mention the fix.

NEWS
src/df.c
tests/df/skip-duplicates.sh

diff --git a/NEWS b/NEWS
index 9679b468431f483faaf1a6b4a3ef64fdfce431e2..3919b7245b6adc426147e07be50755db7365b12c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -44,7 +44,9 @@ GNU coreutils NEWS                                    -*- outline -*-
 
   [These dd bugs were present in "the beginning".]
 
-  df now correctly elides duplicates for virtual file systems like tmpfs.
+  df now elides duplicates for virtual file systems like tmpfs, and will
+  display the correct device name for directories mounted multiple times.
+  [These bugs were present in "the beginning".]
 
   head --bytes=-N and --lines=-N now handles devices more
   consistently, not ignoring data from virtual devices like /dev/zero,
index 01ecca6c52ef53db7cf8cdef3fa499855cbad3ec..82b0c5f378612f8a0c07c2f9d24781b28769f2cc 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -604,7 +604,7 @@ excluded_fstype (const char *fstype)
 }
 
 /* Filter mount list by skipping duplicate entries.
-   In the case of duplicities - based on to the device number - the mount entry
+   In the case of duplicities - based on the device number - the mount entry
    with a '/' in its me_devname (i.e. not pseudo name like tmpfs) wins.
    If both have a real devname (e.g. bind mounts), then that with the shorter
    me_mountdir wins.  */
@@ -638,17 +638,33 @@ filter_mount_list (void)
 
           if (devlist)
             {
-              discard_me = me;
-
               /* ...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 mount entry for existing device.  */
                   discard_me = devlist->me;
                   devlist->me = me;
                 }
+              else
+                {
+                  /* Discard mount entry currently being processed.  */
+                  discard_me = me;
+
+                  /* We might still want the devname from this mount entry as
+                     the dev_num might not correlate with st_dev if another
+                     device is subsequently overmounted at mountdir, so honor
+                     the order of the presented list and replace with the
+                     latest devname encountered.  */
+                  if (! STREQ (devlist->me->me_devname, me->me_devname))
+                    {
+                      free (devlist->me->me_devname);
+                      devlist->me->me_devname = xstrdup (me->me_devname);
+                    }
+                }
+
             }
         }
 
index 44f7d4ca78edbf428f67f2089370f3071978a2cf..6fb6ff561887351538978465782f01015547badf 100755 (executable)
@@ -55,7 +55,7 @@ struct mntent *getmntent (FILE *fp)
     {.mnt_fsname="/fsname", .mnt_dir="/."},
     {.mnt_fsname="/fsname", .mnt_dir="/"},
     {.mnt_fsname="virtfs",  .mnt_dir="/NONROOT"},
-    {.mnt_fsname="virtfs",  .mnt_dir="/NONROOT"},
+    {.mnt_fsname="virtfs2", .mnt_dir="/NONROOT"},
     {.mnt_fsname="netns",   .mnt_dir="net:[1234567]"},
   };
 
@@ -100,9 +100,14 @@ LD_PRELOAD=./k.so CU_TEST_DUPE_INVALID=1 df >out && fail=1
 test $(wc -l <out) -eq $(expr 1 + $unique_entries) || { fail=1; cat out; }
 
 # df should also prefer "/fsname" over "fsname"
-test $(grep -c '/fsname' <out) -eq 1 || { fail=1; cat out; }
-# ... and "/fsname" with '/' as Mounted on over '/.'
-test $(grep -cF '/.' <out) -eq 0 || { fail=1; cat out; }
+if test "$unique_entries" = 2; then
+  test $(grep -c '/fsname' <out) -eq 1 || { fail=1; cat out; }
+  # ... and "/fsname" with '/' as Mounted on over '/.'
+  test $(grep -cF '/.' <out) -eq 0 || { fail=1; cat out; }
+fi
+
+# df should use the last seen devname (mnt_fsname)
+test $(grep -c 'virtfs2' <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