coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

df vs. long-named /dev/disk/by-uuid/... file system device names


From: Jim Meyering
Subject: df vs. long-named /dev/disk/by-uuid/... file system device names
Date: Thu, 29 Dec 2011 15:09:03 +0100

On systems with recent kernel/tools, a symlink from /etc/mtab to
/proc/mounts, and a by-UUID mount (i.e., soon, nearly everyone),
you will see something like the following when running "df -hT":

  Filesystem                                             Type      Size  Used 
Avail Use% Mounted on
  rootfs                                                 rootfs     11G  1.9G  
8.0G  19% /
  udev                                                   devtmpfs  3.8G     0  
3.8G   0% /dev
  tmpfs                                                  tmpfs     774M  376K  
774M   1% /run
  /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7096a2edb66 ext4       11G  1.9G  
8.0G  19% /
  tmpfs                                                  tmpfs     1.6G  8.0K  
1.6G   1% /run/shm
  /dev/sda2                                              ext3      494M   78M  
392M  17% /boot
  /dev/sda5                                              ext4       12G  7.6G  
3.7G  68% /usr
  /dev/sda6                                              ext4      9.9G  6.6G  
2.8G  71% /var

Contrast that with what we're used to seeing (modulo the
two entries mounted on "/", which is a separate problem):

  Filesystem     Type      Size  Used Avail Use% Mounted on
  rootfs         rootfs     11G  1.9G  8.0G  19% /
  udev           devtmpfs  3.8G     0  3.8G   0% /dev
  tmpfs          tmpfs     774M  376K  774M   1% /run
  /dev/sda3      ext4       11G  1.9G  8.0G  19% /
  tmpfs          tmpfs     1.6G  8.0K  1.6G   1% /run/shm
  /dev/sda2      ext3      494M   78M  392M  17% /boot
  /dev/sda5      ext4       12G  7.6G  3.7G  68% /usr
  /dev/sda6      ext4      9.9G  6.6G  2.8G  71% /var

When that long /dev/disk/by-*/... name is merely a symlink
to a much shorter (and often more useful) device name like
"/dev/sda3", and when it's part of a listing of all file systems,
I would much prefer to see only the latter.

I.e., if I explicitly run
"df -hT /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7096a2edb66",
*then*, it's fine -- and expected -- to print to the long name.
It was explicitly given.  However, with no non-option argument,
df should print the shorter name.  Note that performing this
translation at a lower level (via a change to gnulib's mountlist.c)
would make it impossible to distinguish those two cases.

Here's a patch to do that.
It's a little larger than you might expect because of two factors:
  - it modifies each of five get_dev call-points
  - to avoid introducing a leak, it allocates space for dev_name earlier

I hesitated to make this change, because it feels like a kludge that's
working around a misfeature that should be fixed elsewhere.  I'd rather
that the long root device name not appear in the mount listing
(/proc/mounts) in the first place.

If anyone can assure us that this will soon be "fixed" so that we
don't get such entries in /proc/mounts quite so easily, I'll be
happy to defer or drop the patch.


>From a59338b9ca2ed8cbc82bdf3a299c4a664ad113c9 Mon Sep 17 00:00:00 2001
From: Jim Meyering <address@hidden>
Date: Thu, 29 Dec 2011 14:49:00 +0100
Subject: [PATCH] df: work around long-named /dev/disk/by-uuid/... symlinks

On systems with recent kernel/tools, a symlink from /etc/mtab to
/proc/mounts, and a by-UUID mount (i.e., soon, nearly everyone),
you will see something like the following when running "df -hT":
(this has been truncated to fit in a width-limited ChangeLog file)

Filesystem                                             Type      Siz...
rootfs                                                 rootfs     11G
udev                                                   devtmpfs  3.8G
tmpfs                                                  tmpfs     774M
/dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7096a2edb66 ext4       11G
tmpfs                                                  tmpfs     1.6G
/dev/sda2                                              ext3      494M
/dev/sda5                                              ext4       12G
/dev/sda6                                              ext4      9.9G

Contrast that with what we're used to seeing (modulo the
two entries mounted on "/", which is a separate problem):

Filesystem     Type      Size  Used Avail Use% Mounted on
rootfs         rootfs     11G  1.9G  8.0G  19% /
udev           devtmpfs  3.8G     0  3.8G   0% /dev
tmpfs          tmpfs     774M  376K  774M   1% /run
/dev/sda3      ext4       11G  1.9G  8.0G  19% /
tmpfs          tmpfs     1.6G  8.0K  1.6G   1% /run/shm
/dev/sda2      ext3      494M   78M  392M  17% /boot
/dev/sda5      ext4       12G  7.6G  3.7G  68% /usr
/dev/sda6      ext4      9.9G  6.6G  2.8G  71% /var

When that long /dev/disk/by-*/... name is merely a symlink
to a much shorter (and often more useful) device name like
"/dev/sda3", and when it's part of a listing of all file systems,
I would much prefer to see only the latter.

I.e., if I explicitly run
"df -hT /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7096a2edb66",
Then, it's fine -- and expected -- to print to the long name.
It was explicitly given.  However, with no non-option argument,
df should print the shorter name.  Note that performing this
translation at a lower level (via a change to gnulib's mountlist.c)
would make it impossible to distinguish those two cases.

* src/df.c: Include "canonicalize.h".
(get_dev): Add a parameter, telling when to resolve device symlinks
and update all callers.  When true, resolve a symlink name to a
shorter referent.
Reported by Dan Jacobson in http://bugs.gnu.org/10363
---
 src/df.c |   43 +++++++++++++++++++++++++++++++++++--------
 1 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/src/df.c b/src/df.c
index 982d607..516288b 100644
--- a/src/df.c
+++ b/src/df.c
@@ -25,6 +25,7 @@
 #include <assert.h>

 #include "system.h"
+#include "canonicalize.h"
 #include "error.h"
 #include "fsusage.h"
 #include "human.h"
@@ -428,13 +429,16 @@ add_uint_with_neg_flag (uintmax_t *dest, bool *dest_neg,
    If FSTYPE is non-NULL, it is the type of the file system on DISK.
    If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
    not be able to produce statistics in this case.
-   ME_DUMMY and ME_REMOTE are the mount entry flags.  */
+   ME_DUMMY and ME_REMOTE are the mount entry flags.
+   RESOLVE_DEVICE_SYMLINK is true when iterating over all entries, as when
+   df is invoked with no non-option argument.  See below for details.  */

 static void
 get_dev (char const *disk, char const *mount_point,
          char const *stat_file, char const *fstype,
          bool me_dummy, bool me_remote,
-         const struct fs_usage *force_fsu)
+         const struct fs_usage *force_fsu,
+         bool resolve_device_symlink)
 {
   struct fs_usage fsu;
   char buf[LONGEST_HUMAN_READABLE + 2];
@@ -488,6 +492,29 @@ get_dev (char const *disk, char const *mount_point,

   if (! disk)
     disk = "-";                        /* unknown */
+
+  char *dev_name = xstrdup (disk);
+  char *resolved_dev;
+  size_t orig_len = strlen (dev_name);
+
+  /* If dev_name is a long-named symlink like
+     /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 and its
+     canonical name is shorter, use the shorter name.  But don't bother
+     checking when DEV_NAME is no longer than e.g., "/dev/sda1"  */
+  if (resolve_device_symlink && 9 < orig_len
+      && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))
+    {
+      if (strlen (resolved_dev) < orig_len)
+        {
+          free (dev_name);
+          dev_name = resolved_dev;
+        }
+      else
+        {
+          free (resolved_dev);
+        }
+    }
+
   if (! fstype)
     fstype = "-";              /* unknown */

@@ -537,7 +564,7 @@ get_dev (char const *disk, char const *mount_point,
       switch (field)
         {
         case DEV_FIELD:
-          cell = xstrdup (disk);
+          cell = dev_name;
           break;

         case TYPE_FIELD:
@@ -648,7 +675,7 @@ get_disk (char const *disk)
     {
       get_dev (best_match->me_devname, best_match->me_mountdir, NULL,
                best_match->me_type, best_match->me_dummy,
-               best_match->me_remote, NULL);
+               best_match->me_remote, NULL, false);
       return true;
     }

@@ -734,7 +761,7 @@ get_point (const char *point, const struct stat *statp)
   if (best_match)
     get_dev (best_match->me_devname, best_match->me_mountdir, point,
              best_match->me_type, best_match->me_dummy, best_match->me_remote,
-             NULL);
+             NULL, false);
   else
     {
       /* We couldn't find the mount entry corresponding to POINT.  Go ahead and
@@ -745,7 +772,7 @@ get_point (const char *point, const struct stat *statp)
       char *mp = find_mount_point (point, statp);
       if (mp)
         {
-          get_dev (NULL, mp, NULL, NULL, false, false, NULL);
+          get_dev (NULL, mp, NULL, NULL, false, false, NULL, false);
           free (mp);
         }
     }
@@ -774,7 +801,7 @@ get_all_entries (void)

   for (me = mount_list; me; me = me->me_next)
     get_dev (me->me_devname, me->me_mountdir, NULL, me->me_type,
-              me->me_dummy, me->me_remote, NULL);
+             me->me_dummy, me->me_remote, NULL, true);
 }

 /* Add FSTYPE to the list of file system types to display. */
@@ -1066,7 +1093,7 @@ main (int argc, char **argv)
     {
       if (inode_format)
         grand_fsu.fsu_blocks = 1;
-      get_dev ("total", NULL, NULL, NULL, false, false, &grand_fsu);
+      get_dev ("total", NULL, NULL, NULL, false, false, &grand_fsu, false);
     }

   print_table ();
--
1.7.7.3



reply via email to

[Prev in Thread] Current Thread [Next in Thread]