all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
blob 2452d86e7f3abf3f29437af47cd35f6a48d63f13 4151 bytes (raw)
name: gnu/packages/patches/coreutils-tail-handle-kernel-dentry-unlink-race.patch 	 # note: path name is non-authoritative(*)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
 
From 3ba68f9e64fa2eb8af22d510437a0c6441feb5e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
Date: Thu, 2 Jul 2015 08:41:25 +0100
Subject: [PATCH] tail: handle kernel dentry unlink race
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Avoid the intermittent loss of "... has become inaccessible" messages.
That would cause tests/tail-2/assert.sh to fail sometimes,
mainly on uniprocessor systems.

* src/tail.c (tail_forever_inotify): Also monitor IN_DELETE
events on the directory, to avoid a dentry unlink()..open() race,
where the open() on the deleted file was seen to succeed after an,
unlink() and a subsequent IN_ATTRIB, was sent to tail.  Note an
IN_ATTRIB is sent on the monitored file to indicate the change in
number of links, and we can't just use a decrease in the number of
links to determine the file being unlinked, due to the possibility
of the file having multiple links.

Reported by Assaf Gordon and Ludovic Courtès.
Fixes http://bugs.gnu.org/21460
---
 src/tail.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/tail.c b/src/tail.c
index f916d74..2fa0ae0 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)
                 {
@@ -1639,7 +1646,8 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
             }
 
           /* This will be false if only attributes of file change.  */
-          bool new_watch = fspec->wd < 0 || new_wd != fspec->wd;
+          bool new_watch;
+          new_watch = (! deleting) && (fspec->wd < 0 || new_wd != fspec->wd);
 
           if (new_watch)
             {
@@ -1683,7 +1691,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
@@ -1695,6 +1703,14 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
               hash_delete (wd_to_name, fspec);
             }
 
+          /* Note we get IN_ATTRIB for unlink() as st_nlink decrements.
+             The usual path is a close() done in recheck() triggers
+             an IN_DELETE_SELF event as the inode is removed.
+             However sometimes open() will succeed as even though
+             st_nlink is decremented, the dentry (cache) is not updated.
+             Thus we depend on the IN_DELETE event on the directory
+             to trigger processing for the removed file.  */
+
           recheck (fspec, false);
 
           continue;
-- 
2.1.4


debug log:

solving 2452d86 ...
found 2452d86 in https://yhetil.org/guix/871t87c6kn.fsf@dustycloud.org/

applying [1/1] https://yhetil.org/guix/871t87c6kn.fsf@dustycloud.org/
diff --git a/gnu/packages/patches/coreutils-tail-handle-kernel-dentry-unlink-race.patch b/gnu/packages/patches/coreutils-tail-handle-kernel-dentry-unlink-race.patch
new file mode 100644
index 0000000..2452d86

1:46: trailing whitespace.
 
1:48: trailing whitespace.
 
1:50: trailing whitespace.
 
1:52: trailing whitespace.
 
1:71: trailing whitespace.
 
Checking patch gnu/packages/patches/coreutils-tail-handle-kernel-dentry-unlink-race.patch...
Applied patch gnu/packages/patches/coreutils-tail-handle-kernel-dentry-unlink-race.patch cleanly.
warning: squelched 6 whitespace errors
warning: 11 lines add whitespace errors.

index at:
100644 2452d86e7f3abf3f29437af47cd35f6a48d63f13	gnu/packages/patches/coreutils-tail-handle-kernel-dentry-unlink-race.patch

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.