]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
du: avoid to stat all mount points if possible
authorBernhard Voelker <mail@bernhard-voelker.de>
Fri, 18 Sep 2015 11:29:17 +0000 (13:29 +0200)
committerBernhard Voelker <mail@bernhard-voelker.de>
Fri, 18 Sep 2015 11:29:17 +0000 (13:29 +0200)
du calls stat for each mount point at startup.  This would block or
even make du fail if stat for an unrelated mount point hangs.
The result is not needed in the normal case anyway and therefore
should be avoided.  Issue introduced in commit v8.19-2-gcf7e1b5.

* src/du.c (fill_mount_table): Move function up as it's not used ...
(mount_point_in_fts_cycle): ... here, i.e., the DI_MNT set is
initialized and filled only iff FTS has detected a directory cycle.
(main): Remove the initialization and filling of the DI_MNT set here,
and free the DI_MNT set only if it was used.

NEWS
src/du.c

diff --git a/NEWS b/NEWS
index 33414c4ebf1082f5b07137e104107e38153b358b..63574da2d161e9a4e3de98b2ee4e2e631c995a1c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,12 @@ GNU coreutils NEWS                                    -*- outline -*-
   base64 no longer supports hex or oct --wrap parameters,
   thus better supporting decimals with leading zeros.
 
+** Improvements
+
+  du no longer stats all mount points at startup, only doing so
+  upon detection of a directory cycle.
+  [issue introduced in coreutils-8.20]
+
 
 * Noteworthy changes in release 8.24 (2015-07-03) [stable]
 
index 86827f808ebe6abebea3c14fcf2530f22764f740..30378e55281df54e92f7daf984fa1402c7650fa4 100644 (file)
--- a/src/du.c
+++ b/src/du.c
@@ -419,6 +419,33 @@ print_size (const struct duinfo *pdui, const char *string)
   fflush (stdout);
 }
 
+/* Fill the di_mnt set with local mount point dev/ino pairs.  */
+
+static void
+fill_mount_table (void)
+{
+  struct mount_entry *mnt_ent = read_file_system_list (false);
+  while (mnt_ent)
+    {
+      struct mount_entry *mnt_free;
+      if (!mnt_ent->me_remote && !mnt_ent->me_dummy)
+        {
+          struct stat buf;
+          if (!stat (mnt_ent->me_mountdir, &buf))
+            hash_ins (di_mnt, buf.st_ino, buf.st_dev);
+          else
+            {
+              /* Ignore stat failure.  False positives are too common.
+                 E.g., "Permission denied" on /run/user/<name>/gvfs.  */
+            }
+        }
+
+      mnt_free = mnt_ent;
+      mnt_ent = mnt_ent->me_next;
+      free_mount_entry (mnt_free);
+    }
+}
+
 /* This function checks whether any of the directories in the cycle that
    fts detected is a mount point.  */
 
@@ -427,6 +454,16 @@ mount_point_in_fts_cycle (FTSENT const *ent)
 {
   FTSENT const *cycle_ent = ent->fts_cycle;
 
+  if (!di_mnt)
+    {
+      /* Initialize the set of dev,inode pairs.  */
+      di_mnt = di_set_alloc ();
+      if (!di_mnt)
+        xalloc_die ();
+
+      fill_mount_table ();
+    }
+
   while (ent && ent != cycle_ent)
     {
       if (di_set_lookup (di_mnt, ent->fts_statp->st_dev,
@@ -680,33 +717,6 @@ du_files (char **files, int bit_flags)
   return ok;
 }
 
-/* Fill the di_mnt set with local mount point dev/ino pairs.  */
-
-static void
-fill_mount_table (void)
-{
-  struct mount_entry *mnt_ent = read_file_system_list (false);
-  while (mnt_ent)
-    {
-      struct mount_entry *mnt_free;
-      if (!mnt_ent->me_remote && !mnt_ent->me_dummy)
-        {
-          struct stat buf;
-          if (!stat (mnt_ent->me_mountdir, &buf))
-            hash_ins (di_mnt, buf.st_ino, buf.st_dev);
-          else
-            {
-              /* Ignore stat failure.  False positives are too common.
-                 E.g., "Permission denied" on /run/user/<name>/gvfs.  */
-            }
-        }
-
-      mnt_free = mnt_ent;
-      mnt_ent = mnt_ent->me_next;
-      free_mount_entry (mnt_free);
-    }
-}
-
 int
 main (int argc, char **argv)
 {
@@ -1034,13 +1044,6 @@ main (int argc, char **argv)
     xalloc_die ();
 
   /* Initialize the set of dev,inode pairs.  */
-
-  di_mnt = di_set_alloc ();
-  if (!di_mnt)
-    xalloc_die ();
-
-  fill_mount_table ();
-
   di_files = di_set_alloc ();
   if (!di_files)
     xalloc_die ();
@@ -1121,7 +1124,8 @@ main (int argc, char **argv)
 
   argv_iter_free (ai);
   di_set_free (di_files);
-  di_set_free (di_mnt);
+  if (di_mnt)
+    di_set_free (di_mnt);
 
   if (files_from && (ferror (stdin) || fclose (stdin) != 0) && ok)
     error (EXIT_FAILURE, 0, _("error reading %s"), quote (files_from));