From 1fc080b7c1eac7fa8063273aaae6b80165c17fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Sun, 20 Dec 2015 23:46:05 +0000 Subject: [PATCH 1/4] fts: enable leaf optimization for XFS XFS provides usable dirent.d_type only for DT_DIR, but the noleaf optimization still applies, as confirmed with: test $(($(find . -maxdepth 1 -type d | wc -l) + 1)) = $(stat -c %h .) Enabling this gives significant traversal speedup. Testing with find(1) gives: $ time find/find-before /usr/share >/dev/null real 0m0.410s user 0m0.145s sys 0m0.266s $ time find/find-after /usr/share >/dev/null real 0m0.278s user 0m0.147s sys 0m0.131s * lib/fts.c (leaf_optimization_applies): Add XFS to the white list. Upstream-commit: d459ec6a4f97001a57d9299143ea9a5f6b1f313b Signed-off-by: Kamil Dudka --- gl/lib/fts.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gl/lib/fts.c b/gl/lib/fts.c index f76c015..fb720c0 100644 --- a/gl/lib/fts.c +++ b/gl/lib/fts.c @@ -663,6 +663,7 @@ fts_close (FTS *sp) # define S_MAGIC_TMPFS 0x1021994 # define S_MAGIC_NFS 0x6969 # define S_MAGIC_REISERFS 0x52654973 +# define S_MAGIC_XFS 0x58465342 # define S_MAGIC_PROC 0x9FA0 /* Return false if it is easy to determine the file system type of @@ -718,6 +719,7 @@ leaf_optimization_applies (int dir_fd) /* 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; case S_MAGIC_PROC: -- 2.5.0 From 2f0dddbb01a70b2ae02797b315924de7e06c3d83 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 9 Dec 2015 07:34:56 +0100 Subject: [PATCH 2/4] fts: ensure leaf optimization is used for NFS NFS provides usable dirent.d_type but not necessarily for all entries of large directories. See * lib/fts.c (leaf_optimization_applies): Append NFS on the white list. Upstream-commit: c97b8b9030de7c9a9f9f6d7dcdc3505c6b3f7f98 Signed-off-by: Kamil Dudka --- gl/lib/fts.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gl/lib/fts.c b/gl/lib/fts.c index fb720c0..d2d404f 100644 --- a/gl/lib/fts.c +++ b/gl/lib/fts.c @@ -716,6 +716,11 @@ 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 . */ + 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: -- 2.5.0 From 1328926a705fdb4728c1f255dd368de928736d39 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 25 Sep 2015 16:09:39 +0200 Subject: [PATCH 3/4] 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 @@ -786,6 +786,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 @@ -149,10 +149,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 Date: Fri, 25 Sep 2015 19:13:15 +0200 Subject: [PATCH 4/4] 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