Upstream patch for df(1) on top of v8.23, to be removed with v8.24. http://git.sv.gnu.org/cgit/coreutils.git/commit/?id=2e81e6224340 From 2e81e62243409c5c574b899f52b08c000e4d99fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Wed, 29 Oct 2014 02:49:17 +0000 Subject: [PATCH] df: only suppress remote mounts of separate exports with --total * 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 | 8 ++++++++ doc/coreutils.texi | 28 +++++++++++++++------------- src/df.c | 41 ++++++++++++++++++++++++++++------------- tests/df/skip-duplicates.sh | 31 ++++++++++++++++++++++++++++--- 4 files changed, 79 insertions(+), 29 deletions(-) Index: NEWS =================================================================== --- NEWS.orig +++ NEWS @@ -1,5 +1,13 @@ 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] + + * Noteworthy changes in release 8.23 (2014-07-18) [stable] ** Bug fixes Index: doc/coreutils.texi =================================================================== --- doc/coreutils.texi.orig +++ doc/coreutils.texi @@ -11202,19 +11202,6 @@ due to permissions of the mount point et 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 @@ -11355,6 +11342,21 @@ some systems (notably SunOS), doing this 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: src/df.c =================================================================== --- src/df.c.orig +++ 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: tests/df/skip-duplicates.sh =================================================================== --- tests/df/skip-duplicates.sh.orig +++ tests/df/skip-duplicates.sh @@ -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 failur LD_PRELOAD=./k.so df -T >out || fail=1 test $(wc -l out || fail=1 +test "$CU_REMOTE_FS" && elide_remote=1 || elide_remote=0 +test $(wc -l out || fail=1 test $(wc -l out || fail=1 -test $(wc -l