Once we call nfsd_file_put, there is no guarantee that "nf" can still be safely accessed. That may have been the last reference. Change the code to instead check for whether nf_ref is 2 and then unhash it and put the reference if we're successful. We might occasionally race with another lookup and end up unhashing it when it probably shouldn't have been, but that should hopefully be rare and will just result in the competing lookup having to create a new nfsd_file. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/nfsd/filecache.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 6237715bd23e..58f4d9267f4a 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -461,12 +461,14 @@ nfsd_file_put(struct nfsd_file *nf) */ void nfsd_file_close(struct nfsd_file *nf) { - nfsd_file_put(nf); - if (refcount_dec_if_one(&nf->nf_ref)) { - nfsd_file_unhash(nf); - nfsd_file_lru_remove(nf); - nfsd_file_free(nf); + /* One for the reference being put, and one for the hash */ + if (refcount_read(&nf->nf_ref) == 2) { + if (nfsd_file_unhash(nf)) + nfsd_file_put_noref(nf); } + /* put the ref for the stateid */ + nfsd_file_put(nf); + } struct nfsd_file * -- 2.37.3