fsnotify: add fsnotify_modify_mark_mask()

nfsd needs to be able to modify the mask on an existing mark when new
directory delegations are set or unset. Add an exported function that
allows the caller to set and clear bits in the mark->mask, and does
the recalculation if something changed.

Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260428-dir-deleg-v3-6-5a0780ba9def@kernel.org
Acked-by: Jan Kara <jack@suse.cz>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Jeff Layton 2026-04-28 08:09:50 +01:00 committed by Christian Brauner
parent ad4489dcd0
commit 12ffbb117b
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
2 changed files with 30 additions and 0 deletions

View File

@ -310,6 +310,35 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
fsnotify_conn_set_children_dentry_flags(conn);
}
/**
* fsnotify_modify_mark_mask - set and/or clear flags in a mark's mask
* @mark: mark to be modified
* @set: bits to be set in mask
* @clear: bits to be cleared in mask
*
* Modify a fsnotify_mark mask as directed, and update its associated conn.
* The caller is expected to hold a reference to the mark.
*/
void fsnotify_modify_mark_mask(struct fsnotify_mark *mark, u32 set, u32 clear)
{
bool recalc = false;
u32 mask;
WARN_ON_ONCE(clear & set);
spin_lock(&mark->lock);
mask = mark->mask;
mark->mask |= set;
mark->mask &= ~clear;
if (mark->mask != mask)
recalc = true;
spin_unlock(&mark->lock);
if (recalc)
fsnotify_recalc_mask(mark->connector);
}
EXPORT_SYMBOL_GPL(fsnotify_modify_mark_mask);
/* Free all connectors queued for freeing once SRCU period ends */
static void fsnotify_connector_destroy_workfn(struct work_struct *work)
{

View File

@ -917,6 +917,7 @@ extern void fsnotify_get_mark(struct fsnotify_mark *mark);
extern void fsnotify_put_mark(struct fsnotify_mark *mark);
extern void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info);
extern bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info);
extern void fsnotify_modify_mark_mask(struct fsnotify_mark *mark, u32 set, u32 clear);
static inline void fsnotify_init_event(struct fsnotify_event *event)
{