Skip to content

Commit e730558

Browse files
amir73iljankara
authored andcommitted
fsnotify: consistent behavior for parent not watching children
The logic for handling events on child in groups that have a mark on the parent inode, but without FS_EVENT_ON_CHILD flag in the mask is duplicated in several places and inconsistent. Move the logic into the preparation of mark type iterator, so that the parent mark type will be excluded from all mark type iterations in that case. This results in several subtle changes of behavior, hopefully all desired changes of behavior, for example: - Group A has a mount mark with FS_MODIFY in mask - Group A has a mark with ignore mask that does not survive FS_MODIFY and does not watch children on directory D. - Group B has a mark with FS_MODIFY in mask that does watch children on directory D. - FS_MODIFY event on file D/foo should not clear the ignore mask of group A, but before this change it does And if group A ignore mask was set to survive FS_MODIFY: - FS_MODIFY event on file D/foo should be reported to group A on account of the mount mark, but before this change it is wrongly ignored Fixes: 2f02fd3 ("fanotify: fix ignore mask logic for events on child and on dir") Reported-by: Jan Kara <jack@suse.com> Link: https://lore.kernel.org/linux-fsdevel/20220314113337.j7slrb5srxukztje@quack3.lan/ Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20220511190213.831646-3-amir73il@gmail.com
1 parent 14362a2 commit e730558

2 files changed

Lines changed: 20 additions & 24 deletions

File tree

fs/notify/fanotify/fanotify.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
320320
}
321321

322322
fsnotify_foreach_iter_mark_type(iter_info, mark, type) {
323-
/* Apply ignore mask regardless of ISDIR and ON_CHILD flags */
323+
/* Apply ignore mask regardless of mark's ISDIR flag */
324324
marks_ignored_mask |= mark->ignored_mask;
325325

326326
/*
@@ -330,14 +330,6 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
330330
if (event_mask & FS_ISDIR && !(mark->mask & FS_ISDIR))
331331
continue;
332332

333-
/*
334-
* If the event is on a child and this mark is on a parent not
335-
* watching children, don't send it!
336-
*/
337-
if (type == FSNOTIFY_ITER_TYPE_PARENT &&
338-
!(mark->mask & FS_EVENT_ON_CHILD))
339-
continue;
340-
341333
marks_mask |= mark->mask;
342334

343335
/* Record the mark types of this group that matched the event */

fs/notify/fsnotify.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -290,22 +290,15 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
290290
}
291291

292292
if (parent_mark) {
293-
/*
294-
* parent_mark indicates that the parent inode is watching
295-
* children and interested in this event, which is an event
296-
* possible on child. But is *this mark* watching children and
297-
* interested in this event?
298-
*/
299-
if (parent_mark->mask & FS_EVENT_ON_CHILD) {
300-
ret = fsnotify_handle_inode_event(group, parent_mark, mask,
301-
data, data_type, dir, name, 0);
302-
if (ret)
303-
return ret;
304-
}
305-
if (!inode_mark)
306-
return 0;
293+
ret = fsnotify_handle_inode_event(group, parent_mark, mask,
294+
data, data_type, dir, name, 0);
295+
if (ret)
296+
return ret;
307297
}
308298

299+
if (!inode_mark)
300+
return 0;
301+
309302
if (mask & FS_EVENT_ON_CHILD) {
310303
/*
311304
* Some events can be sent on both parent dir and child marks
@@ -422,8 +415,19 @@ static bool fsnotify_iter_select_report_types(
422415
iter_info->report_mask = 0;
423416
fsnotify_foreach_iter_type(type) {
424417
mark = iter_info->marks[type];
425-
if (mark && mark->group == iter_info->current_group)
418+
if (mark && mark->group == iter_info->current_group) {
419+
/*
420+
* FSNOTIFY_ITER_TYPE_PARENT indicates that this inode
421+
* is watching children and interested in this event,
422+
* which is an event possible on child.
423+
* But is *this mark* watching children?
424+
*/
425+
if (type == FSNOTIFY_ITER_TYPE_PARENT &&
426+
!(mark->mask & FS_EVENT_ON_CHILD))
427+
continue;
428+
426429
fsnotify_iter_set_report_type(iter_info, type);
430+
}
427431
}
428432

429433
return true;

0 commit comments

Comments
 (0)