Blob Blame History Raw
From 1328926a705fdb4728c1f255dd368de928736d39 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 25 Sep 2015 16:09:39 +0200
Subject: [PATCH 1/3] fts: introduce the FTS_NOLEAF flag

The flag is needed to implement the -noleaf option of find.
* lib/fts.c (link_count_optimize_ok): Implement the FTS_NOLEAF flag.
* lib/fts_.h (FTS_NOLEAF): New macro, shifted conflicting constants.
---
 gl/lib/fts.c  |  4 ++++
 gl/lib/fts_.h | 12 +++++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index d2d404f..808466f 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -788,6 +788,10 @@ link_count_optimize_ok (FTSENT const *p)
   bool opt_ok;
   struct LCO_ent *t2;
 
+  if (ISSET(FTS_NOLEAF))
+    /* leaf optimization explicitly disabled by the FTS_NOLEAF flag */
+    return false;
+
   /* If we're not in CWDFD mode, don't bother with this optimization,
      since the caller is not serious about performance. */
   if (!ISSET(FTS_CWDFD))
diff --git a/gl/lib/fts_.h b/gl/lib/fts_.h
index 63d4b74..f1d519b 100644
--- a/gl/lib/fts_.h
+++ b/gl/lib/fts_.h
@@ -155,10 +155,16 @@ typedef struct {
      from input path names during fts_open initialization.  */
 # define FTS_VERBATIM   0x1000
 
-# define FTS_OPTIONMASK 0x1fff          /* valid user option mask */
+  /* Disable leaf optimization (which eliminates stat() calls during traversal,
+     based on the count of nested directories stored in stat.st_nlink of each
+     directory).  Note that the optimization is by default enabled only for
+     selected file systems, and only if the FTS_CWDFD flag is set.  */
+# define FTS_NOLEAF     0x2000
 
-# define FTS_NAMEONLY   0x2000          /* (private) child names only */
-# define FTS_STOP       0x4000          /* (private) unrecoverable error */
+# define FTS_OPTIONMASK 0x3fff          /* valid user option mask */
+
+# define FTS_NAMEONLY   0x4000          /* (private) child names only */
+# define FTS_STOP       0x8000          /* (private) unrecoverable error */
         int fts_options;                /* fts_open options, global flags */
 
         /* Map a directory's device number to a boolean.  The boolean is
-- 
2.5.0


From c186934e6e37ddadf7511abb9b1045192757618e Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 25 Sep 2015 19:13:15 +0200
Subject: [PATCH 2/3] ftsfind: propagate the -noleaf option to FTS

* find/ftsfind.c (find): Propagate the -noleaf option to FTS.
---
 find/ftsfind.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/find/ftsfind.c b/find/ftsfind.c
index 5159470..e34b672 100644
--- a/find/ftsfind.c
+++ b/find/ftsfind.c
@@ -559,6 +559,9 @@ find (char *arg)
   if (options.stay_on_filesystem)
     ftsoptions |= FTS_XDEV;
 
+  if (options.no_leaf_check)
+    ftsoptions |= FTS_NOLEAF;
+
   p = fts_open (arglist, ftsoptions, NULL);
   if (NULL == p)
     {
-- 
2.5.0


From 2edb6204bab0acb0ef8cdde7499396afd9c66131 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
Date: Mon, 18 Jan 2016 17:29:28 +0000
Subject: [PATCH 3/3] fts: don't unconditionally use leaf optimization for NFS

NFS st_nlink are not accurate on all implementations,
leading to aborts() if that assumption is made.
See <https://bugzilla.redhat.com/1299169>
* lib/fts.c (leaf_optimization_applies): Remove NFS from
the white list, and document the issue.

Upstream-commit: 85717b68b03bf85016c5079fbbf0c8aa2b182ba6
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
 gl/lib/fts.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/gl/lib/fts.c b/gl/lib/fts.c
index 55cd554..6e1eaf5 100644
--- a/gl/lib/fts.c
+++ b/gl/lib/fts.c
@@ -718,22 +718,23 @@ leaf_optimization_applies (int dir_fd)
 
   switch (fs_buf.f_type)
     {
-    case S_MAGIC_NFS:
-      /* NFS provides usable dirent.d_type but not necessarily for all entries
-         of large directories.  See <https://bugzilla.redhat.com/1252549>.  */
-      return true;
-
       /* 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;
 
+      /* Explicitly list here any other file system type for which the
+         optimization is not applicable, but need documentation.  */
+    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>
+         NFS should return true.  However st_nlink values are not accurate on
+         all implementations as per <https://bugzilla.redhat.com/1299169>.  */
+      /* fall through */
     case S_MAGIC_PROC:
-      /* Explicitly listing this or any other file system type for which
-         the optimization is not applicable is not necessary, but we leave
-         it here to document the risk.  Per http://bugs.debian.org/143111,
-         /proc may have bogus stat.st_nlink values.  */
+      /* Per <http://bugs.debian.org/143111> /proc may have
+         bogus stat.st_nlink values.  */
       /* fall through */
     default:
       return false;
-- 
2.5.5