Handle FAN_MARK_IGNORED_SURV_MODIFY flag change in a helper that is called after updating the mark mask. Move recalc of object mask inside fanotify_mark_add_to_mask() which makes the code a bit simpler to follow. Add also helper to translate fsnotify mark flags to user visible fanotify mark flags. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/notify/fanotify/fanotify_user.c | 41 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index bf72856da42e..d8d44a5b37e3 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -1081,42 +1081,48 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, flags, umask); } -static void fanotify_mark_add_ignored_mask(struct fsnotify_mark *fsn_mark, - __u32 mask, unsigned int flags, - __u32 *removed) +static int fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark, + unsigned int flags, bool *recalc) { - fsn_mark->ignored_mask |= mask; - /* * Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time may lead to * the removal of the FS_MODIFY bit in calculated mask if it was set * because of an ignored mask that is now going to survive FS_MODIFY. */ if ((flags & FAN_MARK_IGNORED_SURV_MODIFY) && + (flags & FAN_MARK_IGNORED_MASK) && !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) { fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; if (!(fsn_mark->mask & FS_MODIFY)) - *removed = FS_MODIFY; + *recalc = true; } + + return 0; } -static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, - __u32 mask, unsigned int flags, - __u32 *removed) +static int fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, + __u32 mask, unsigned int flags) { - __u32 oldmask, newmask; + bool recalc = false; + int ret; spin_lock(&fsn_mark->lock); - oldmask = fsnotify_calc_mask(fsn_mark); if (!(flags & FAN_MARK_IGNORED_MASK)) { fsn_mark->mask |= mask; } else { - fanotify_mark_add_ignored_mask(fsn_mark, mask, flags, removed); + fsn_mark->ignored_mask |= mask; } - newmask = fsnotify_calc_mask(fsn_mark); + + recalc = fsnotify_calc_mask(fsn_mark) & + ~fsnotify_conn_mask(fsn_mark->connector); + + ret = fanotify_mark_update_flags(fsn_mark, flags, &recalc); spin_unlock(&fsn_mark->lock); - return newmask & ~oldmask; + if (recalc) + fsnotify_recalc_mask(fsn_mark->connector); + + return ret; } static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, @@ -1174,8 +1180,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, __kernel_fsid_t *fsid) { struct fsnotify_mark *fsn_mark; - __u32 added, removed = 0; - int ret = 0; + int ret; mutex_lock(&group->mark_mutex); fsn_mark = fsnotify_find_mark(connp, group); @@ -1197,9 +1202,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, goto out; } - added = fanotify_mark_add_to_mask(fsn_mark, mask, flags, &removed); - if (removed || (added & ~fsnotify_conn_mask(fsn_mark->connector))) - fsnotify_recalc_mask(fsn_mark->connector); + ret = fanotify_mark_add_to_mask(fsn_mark, mask, flags); out: mutex_unlock(&group->mark_mutex); -- 2.35.1