[PATCH v3 7/7] NFSD: Make nfsd4_rename() wait before returning NFS4ERR_DELAY

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Link: https://bugzilla.linux-nfs.org/show_bug.cgi?id=354
Tested-by: Igor Mammedov <imammedo@xxxxxxxxxx>
Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---
 fs/nfsd/nfs4proc.c |   32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 5b18a71f1043..ed3c6ef875c3 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1056,17 +1056,33 @@ 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;
+		if (!nfsd4_wait_for_delegreturn(rqstp, &cstate->current_fh))
+			break;
+
+		fh_clear_pre_post_attrs(&cstate->save_fh);
+		fh_clear_pre_post_attrs(&cstate->current_fh);
+	} while (1);
+
+	return status;
 }
 
 static __be32





[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux