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.
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 c8fb84c38637..9a4cff08c67d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1258,6 +1258,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; + else + clear |= FS_CREATE; + + if (lease_mask & FL_IGN_DIR_DELETE) + set |= FS_DELETE; + else + clear |= FS_DELETE; + + 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; @@ -1266,6 +1297,7 @@ static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp) WARN_ON_ONCE(!fp->fi_delegees); nfsd4_finalize_deleg_timestamps(dp, nf->nf_file); + nfsd_fsnotify_recalc_mask(nf); kernel_setlease(nf->nf_file, F_UNLCK, NULL, (void **)&dp); put_deleg_file(fp); } @@ -9652,6 +9684,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
