Kamil Dudka dd90a0
From 42b0e609390e62a900c0d73de60282c8b0f15121 Mon Sep 17 00:00:00 2001
Kamil Dudka dd90a0
From: Paul Eggert <eggert@cs.ucla.edu>
Kamil Dudka dd90a0
Date: Thu, 5 Apr 2018 08:48:01 -0700
Kamil Dudka dd90a0
Subject: [PATCH 1/2] fts: treat CIFS like NFS
Kamil Dudka dd90a0
Kamil Dudka dd90a0
Problem reported by Kamil Dudka in:
Kamil Dudka dd90a0
https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html
Kamil Dudka dd90a0
* lib/fts.c (S_MAGIC_CIFS): New macro.
Kamil Dudka dd90a0
(dirent_inode_sort_may_be_useful, leaf_optimization):
Kamil Dudka dd90a0
Treat CIFS like NFS.
Kamil Dudka dd90a0
Kamil Dudka dd90a0
Upstream-commit: 2e53df541a30d438859087ed4b5a396e04697b9b
Kamil Dudka dd90a0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
Kamil Dudka dd90a0
---
Kamil Dudka dd90a0
 lib/fts.c | 8 +++++++-
Kamil Dudka dd90a0
 1 file changed, 7 insertions(+), 1 deletion(-)
Kamil Dudka dd90a0
Kamil Dudka dd90a0
diff --git a/lib/fts.c b/lib/fts.c
Kamil Dudka dd90a0
index 8f2595d..0689da6 100644
Kamil Dudka dd90a0
--- a/lib/fts.c
Kamil Dudka dd90a0
+++ b/lib/fts.c
Kamil Dudka dd90a0
@@ -685,6 +685,7 @@ enum leaf_optimization
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
 /* Linux-specific constants from coreutils' src/fs.h */
Kamil Dudka dd90a0
 # define S_MAGIC_AFS 0x5346414F
Kamil Dudka dd90a0
+# define S_MAGIC_CIFS 0xFF534D42
Kamil Dudka dd90a0
 # define S_MAGIC_NFS 0x6969
Kamil Dudka dd90a0
 # define S_MAGIC_PROC 0x9FA0
Kamil Dudka dd90a0
 # define S_MAGIC_REISERFS 0x52654973
Kamil Dudka dd90a0
@@ -792,8 +793,9 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
   switch (filesystem_type (p))
Kamil Dudka dd90a0
     {
Kamil Dudka dd90a0
-    case S_MAGIC_TMPFS:
Kamil Dudka dd90a0
+    case S_MAGIC_CIFS:
Kamil Dudka dd90a0
     case S_MAGIC_NFS:
Kamil Dudka dd90a0
+    case S_MAGIC_TMPFS:
Kamil Dudka dd90a0
       /* On a file system of any of these types, sorting
Kamil Dudka dd90a0
          is unnecessary, and hence wasteful.  */
Kamil Dudka dd90a0
       return false;
Kamil Dudka dd90a0
@@ -827,6 +829,10 @@ leaf_optimization (FTSENT const *p)
Kamil Dudka dd90a0
       /* Although AFS mount points are not counted in st_nlink, they
Kamil Dudka dd90a0
          act like directories.  See <https://bugs.debian.org/143111>.  */
Kamil Dudka dd90a0
       FALLTHROUGH;
Kamil Dudka dd90a0
+    case S_MAGIC_CIFS:
Kamil Dudka dd90a0
+      /* Leaf optimization causes 'find' to abort.  See
Kamil Dudka dd90a0
+         <https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html>.  */
Kamil Dudka dd90a0
+      FALLTHROUGH;
Kamil Dudka dd90a0
     case S_MAGIC_NFS:
Kamil Dudka dd90a0
       /* NFS provides usable dirent.d_type but not necessarily for all entries
Kamil Dudka dd90a0
          of large directories, so as per <https://bugzilla.redhat.com/1252549>
Kamil Dudka dd90a0
-- 
Kamil Dudka dd90a0
2.14.3
Kamil Dudka dd90a0
Kamil Dudka dd90a0
Kamil Dudka dd90a0
From bf96f62507931eb296c5b16d7e46c141ad505a1f Mon Sep 17 00:00:00 2001
Kamil Dudka dd90a0
From: Paul Eggert <eggert@cs.ucla.edu>
Kamil Dudka dd90a0
Date: Wed, 11 Apr 2018 12:50:35 -0700
Kamil Dudka dd90a0
Subject: [PATCH 2/2] fts: fix bug in find across filesystems
Kamil Dudka dd90a0
Kamil Dudka dd90a0
This fixes a bug I introduced last summer.
Kamil Dudka dd90a0
Problem reported by Kamil Dudka in:
Kamil Dudka dd90a0
https://lists.gnu.org/r/bug-gnulib/2018-04/msg00033.html
Kamil Dudka dd90a0
* lib/fts.c (filesystem_type, dirent_inode_sort_may_be_useful)
Kamil Dudka dd90a0
(leaf_optimization):
Kamil Dudka dd90a0
New arg for file descriptor.  All callers changed.
Kamil Dudka dd90a0
(fts_build): Check for whether inodes should be sorted
Kamil Dudka dd90a0
before closing the directory.
Kamil Dudka dd90a0
Kamil Dudka dd90a0
Upstream-commit: 81b8c0d3be98f5a77403599de3d06329b3e7673e
Kamil Dudka dd90a0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
Kamil Dudka dd90a0
---
Kamil Dudka dd90a0
 lib/fts.c | 55 +++++++++++++++++++++++++++++++------------------------
Kamil Dudka dd90a0
 1 file changed, 31 insertions(+), 24 deletions(-)
Kamil Dudka dd90a0
Kamil Dudka dd90a0
diff --git a/lib/fts.c b/lib/fts.c
Kamil Dudka dd90a0
index 0689da6..6420ba1 100644
Kamil Dudka dd90a0
--- a/lib/fts.c
Kamil Dudka dd90a0
+++ b/lib/fts.c
Kamil Dudka dd90a0
@@ -726,11 +726,12 @@ dev_type_compare (void const *x, void const *y)
Kamil Dudka dd90a0
   return ax->st_dev == ay->st_dev;
Kamil Dudka dd90a0
 }
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
-/* Return the file system type of P, or 0 if not known.
Kamil Dudka dd90a0
+/* Return the file system type of P with file descriptor FD, or 0 if not known.
Kamil Dudka dd90a0
+   If FD is negative, P's file descriptor is unavailable.
Kamil Dudka dd90a0
    Try to cache known values.  */
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
 static fsword
Kamil Dudka dd90a0
-filesystem_type (FTSENT const *p)
Kamil Dudka dd90a0
+filesystem_type (FTSENT const *p, int fd)
Kamil Dudka dd90a0
 {
Kamil Dudka dd90a0
   FTS *sp = p->fts_fts;
Kamil Dudka dd90a0
   Hash_table *h = sp->fts_leaf_optimization_works_ht;
Kamil Dudka dd90a0
@@ -756,7 +757,7 @@ filesystem_type (FTSENT const *p)
Kamil Dudka dd90a0
     }
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
   /* Look-up failed.  Query directly and cache the result.  */
Kamil Dudka dd90a0
-  if (fstatfs (p->fts_fts->fts_cwd_fd, &fs_buf) != 0)
Kamil Dudka dd90a0
+  if (fd < 0 || fstatfs (fd, &fs_buf) != 0)
Kamil Dudka dd90a0
     return 0;
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
   if (h)
Kamil Dudka dd90a0
@@ -778,12 +779,12 @@ filesystem_type (FTSENT const *p)
Kamil Dudka dd90a0
   return fs_buf.f_type;
Kamil Dudka dd90a0
 }
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
-/* Return false if it is easy to determine the file system type of the
Kamil Dudka dd90a0
-   directory P, and sorting dirents on inode numbers is known not to
Kamil Dudka dd90a0
-   improve traversal performance with that type of file system.
Kamil Dudka dd90a0
-   Otherwise, return true.  */
Kamil Dudka dd90a0
+/* Return true if sorting dirents on inode numbers is known to improve
Kamil Dudka dd90a0
+   traversal performance for the directory P with descriptor DIR_FD.
Kamil Dudka dd90a0
+   Return false otherwise.  When in doubt, return true.
Kamil Dudka dd90a0
+   DIR_FD is negative if unavailable.  */
Kamil Dudka dd90a0
 static bool
Kamil Dudka dd90a0
-dirent_inode_sort_may_be_useful (FTSENT const *p)
Kamil Dudka dd90a0
+dirent_inode_sort_may_be_useful (FTSENT const *p, int dir_fd)
Kamil Dudka dd90a0
 {
Kamil Dudka dd90a0
   /* Skip the sort only if we can determine efficiently
Kamil Dudka dd90a0
      that skipping it is the right thing to do.
Kamil Dudka dd90a0
@@ -791,7 +792,7 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
Kamil Dudka dd90a0
      while the cost of *not* performing it can be O(N^2) with
Kamil Dudka dd90a0
      a very large constant.  */
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
-  switch (filesystem_type (p))
Kamil Dudka dd90a0
+  switch (filesystem_type (p, dir_fd))
Kamil Dudka dd90a0
     {
Kamil Dudka dd90a0
     case S_MAGIC_CIFS:
Kamil Dudka dd90a0
     case S_MAGIC_NFS:
Kamil Dudka dd90a0
@@ -805,16 +806,17 @@ dirent_inode_sort_may_be_useful (FTSENT const *p)
Kamil Dudka dd90a0
     }
Kamil Dudka dd90a0
 }
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
-/* Given an FTS entry P for a directory D,
Kamil Dudka dd90a0
+/* Given an FTS entry P for a directory with descriptor DIR_FD,
Kamil Dudka dd90a0
    return true if it is both useful and valid to apply leaf optimization.
Kamil Dudka dd90a0
    The optimization is useful only for file systems that lack usable
Kamil Dudka dd90a0
    dirent.d_type info.  The optimization is valid if an st_nlink value
Kamil Dudka dd90a0
    of at least MIN_DIR_NLINK is an upper bound on the number of
Kamil Dudka dd90a0
-   subdirectories of D, counting "." and ".."  as subdirectories.  */
Kamil Dudka dd90a0
+   subdirectories of D, counting "." and ".."  as subdirectories.
Kamil Dudka dd90a0
+   DIR_FD is negative if unavailable.  */
Kamil Dudka dd90a0
 static enum leaf_optimization
Kamil Dudka dd90a0
-leaf_optimization (FTSENT const *p)
Kamil Dudka dd90a0
+leaf_optimization (FTSENT const *p, int dir_fd)
Kamil Dudka dd90a0
 {
Kamil Dudka dd90a0
-  switch (filesystem_type (p))
Kamil Dudka dd90a0
+  switch (filesystem_type (p, dir_fd))
Kamil Dudka dd90a0
     {
Kamil Dudka dd90a0
       /* List here the file system types that may lack usable dirent.d_type
Kamil Dudka dd90a0
          info, yet for which the optimization does apply.  */
Kamil Dudka dd90a0
@@ -851,12 +853,13 @@ leaf_optimization (FTSENT const *p)
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
 #else
Kamil Dudka dd90a0
 static bool
Kamil Dudka dd90a0
-dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED)
Kamil Dudka dd90a0
+dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED,
Kamil Dudka dd90a0
+                                 int dir_fd _GL_UNUSED)
Kamil Dudka dd90a0
 {
Kamil Dudka dd90a0
   return true;
Kamil Dudka dd90a0
 }
Kamil Dudka dd90a0
 static enum leaf_optimization
Kamil Dudka dd90a0
-leaf_optimization (FTSENT const *p _GL_UNUSED)
Kamil Dudka dd90a0
+leaf_optimization (FTSENT const *p _GL_UNUSED, int dir_fd _GL_UNUSED)
Kamil Dudka dd90a0
 {
Kamil Dudka dd90a0
   return NO_LEAF_OPTIMIZATION;
Kamil Dudka dd90a0
 }
Kamil Dudka dd90a0
@@ -1050,7 +1053,7 @@ check_for_dir:
Kamil Dudka dd90a0
                         if (parent->fts_n_dirs_remaining == 0
Kamil Dudka dd90a0
                             && ISSET(FTS_NOSTAT)
Kamil Dudka dd90a0
                             && ISSET(FTS_PHYSICAL)
Kamil Dudka dd90a0
-                            && (leaf_optimization (parent)
Kamil Dudka dd90a0
+                            && (leaf_optimization (parent, sp->fts_cwd_fd)
Kamil Dudka dd90a0
                                 == NOSTAT_LEAF_OPTIMIZATION))
Kamil Dudka dd90a0
                           {
Kamil Dudka dd90a0
                             /* nothing more needed */
Kamil Dudka dd90a0
@@ -1335,6 +1338,7 @@ fts_build (register FTS *sp, int type)
Kamil Dudka dd90a0
         int dir_fd;
Kamil Dudka dd90a0
         FTSENT *cur = sp->fts_cur;
Kamil Dudka dd90a0
         bool continue_readdir = !!cur->fts_dirp;
Kamil Dudka dd90a0
+        bool sort_by_inode = false;
Kamil Dudka dd90a0
         size_t max_entries;
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
         /* When cur->fts_dirp is non-NULL, that means we should
Kamil Dudka dd90a0
@@ -1428,7 +1432,7 @@ fts_build (register FTS *sp, int type)
Kamil Dudka dd90a0
                        && ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL)
Kamil Dudka dd90a0
                              && ! ISSET (FTS_SEEDOT)
Kamil Dudka dd90a0
                              && cur->fts_statp->st_nlink == MIN_DIR_NLINK
Kamil Dudka dd90a0
-                             && (leaf_optimization (cur)
Kamil Dudka dd90a0
+                             && (leaf_optimization (cur, dir_fd)
Kamil Dudka dd90a0
                                  != NO_LEAF_OPTIMIZATION)));
Kamil Dudka dd90a0
             if (descend || type == BREAD)
Kamil Dudka dd90a0
               {
Kamil Dudka dd90a0
@@ -1589,6 +1593,15 @@ mem1:                           saved_errno = errno;
Kamil Dudka dd90a0
                         tail->fts_link = p;
Kamil Dudka dd90a0
                         tail = p;
Kamil Dudka dd90a0
                 }
Kamil Dudka dd90a0
+
Kamil Dudka dd90a0
+                /* If there are many entries, no sorting function has been
Kamil Dudka dd90a0
+                   specified, and this file system is of a type that may be
Kamil Dudka dd90a0
+                   slow with a large number of entries, arrange to sort the
Kamil Dudka dd90a0
+                   directory entries on increasing inode numbers.  */
Kamil Dudka dd90a0
+                if (nitems == _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
Kamil Dudka dd90a0
+                    && !sp->fts_compar)
Kamil Dudka dd90a0
+                  sort_by_inode = dirent_inode_sort_may_be_useful (cur, dir_fd);
Kamil Dudka dd90a0
+
Kamil Dudka dd90a0
                 ++nitems;
Kamil Dudka dd90a0
                 if (max_entries <= nitems) {
Kamil Dudka dd90a0
                         /* When there are too many dir entries, leave
Kamil Dudka dd90a0
@@ -1646,13 +1659,7 @@ mem1:                           saved_errno = errno;
Kamil Dudka dd90a0
                 return (NULL);
Kamil Dudka dd90a0
         }
Kamil Dudka dd90a0
 
Kamil Dudka dd90a0
-        /* If there are many entries, no sorting function has been specified,
Kamil Dudka dd90a0
-           and this file system is of a type that may be slow with a large
Kamil Dudka dd90a0
-           number of entries, then sort the directory entries on increasing
Kamil Dudka dd90a0
-           inode numbers.  */
Kamil Dudka dd90a0
-        if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD
Kamil Dudka dd90a0
-            && !sp->fts_compar
Kamil Dudka dd90a0
-            && dirent_inode_sort_may_be_useful (cur)) {
Kamil Dudka dd90a0
+        if (sort_by_inode) {
Kamil Dudka dd90a0
                 sp->fts_compar = fts_compare_ino;
Kamil Dudka dd90a0
                 head = fts_sort (sp, head, nitems);
Kamil Dudka dd90a0
                 sp->fts_compar = NULL;
Kamil Dudka dd90a0
-- 
Kamil Dudka dd90a0
2.14.3
Kamil Dudka dd90a0