The patch addresses df not showing the root filesystem line (
https://bugzilla.redhat.com/show_bug.cgi?id=887763 ). It's based on
Pádraig Brady's idea of favoring certain patterns
when deduplicating the list of mount entries
( http://lists.gnu.org/archive/html/coreutils/2013-01/msg00080.html ).
Thanks,
Ondrej
>From decfe8df670818aa36637470bc38f221d49704b7 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <[email protected]>
Date: Thu, 24 Jan 2013 17:28:54 +0100
Subject: [PATCH] df: prefer fullpath entries when deduplicating
* src/df.c (struct devlist): Add a new element for storing
pointers to mount_entry structures.
(dev_approved): Check if a device is in the global devlist.
(dev_examine): Renamed from dev_examined, the function now
favors entries with a '/' character in me_devname or those
with the shortest me_mountdir string, if multiple entries
fulfill the first condition.
(get_all_entries): Call dev_examine and dev_approved if
appropriate.
(get_dev): Do not call dev_examined.
* tests/df/skip-duplicates.sh: Add tests.
---
src/df.c | 45 +++++++++++++++++++++++++++++++++++++--------
tests/df/skip-duplicates.sh | 18 ++++++++++++++----
2 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/src/df.c b/src/df.c
index 9523cc1..89bc93f 100644
--- a/src/df.c
+++ b/src/df.c
@@ -48,6 +48,7 @@
struct devlist
{
dev_t dev_num;
+ struct mount_entry *me;
struct devlist *next;
};
@@ -609,24 +610,44 @@ excluded_fstype (const char *fstype)
/* Check if the device was already examined. */
static bool
-dev_examined (char const *mount_dir, char const *devname)
+dev_approved (const struct mount_entry *me)
+{
+ struct devlist *devlist = devlist_head;
+ for ( ; devlist; devlist = devlist->next)
+ if (devlist->me == me)
+ return true;
+
+ return false;
+}
+
+static int
+dev_examine (struct mount_entry *me)
{
struct stat buf;
- if (-1 == stat (mount_dir, &buf))
- return false;
+ if (-1 == stat (me->me_mountdir, &buf))
+ return -1;
struct devlist *devlist = devlist_head;
for ( ; devlist; devlist = devlist->next)
if (devlist->dev_num == buf.st_dev)
- return true;
+ {
+ if ((!strchr (devlist->me->me_devname, '/')
+ && strchr (me->me_devname, '/'))
+ || (strchr (devlist->me->me_devname, '/')
+ && strchr (me->me_devname, '/')
+ && strlen (devlist->me->me_mountdir) > strlen (me->me_mountdir)))
+ devlist->me = me;
+
+ return 0;
+ }
/* Add the device number to the global list devlist. */
devlist = xmalloc (sizeof *devlist);
+ devlist->me = me;
devlist->dev_num = buf.st_dev;
devlist->next = devlist_head;
devlist_head = devlist;
-
- return false;
+ return 0;
}
/* Return true if N is a known integer value. On many file systems,
@@ -803,8 +824,6 @@ get_dev (char const *disk, char const *mount_point,
/* No arguments nor "df -a", then check if df has to ... */
if (!show_rootfs && STREQ (disk, ROOTFS))
return; /* ... skip rootfs: (unless -trootfs is given. */
- if (dev_examined (mount_point, disk))
- return; /* ... skip duplicate entries (bind mounts). */
}
/* If MOUNT_POINT is NULL, then the file system is not mounted, and this
@@ -1133,9 +1152,19 @@ get_all_entries (void)
{
struct mount_entry *me;
+ if (!show_rootfs && !show_all_fs && !show_listed_fs)
+ {
+ for (me = mount_list; me; me = me->me_next)
+ dev_examine (me);
+ }
+
for (me = mount_list; me; me = me->me_next)
+ {
+ if (!show_rootfs && !show_all_fs && !show_listed_fs && !dev_approved (me))
+ continue;
get_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
me->me_dummy, me->me_remote, NULL, true);
+ }
}
/* Add FSTYPE to the list of file system types to display. */
diff --git a/tests/df/skip-duplicates.sh b/tests/df/skip-duplicates.sh
index 31ab014..20f3910 100755
--- a/tests/df/skip-duplicates.sh
+++ b/tests/df/skip-duplicates.sh
@@ -39,10 +39,15 @@ struct mntent *getmntent (FILE *fp)
static struct mntent mntent;
- while (done++ < 3)
+ while (done++ < 4)
{
- mntent.mnt_fsname = "fsname";
- mntent.mnt_dir = "/";
+ /* File system - Mounted on
+ fsname /
+ /fsname /root
+ /fsname /
+ */
+ mntent.mnt_fsname = (done == 2) ? "fsname" : "/fsname";
+ mntent.mnt_dir = (done == 3) ? "/root" : "/";
mntent.mnt_type = "-";
return &mntent;
@@ -65,9 +70,14 @@ test -f x || skip_ "internal test failure: maybe LD_PRELOAD
doesn't work?"
LD_PRELOAD=./k.so df >out || fail=1
test $(wc -l <out) -eq 2 || { 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 '/root'
+test $(grep -c '/root' <out) -eq 0 || { 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 3 || { fail=1; cat out; }
+test $(wc -l <out) -eq 4 || { fail=1; cat out; }
# Ensure that filtering duplcates does not affect
# argument processing (now without the fake getmntent()).
--
1.7.11.7