diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/notify/fsnotify.c | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 59dc7a02bd0c..6f2777ce87a1 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -149,8 +149,8 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, | |||
149 | struct fsnotify_event **event) | 149 | struct fsnotify_event **event) |
150 | { | 150 | { |
151 | struct fsnotify_group *group = NULL; | 151 | struct fsnotify_group *group = NULL; |
152 | __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); | 152 | __u32 inode_test_mask = 0; |
153 | __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); | 153 | __u32 vfsmount_test_mask = 0; |
154 | 154 | ||
155 | if (unlikely(!inode_mark && !vfsmount_mark)) { | 155 | if (unlikely(!inode_mark && !vfsmount_mark)) { |
156 | BUG(); | 156 | BUG(); |
@@ -170,12 +170,14 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, | |||
170 | /* does the inode mark tell us to do something? */ | 170 | /* does the inode mark tell us to do something? */ |
171 | if (inode_mark) { | 171 | if (inode_mark) { |
172 | group = inode_mark->group; | 172 | group = inode_mark->group; |
173 | inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); | ||
173 | inode_test_mask &= inode_mark->mask; | 174 | inode_test_mask &= inode_mark->mask; |
174 | inode_test_mask &= ~inode_mark->ignored_mask; | 175 | inode_test_mask &= ~inode_mark->ignored_mask; |
175 | } | 176 | } |
176 | 177 | ||
177 | /* does the vfsmount_mark tell us to do something? */ | 178 | /* does the vfsmount_mark tell us to do something? */ |
178 | if (vfsmount_mark) { | 179 | if (vfsmount_mark) { |
180 | vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); | ||
179 | group = vfsmount_mark->group; | 181 | group = vfsmount_mark->group; |
180 | vfsmount_test_mask &= vfsmount_mark->mask; | 182 | vfsmount_test_mask &= vfsmount_mark->mask; |
181 | vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; | 183 | vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; |
@@ -183,9 +185,12 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, | |||
183 | vfsmount_test_mask &= ~inode_mark->ignored_mask; | 185 | vfsmount_test_mask &= ~inode_mark->ignored_mask; |
184 | } | 186 | } |
185 | 187 | ||
186 | pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" | 188 | pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x inode_mark=%p" |
187 | " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, | 189 | " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" |
188 | mnt, inode_mark, mask, data, data_is, cookie, *event); | 190 | " data=%p data_is=%d cookie=%d event=%p\n", |
191 | __func__, group, to_tell, mnt, mask, inode_mark, | ||
192 | inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, | ||
193 | data_is, cookie, *event); | ||
189 | 194 | ||
190 | if (!inode_test_mask && !vfsmount_test_mask) | 195 | if (!inode_test_mask && !vfsmount_test_mask) |
191 | return 0; | 196 | return 0; |
@@ -214,7 +219,7 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, | |||
214 | int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | 219 | int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, |
215 | const unsigned char *file_name, u32 cookie) | 220 | const unsigned char *file_name, u32 cookie) |
216 | { | 221 | { |
217 | struct hlist_node *inode_node, *vfsmount_node; | 222 | struct hlist_node *inode_node = NULL, *vfsmount_node = NULL; |
218 | struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL; | 223 | struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL; |
219 | struct fsnotify_group *inode_group, *vfsmount_group; | 224 | struct fsnotify_group *inode_group, *vfsmount_group; |
220 | struct fsnotify_event *event = NULL; | 225 | struct fsnotify_event *event = NULL; |
@@ -245,19 +250,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
245 | (test_mask & to_tell->i_fsnotify_mask)) | 250 | (test_mask & to_tell->i_fsnotify_mask)) |
246 | inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first, | 251 | inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first, |
247 | &fsnotify_mark_srcu); | 252 | &fsnotify_mark_srcu); |
248 | else | ||
249 | inode_node = NULL; | ||
250 | 253 | ||
251 | if (mnt) { | 254 | if (mnt && ((mask & FS_MODIFY) || |
252 | if ((mask & FS_MODIFY) || | 255 | (test_mask & mnt->mnt_fsnotify_mask))) { |
253 | (test_mask & mnt->mnt_fsnotify_mask)) | 256 | vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first, |
254 | vfsmount_node = srcu_dereference(mnt->mnt_fsnotify_marks.first, | 257 | &fsnotify_mark_srcu); |
255 | &fsnotify_mark_srcu); | 258 | inode_node = srcu_dereference(to_tell->i_fsnotify_marks.first, |
256 | else | 259 | &fsnotify_mark_srcu); |
257 | vfsmount_node = NULL; | ||
258 | } else { | ||
259 | mnt = NULL; | ||
260 | vfsmount_node = NULL; | ||
261 | } | 260 | } |
262 | 261 | ||
263 | while (inode_node || vfsmount_node) { | 262 | while (inode_node || vfsmount_node) { |