Skip to content

Commit

Permalink
fts: remove NOSTAT_LEAF_OPTIMIZATION
Browse files Browse the repository at this point in the history
It caused ‘find’ and ‘du’ to dump core, and it was useful
only for obsolescent Linux filesystems anyway.  Problem reported in:
https://lists.gnu.org/r/bug-gnulib/2020-04/msg00068.html
Quite possibly there is still a serious underlying fts bug with
tight-loop-check and mutating file systems, but if so this patch
should cause the bug to be triggered less often.
* lib/fts.c (enum leaf_optimization): Remove
NOSTAT_LEAF_OPTIMIZATION, as it’s problematic.
(S_MAGIC_REISERFS, S_MAGIC_XFS): Remove; no longer needed.
(leaf_optimization): Remove special cases for ReiserFS and XFS.
(fts_read): Remove NOSTAT_LEAF_OPTIMIZATION code.
* lib/fts_.h (struct _ftsent.fts_n_dirs_remaining):
Remove.  All uses removed.
  • Loading branch information
eggert committed Apr 16, 2020
1 parent 2d665c8 commit 47bf2cf
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 53 deletions.
17 changes: 17 additions & 0 deletions ChangeLog
@@ -1,3 +1,20 @@
2020-04-15 Paul Eggert <eggert@cs.ucla.edu>

fts: remove NOSTAT_LEAF_OPTIMIZATION
It caused ‘find’ and ‘du’ to dump core, and it was useful
only for obsolescent Linux filesystems anyway. Problem reported in:
https://lists.gnu.org/r/bug-gnulib/2020-04/msg00068.html
Quite possibly there is still a serious underlying fts bug with
tight-loop-check and mutating file systems, but if so this patch
should cause the bug to be triggered less often.
* lib/fts.c (enum leaf_optimization): Remove
NOSTAT_LEAF_OPTIMIZATION, as it’s problematic.
(S_MAGIC_REISERFS, S_MAGIC_XFS): Remove; no longer needed.
(leaf_optimization): Remove special cases for ReiserFS and XFS.
(fts_read): Remove NOSTAT_LEAF_OPTIMIZATION code.
* lib/fts_.h (struct _ftsent.fts_n_dirs_remaining):
Remove. All uses removed.

2020-04-13 Bastien Roucariès <rouca@debian.org>

explicit_bzero: Improve code style.
Expand Down
56 changes: 8 additions & 48 deletions lib/fts.c
Expand Up @@ -445,7 +445,6 @@ fts_open (char * const *argv,
if ((parent = fts_alloc(sp, "", 0)) == NULL)
goto mem2;
parent->fts_level = FTS_ROOTPARENTLEVEL;
parent->fts_n_dirs_remaining = -1;
}

/* The classic fts implementation would call fts_stat with
Expand Down Expand Up @@ -634,9 +633,8 @@ fts_close (FTS *sp)
}

/* Minimum link count of a traditional Unix directory. When leaf
optimization is OK and MIN_DIR_NLINK <= st_nlink, then st_nlink is
an upper bound on the number of subdirectories (counting "." and
".."). */
optimization is OK and a directory's st_nlink == MIN_DIR_NLINK,
then the directory has no subdirectories. */
enum { MIN_DIR_NLINK = 2 };

/* Whether leaf optimization is OK for a directory. */
Expand All @@ -645,12 +643,8 @@ 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
/* st_nlink == 2 means the directory lacks subdirectories. */
OK_LEAF_OPTIMIZATION
};

#if (defined __linux__ || defined __ANDROID__) \
Expand All @@ -663,9 +657,7 @@ enum leaf_optimization
# define S_MAGIC_CIFS 0xFF534D42
# 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

# ifdef HAVE___FSWORD_T
typedef __fsword_t fsword;
Expand Down Expand Up @@ -782,23 +774,15 @@ dirent_inode_sort_may_be_useful (FTSENT const *p, int dir_fd)
}

/* Given an FTS entry P for a directory with descriptor DIR_FD,
return true if it is both useful and valid to apply leaf optimization.
The optimization is useful only for file systems that lack usable
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.
return whether it is valid to apply leaf optimization.
The optimization is valid if a directory's st_nlink value equal
to MIN_DIR_NLINK means the directory has no subdirectories.
DIR_FD is negative if unavailable. */
static enum leaf_optimization
leaf_optimization (FTSENT const *p, int dir_fd)
{
switch (filesystem_type (p, dir_fd))
{
/* List here the file system types that may lack usable dirent.d_type
info, yet for which the optimization does apply. */
case S_MAGIC_REISERFS:
case S_MAGIC_XFS: /* XFS lacked it until 2013-08-22 commit. */
return NOSTAT_LEAF_OPTIMIZATION;

case 0:
/* Leaf optimization is unsafe if the file system type is unknown. */
FALLTHROUGH;
Expand Down Expand Up @@ -1023,26 +1007,7 @@ name: t = sp->fts_path + NAPPEND(p->fts_parent);
if (p->fts_info == FTS_NSOK)
{
if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
{
FTSENT *parent = p->fts_parent;
if (parent->fts_n_dirs_remaining == 0
&& ISSET(FTS_NOSTAT)
&& ISSET(FTS_PHYSICAL)
&& (leaf_optimization (parent, sp->fts_cwd_fd)
== NOSTAT_LEAF_OPTIMIZATION))
{
/* nothing more needed */
}
else
{
p->fts_info = fts_stat(sp, p, false);
if (S_ISDIR(p->fts_statp->st_mode)
&& p->fts_level != FTS_ROOTLEVEL
&& 0 < parent->fts_n_dirs_remaining
&& parent->fts_n_dirs_remaining != (nlink_t) -1)
parent->fts_n_dirs_remaining--;
}
}
p->fts_info = fts_stat(sp, p, false);
else
fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED);
}
Expand Down Expand Up @@ -1826,11 +1791,6 @@ err: memset(sbp, 0, sizeof(struct stat));
}

if (S_ISDIR(sbp->st_mode)) {
p->fts_n_dirs_remaining
= ((sbp->st_nlink < MIN_DIR_NLINK
|| p->fts_level <= FTS_ROOTLEVEL)
? -1
: sbp->st_nlink - (ISSET (FTS_SEEDOT) ? 0 : MIN_DIR_NLINK));
if (ISDOT(p->fts_name)) {
/* Command-line "." and ".." are real directories. */
return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);
Expand Down
5 changes: 0 additions & 5 deletions lib/fts_.h
Expand Up @@ -219,11 +219,6 @@ typedef struct _ftsent {

size_t fts_namelen; /* strlen(fts_name) */

/* If not (nlink_t) -1, an upper bound on the number of
remaining subdirectories of interest. If this becomes
zero, some work can be avoided. */
nlink_t fts_n_dirs_remaining;

# define FTS_D 1 /* preorder directory */
# define FTS_DC 2 /* directory that causes cycles */
# define FTS_DEFAULT 3 /* none of the above */
Expand Down

0 comments on commit 47bf2cf

Please sign in to comment.