This gives clients the option to try a non-invasive traversal,
where merely visiting a directory does not update its timestamp,
where such is supported by the kernel.
Note that this is best-effort. FTS_NOATIME is silently ignored
on systems that lack O_NOATIME support - it is up to the caller
to decide whether to issue an error when the gnulib replacement
<fcntl.h> defined O_NOATIME to 0, and/or detect older Linux
kernels where O_NOATIME is defined to non-zero but has no effect.
Note that whiteout support and O_NOATIME support are currently
orthogonal: there is no way to get O_NOATIME behavior when using
__opendir2 to visit whiteouts on BSD systems. So far, I don't
know of any system with both __opendir2 and O_NOATIME; if such
a system exists, then fts_build() needs a tweak (then again,
such a system would probably add DTF_NOATIME for __opendir2).
* lib/fts_.h (FTS_NOATIME): New bit flag.
(FTS_OPTIONMASK): Adjust.
* lib/fts.c (diropen, fts_open, fts_build): Honor it.
(fd_ring_check): Debug code unconditionally uses O_NOATIME.
Needed for findutils bug http://savannah.gnu.org/bugs/?33724
Signed-off-by: Eric Blake <eblake@redhat.com>
+2011-07-08 Eric Blake <eblake@redhat.com>
+
+ fts: introduce FTS_NOATIME
+ * lib/fts_.h (FTS_NOATIME): New bit flag.
+ (FTS_OPTIONMASK): Adjust.
+ * lib/fts.c (diropen, fts_open, fts_build): Honor it.
+ (fd_ring_check): Debug code unconditionally uses O_NOATIME.
+
2011-07-08 Bruno Haible <bruno@clisp.org>
Tests for module 'thread'.
2011-07-08 Bruno Haible <bruno@clisp.org>
Tests for module 'thread'.
diropen (FTS const *sp, char const *dir)
{
int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
diropen (FTS const *sp, char const *dir)
{
int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
- | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0));
+ | (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0)
+ | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
int fd = (ISSET (FTS_CWDFD)
? openat (sp->fts_cwd_fd, dir, open_flags)
int fd = (ISSET (FTS_CWDFD)
? openat (sp->fts_cwd_fd, dir, open_flags)
early, doing it here saves us the trouble of ensuring
later (where it'd be messier) that "." can in fact
be opened. If not, revert to FTS_NOCHDIR mode. */
early, doing it here saves us the trouble of ensuring
later (where it'd be messier) that "." can in fact
be opened. If not, revert to FTS_NOCHDIR mode. */
- int fd = open (".", O_SEARCH);
+ int fd = open (".",
+ O_SEARCH | (ISSET (FTS_NOATIME) ? O_NOATIME : 0));
if (fd < 0)
{
/* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
if (fd < 0)
{
/* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
? sp->fts_cwd_fd : AT_FDCWD), \
file, \
opendirat((! ISSET(FTS_NOCHDIR) && ISSET(FTS_CWDFD) \
? sp->fts_cwd_fd : AT_FDCWD), \
file, \
- ((ISSET(FTS_PHYSICAL) \
- && ! (ISSET(FTS_COMFOLLOW) \
- && cur->fts_level == FTS_ROOTLEVEL)) \
- ? O_NOFOLLOW : 0), \
+ (((ISSET(FTS_PHYSICAL) \
+ && ! (ISSET(FTS_COMFOLLOW) \
+ && cur->fts_level == FTS_ROOTLEVEL)) \
+ ? O_NOFOLLOW : 0) \
+ | (ISSET (FTS_NOATIME) ? O_NOATIME : 0)), \
&dir_fd)
#endif
if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
&dir_fd)
#endif
if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
int fd = i_ring_pop (&fd_w);
if (0 <= fd)
{
int fd = i_ring_pop (&fd_w);
if (0 <= fd)
{
- int parent_fd = openat (cwd_fd, "..", O_SEARCH);
+ int parent_fd = openat (cwd_fd, "..", O_SEARCH | O_NOATIME);
if (parent_fd < 0)
{
// Warn?
if (parent_fd < 0)
{
// Warn?
dirent.d_type data. */
# define FTS_DEFER_STAT 0x0400
dirent.d_type data. */
# define FTS_DEFER_STAT 0x0400
-# define FTS_OPTIONMASK 0x07ff /* valid user option mask */
+# define FTS_NOATIME 0x0800 /* use O_NOATIME during traversal */
+
+# define FTS_OPTIONMASK 0x0fff /* valid user option mask */
# define FTS_NAMEONLY 0x1000 /* (private) child names only */
# define FTS_STOP 0x2000 /* (private) unrecoverable error */
# define FTS_NAMEONLY 0x1000 /* (private) child names only */
# define FTS_STOP 0x2000 /* (private) unrecoverable error */