From 850915551f89099b1774fd4531f730d0cfff7498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Thu, 2 Jul 2015 08:41:25 +0100 Subject: [PATCH] tail: avoid kernel dentry unlink race seen on 3.7.10 * src/tail.c (tail_forever_inotify): Also monitor IN_DELETE events on the directory, to avoid a dentry unlink()..open() race seen on OpenSUSE 13.2, where the open() on the deleted file was seen to succeed after an unlink() and a subsequent IN_ATTRIB was sent to tail. Note the IN_ATTRIB is sent on the monitored file to indicate the change in number of links. --- src/tail.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/tail.c b/src/tail.c index c062d40..a9cfe5d 100644 --- a/src/tail.c +++ b/src/tail.c @@ -1429,8 +1429,8 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, /* It's fine to add the same directory more than once. In that case the same watch descriptor is returned. */ f[i].parent_wd = inotify_add_watch (wd, dirlen ? f[i].name : ".", - (IN_CREATE | IN_MOVED_TO - | IN_ATTRIB)); + (IN_CREATE | IN_DELETE + | IN_MOVED_TO | IN_ATTRIB)); f[i].name[dirlen] = prev; @@ -1619,9 +1619,16 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, fspec = &(f[j]); - /* Adding the same inode again will look up any existing wd. */ - int new_wd = inotify_add_watch (wd, f[j].name, inotify_wd_mask); - if (new_wd < 0) + int new_wd = -1; + bool deleting = !! (ev->mask & IN_DELETE); + + if (! deleting) + { + /* Adding the same inode again will look up any existing wd. */ + new_wd = inotify_add_watch (wd, f[j].name, inotify_wd_mask); + } + + if (! deleting && new_wd < 0) { if (errno == ENOSPC || errno == ENOMEM) { @@ -1683,7 +1690,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, if (! fspec) continue; - if (ev->mask & (IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF)) + if (ev->mask & (IN_ATTRIB | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF)) { /* Note for IN_MOVE_SELF (the file we're watching has been clobbered via a rename) we leave the watch -- 2.4.1