Skip to content

Commit da05ba2

Browse files
jtlaytonchucklever
authored andcommitted
nfsd: hold reference to delegation when updating it for cb_getattr
Once we've dropped the flc_lock, there is nothing that ensures that the delegation that was found will still be around later. Take a reference to it while holding the lock and then drop it when we've finished with the delegation. Fixes: c596772 ("NFSD: handle GETATTR conflict with write delegation") Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent f25d1b5 commit da05ba2

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

fs/nfsd/nfs4state.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8837,7 +8837,6 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
88378837
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
88388838
struct file_lock_context *ctx;
88398839
struct file_lease *fl;
8840-
struct nfs4_delegation *dp;
88418840
struct iattr attrs;
88428841
struct nfs4_cb_fattr *ncf;
88438842

@@ -8862,14 +8861,16 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
88628861
goto break_lease;
88638862
}
88648863
if (type == F_WRLCK) {
8865-
dp = fl->c.flc_owner;
8864+
struct nfs4_delegation *dp = fl->c.flc_owner;
8865+
88668866
if (dp->dl_recall.cb_clp == *(rqstp->rq_lease_breaker)) {
88678867
spin_unlock(&ctx->flc_lock);
88688868
return 0;
88698869
}
88708870
break_lease:
88718871
nfsd_stats_wdeleg_getattr_inc(nn);
88728872
dp = fl->c.flc_owner;
8873+
refcount_inc(&dp->dl_stid.sc_count);
88738874
ncf = &dp->dl_cb_fattr;
88748875
nfs4_cb_getattr(&dp->dl_cb_fattr);
88758876
spin_unlock(&ctx->flc_lock);
@@ -8879,8 +8880,10 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
88798880
/* Recall delegation only if client didn't respond */
88808881
status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
88818882
if (status != nfserr_jukebox ||
8882-
!nfsd_wait_for_delegreturn(rqstp, inode))
8883+
!nfsd_wait_for_delegreturn(rqstp, inode)) {
8884+
nfs4_put_stid(&dp->dl_stid);
88838885
return status;
8886+
}
88848887
}
88858888
if (!ncf->ncf_file_modified &&
88868889
(ncf->ncf_initial_cinfo != ncf->ncf_cb_change ||
@@ -8900,6 +8903,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode,
89008903
*size = ncf->ncf_cur_fsize;
89018904
*modified = true;
89028905
}
8906+
nfs4_put_stid(&dp->dl_stid);
89038907
return 0;
89048908
}
89058909
break;

0 commit comments

Comments
 (0)