# HG changeset patch # User Eric Blake # Date 1310060257 21600 # Node ID 04a9f678e342bbba8b32fdb32b84400c087b83c8 # Parent 335a77ae4731b53bb9d805c0e79823bdbef9226a fts: introduce FTS_NOATIME 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 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 diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-07-08 Eric Blake + + 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 Tests for module 'thread'. diff --git a/lib/fts.c b/lib/fts.c --- a/lib/fts.c +++ b/lib/fts.c @@ -349,7 +349,8 @@ 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) @@ -406,7 +407,8 @@ 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 @@ -1241,10 +1243,11 @@ 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) { @@ -1653,7 +1656,7 @@ 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? diff --git a/lib/fts_.h b/lib/fts_.h --- a/lib/fts_.h +++ b/lib/fts_.h @@ -142,7 +142,9 @@ 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 */