bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 5/6] fts: three levels of leaf optimization


From: Paul Eggert
Subject: [PATCH 5/6] fts: three levels of leaf optimization
Date: Tue, 25 Jul 2017 00:28:05 -0700

* lib/fts.c (enum leaf_optimization): New type with three values.
(S_MAGIC_AFS): New macro.  Sort them.
(leaf_optimization): Rename from leaf_optimization_applies, and
return enum leaf_optimization instead of bool.  All uses changed.
Add cases for unknown type and for AFS.
(fts_build): Don’t rely on link counts if NO_LEAF_OPTIMIZATION.
---
 ChangeLog |  8 ++++++++
 lib/fts.c | 54 +++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2c194327d..cbe4c9e27 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2017-07-24  Paul Eggert  <address@hidden>
 
+       fts: three levels of leaf optimization
+       * lib/fts.c (enum leaf_optimization): New type with three values.
+       (S_MAGIC_AFS): New macro.  Sort them.
+       (leaf_optimization): Rename from leaf_optimization_applies, and
+       return enum leaf_optimization instead of bool.  All uses changed.
+       Add cases for unknown type and for AFS.
+       (fts_build): Don’t rely on link counts if NO_LEAF_OPTIMIZATION.
+
        fts: cache dirent_inode_sort_may_be_useful too
        * lib/fts.c (struct dev_type): New struct.
        (DEV_TYPE_HT_INITIAL_SIZE): New constant.
diff --git a/lib/fts.c b/lib/fts.c
index a8de3f910..663a09b5e 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -672,17 +672,32 @@ fts_close (FTS *sp)
    "..").  */
 enum { MIN_DIR_NLINK = 2 };
 
+/* Whether leaf optimization is OK for a directory.  */
+enum leaf_optimization
+  {
+    /* st_nlink is not reliable for this directory's subdirectories.  */
+    NO_LEAF_OPTIMIZATION,
+
+    /* Leaf optimization is OK, but is not useful for avoiding stat calls.  */
+    OK_LEAF_OPTIMIZATION,
+
+    /* Leaf optimization is not only OK: it is useful for avoiding
+       stat calls, because dirent.d_type does not work.  */
+    NOSTAT_LEAF_OPTIMIZATION
+  };
+
 #if defined __linux__ \
   && HAVE_SYS_VFS_H && HAVE_FSTATFS && HAVE_STRUCT_STATFS_F_TYPE
 
 # include <sys/vfs.h>
 
 /* Linux-specific constants from coreutils' src/fs.h */
-# define S_MAGIC_TMPFS 0x1021994
+# define S_MAGIC_AFS 0x5346414F
 # define S_MAGIC_NFS 0x6969
+# define S_MAGIC_PROC 0x9FA0
 # define S_MAGIC_REISERFS 0x52654973
+# define S_MAGIC_TMPFS 0x1021994
 # define S_MAGIC_XFS 0x58465342
-# define S_MAGIC_PROC 0x9FA0
 
 /* Map a stat.st_dev number to a file system type number f_ftype.  */
 struct dev_type
@@ -796,22 +811,24 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
    dirent.d_type info.  The optimization is valid if an st_nlink value
    of at least MIN_DIR_NLINK is an upper bound on the number of
    subdirectories of D, counting "." and ".."  as subdirectories.  */
-static bool
-leaf_optimization_applies (FTSENT const *p)
+static enum leaf_optimization
+leaf_optimization (FTSENT const *p)
 {
-  /* FIXME: do we need to detect AFS mount points?  I doubt it,
-     unless fstatfs can report S_MAGIC_REISERFS for such a directory.  */
-
   switch (filesystem_type (p))
     {
       /* List here the file system types that lack usable dirent.d_type
          info, yet for which the optimization does apply.  */
     case S_MAGIC_REISERFS:
     case S_MAGIC_XFS:
-      return true;
+      return NOSTAT_LEAF_OPTIMIZATION;
 
-      /* Explicitly list here any other file system type for which the
-         optimization is not applicable, but need documentation.  */
+    case 0:
+      /* Leaf optimization is unsafe if the file system type is unknown.  */
+      FALLTHROUGH;
+    case S_MAGIC_AFS:
+      /* Although AFS mount points are not counted in st_nlink, they
+         act like directories.  See <https://bugs.debian.org/143111>.  */
+      FALLTHROUGH;
     case S_MAGIC_NFS:
       /* NFS provides usable dirent.d_type but not necessarily for all entries
          of large directories, so as per <https://bugzilla.redhat.com/1252549>
@@ -821,9 +838,10 @@ leaf_optimization_applies (FTSENT const *p)
     case S_MAGIC_PROC:
       /* Per <http://bugs.debian.org/143111> /proc may have
          bogus stat.st_nlink values.  */
-      FALLTHROUGH;
+      return NO_LEAF_OPTIMIZATION;
+
     default:
-      return false;
+      return OK_LEAF_OPTIMIZATION;
     }
 }
 
@@ -833,10 +851,10 @@ dirent_inode_sort_may_be_useful (FTSENT const *p 
_GL_UNUSED)
 {
   return true;
 }
-static bool
-leaf_optimization_applies (FTSENT const *p _GL_UNUSED)
+static enum leaf_optimization
+leaf_optimization (FTSENT const *p _GL_UNUSED)
 {
-  return false;
+  return NO_LEAF_OPTIMIZATION;
 }
 #endif
 
@@ -1028,7 +1046,8 @@ check_for_dir:
                         if (parent->fts_n_dirs_remaining == 0
                             && ISSET(FTS_NOSTAT)
                             && ISSET(FTS_PHYSICAL)
-                            && leaf_optimization_applies (parent))
+                            && (leaf_optimization (parent)
+                                == NOSTAT_LEAF_OPTIMIZATION))
                           {
                             /* nothing more needed */
                           }
@@ -1387,7 +1406,8 @@ fts_build (register FTS *sp, int type)
                 nlinks = 0;
                 /* Be quiet about nostat, GCC. */
                 nostat = false;
-        } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+        } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)
+                   && leaf_optimization (cur) != NO_LEAF_OPTIMIZATION) {
                 nlinks = (cur->fts_statp->st_nlink
                           - (ISSET (FTS_SEEDOT) ? 0 : MIN_DIR_NLINK));
                 nostat = true;
-- 
2.13.3




reply via email to

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