NFSv4 need to close a file completely (no lingering open) when it does a CLOSE or DELEGRETURN. When multiple NFSv4/OPEN from different clients, we need to check the reference count. The flowing reference-count-check change the behavior of NFSv3 nfsd_rename()/nfsd_unlink() too. Link: https://bugzilla.linux-nfs.org/show_bug.cgi?id=387 Signed-off-by: Wang Yugui <wangyugui@xxxxxxxxxxxx> --- TO-CHECK: 1) NFSv3 nfsd_rename()/nfsd_unlink() feature change is OK? 2) Can we do better performance than nfsd_file_close_inode_sync()? 3) nfsd_file_close_inode_sync()->nfsd_file_close_inode() in nfsd4_delegreturn() => 'Text file busy' about 4s 4) reference-count-check : refcount_read(&nf->nf_ref) <= 1 or ==0? nfsd_file_alloc() refcount_set(&nf->nf_ref, 1); fs/nfsd/filecache.c | 2 +- fs/nfsd/nfs4state.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 9cb2d590c036..8890a8fa7402 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -512,7 +512,7 @@ __nfsd_file_close_inode(struct inode *inode, unsigned int hashval, spin_lock(&nfsd_file_hashtbl[hashval].nfb_lock); hlist_for_each_entry_safe(nf, tmp, &nfsd_file_hashtbl[hashval].nfb_head, nf_node) { - if (inode == nf->nf_inode) + if (inode == nf->nf_inode && refcount_read(&nf->nf_ref) <= 1) nfsd_file_unhash_and_release_locked(nf, dispose); } spin_unlock(&nfsd_file_hashtbl[hashval].nfb_lock); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9409a0dc1b76..be4b480f5914 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -6673,6 +6673,8 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, /* put reference from nfs4_preprocess_seqid_op */ nfs4_put_stid(&stp->st_stid); + + nfsd_file_close_inode_sync(d_inode(cstate->current_fh.fh_dentry)); out: return status; } @@ -6702,6 +6704,8 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, destroy_delegation(dp); put_stateid: nfs4_put_stid(&dp->dl_stid); + + nfsd_file_close_inode_sync(d_inode(cstate->current_fh.fh_dentry)); out: return status; } -- 2.36.1