With fanotify_init() flags FAN_REPORT_FID_NAME, when adding an inode mark with FS_EVENT_ON_CHILD, events are reported with fid of the parent and the name of the child entry. When adding a filesystem or mount mark, report events that are "possible on child" (e.g. open/close) in two flavors, one with just the child fid and one also with the parent fid and the child entry name, as if all directories are interested in events "on child". The flag FAN_EVENT_ON_CHILD was always ignored for sb/mount mark, so we can safely ignore the value of the flag passed by the user and set the flag in sb/mount mark mask depending on the FAN_REPORT_NAME group flag. Cc: <linux-api@xxxxxxxxxxxxxxx> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/notify/fanotify/fanotify.c | 7 +++++-- fs/notify/fanotify/fanotify_user.c | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index e91a8cc1b83c..ec42c721850c 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -244,10 +244,13 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, /* * If the event is for a child and this mark doesn't care about * events on a child, don't send it! + * An event "on child" without name info is not intended for a + * mount/sb mark. */ if (event_mask & FS_EVENT_ON_CHILD && - (type != FSNOTIFY_OBJ_TYPE_INODE || - !(mark->mask & FS_EVENT_ON_CHILD))) + (!(mark->mask & FS_EVENT_ON_CHILD) || + (type != FSNOTIFY_OBJ_TYPE_INODE && + !FAN_GROUP_FLAG(group, FAN_REPORT_NAME)))) continue; marks_mask |= mark->mask; diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 36c1327b32f4..89c0554da90e 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -1150,8 +1150,20 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, inode = path.dentry->d_inode; } else { mnt = path.mnt; - /* Mask out FAN_EVENT_ON_CHILD flag for sb/mount marks */ - mask &= ~FAN_EVENT_ON_CHILD; + /* + * So far, flag FAN_EVENT_ON_CHILD was ignored for sb/mount + * marks. Reporting events "on child" with name info for + * sb/mount marks is now implemented, so explicitly mask out + * the flag for backward compatibility with existing programs + * that do not request events with name info. + * On sb/mount mark events with FAN_REPORT_NAME, events are + * reported as if all directories are interested in events + * "on child". + */ + if (FAN_GROUP_FLAG(group, FAN_REPORT_NAME)) + mask |= FAN_EVENT_ON_CHILD; + else + mask &= ~FAN_EVENT_ON_CHILD; } /* create/update an inode mark */ -- 2.17.1