@@ -1056,17 +1056,32 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{
struct nfsd4_rename *rename = &u->rename;
__be32 status;
+ int retries;
if (opens_in_grace(SVC_NET(rqstp)))
return nfserr_grace;
- status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
- rename->rn_snamelen, &cstate->current_fh,
- rename->rn_tname, rename->rn_tnamelen);
- if (status)
- return status;
- set_change_info(&rename->rn_sinfo, &cstate->current_fh);
- set_change_info(&rename->rn_tinfo, &cstate->save_fh);
- return nfs_ok;
+
+ retries = 1;
+ do {
+ status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+ rename->rn_snamelen, &cstate->current_fh,
+ rename->rn_tname, rename->rn_tnamelen);
+ if (status == nfs_ok) {
+ set_change_info(&rename->rn_sinfo, &cstate->current_fh);
+ set_change_info(&rename->rn_tinfo, &cstate->save_fh);
+ break;
+ }
+ if (status != nfserr_jukebox)
+ break;
+ if (!retries--)
+ break;
+
+ fh_clear_pre_post_attrs(&cstate->save_fh);
+ fh_clear_pre_post_attrs(&cstate->current_fh);
+ nfsd4_wait_for_delegreturn(rqstp, &cstate->current_fh);
+ } while (1);
+
+ return status;
}
static __be32
nfsd_rename() can kick off a CB_RECALL (via vfs_rename() -> leases_conflict()) if a delegation is present. Before returning NFS4ERR_DELAY, give the client holding that delegation a chance to return it and then retry the nfsd_rename() again, once. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/nfsd/nfs4proc.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-)