Add a new helper function that will update the mask on the nfsd_file's fsnotify_mark to be a union of all current directory delegations on an inode. Call that when directory delegations are added or removed.
Reviewed-by: Jan Kara <[email protected]> Signed-off-by: Jeff Layton <[email protected]> --- fs/nfsd/nfs4state.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index bd7e4f9cdaa5..6adce94e9fdb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1260,6 +1260,37 @@ static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct f } } +static void nfsd_fsnotify_recalc_mask(struct nfsd_file *nf) +{ + struct fsnotify_mark *mark = &nf->nf_mark->nfm_mark; + struct inode *inode = file_inode(nf->nf_file); + u32 lease_mask, set = 0, clear = 0; + + /* This is only needed when adding or removing dir delegs */ + if (!S_ISDIR(inode->i_mode)) + return; + + /* Set up notifications for any ignored delegation events */ + lease_mask = inode_lease_ignore_mask(inode); + + if (lease_mask & FL_IGN_DIR_CREATE) + set |= FS_CREATE | FS_MOVED_TO; + else + clear |= FS_CREATE | FS_MOVED_TO; + + if (lease_mask & FL_IGN_DIR_DELETE) + set |= FS_DELETE | FS_MOVED_FROM; + else + clear |= FS_DELETE | FS_MOVED_FROM; + + if (lease_mask & FL_IGN_DIR_RENAME) + set |= FS_RENAME; + else + clear |= FS_RENAME; + + fsnotify_modify_mark_mask(mark, set, clear); +} + static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp) { struct nfs4_file *fp = dp->dl_stid.sc_file; @@ -1269,6 +1300,7 @@ static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp) nfsd4_finalize_deleg_timestamps(dp, nf->nf_file); kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp); + nfsd_fsnotify_recalc_mask(nf); put_deleg_file(fp); } @@ -9674,6 +9706,7 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate, if (!status) { put_nfs4_file(fp); + nfsd_fsnotify_recalc_mask(nf); return dp; } -- 2.53.0
