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?= <P@draigBrady.com>
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	2015-03-16 11:48:06.423587945 +0100
+++ NEWS	2015-03-16 11:49:07.680156730 +0100
@@ -9,6 +9,14 @@ GNU coreutils NEWS
   than error messages or values for the wrong file system.
   [These bugs were present in "the beginning".]
 
+** 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.22 (2013-12-13) [stable]
 
 ** Bug fixes
Index: doc/coreutils.texi
===================================================================
--- doc/coreutils.texi.orig	2015-03-16 11:48:02.084689315 +0100
+++ doc/coreutils.texi	2015-03-16 11:48:06.425587898 +0100
@@ -11122,19 +11122,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
@@ -11275,6 +11262,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	2015-03-16 11:48:02.085689291 +0100
+++ src/df.c	2015-03-16 11:48:06.426587875 +0100
@@ -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	2015-03-16 11:48:02.085689291 +0100
+++ tests/df/skip-duplicates.sh	2015-03-16 11:50:40.542986812 +0100
@@ -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)
 
 # Simulate an mtab file to test various cases.
 cat > k.c <<'EOF' || framework_failure_
@@ -40,6 +45,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. */
@@ -57,6 +63,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)
@@ -64,17 +73,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];
     }
 
@@ -96,6 +114,12 @@ test -f x || skip_ "internal test failur
 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; }
@@ -112,7 +136,8 @@ test $(grep -c 'virtfs2.*fstype2' <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; }
 
