[PATCH] nfsd4: no replays on unconfirmed owners

We shouldn't check for replays until after checking whether the open owner is
confirmed.  Clients are allowed to reuse openowners without bumping the seqid.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index e13d223..dc792b6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1465,8 +1465,16 @@
 	sop = find_openstateowner_str(strhashval, open);
 	if (sop) {
 		open->op_stateowner = sop;
-		/* check for replay */
-		if (open->op_seqid == sop->so_seqid - 1){
+		if (!sop->so_confirmed) {
+			/* Replace any unconfirmed stateowner without
+			 * even checking for replays */
+			clp = sop->so_client;
+			release_stateowner(sop);
+		} else if (open->op_seqid == sop->so_seqid) {
+			/* normal case */
+			goto renew;
+		} else if (open->op_seqid == sop->so_seqid - 1) {
+			/* replay */
 			if (sop->so_replay.rp_buflen)
 				return NFSERR_REPLAY_ME;
 			else {
@@ -1480,19 +1488,9 @@
 					" replay with no replay cache\n");
 				goto renew;
 			}
-		} else if (sop->so_confirmed) {
-			if (open->op_seqid == sop->so_seqid)
-				goto renew;
+		} else {
 			status = nfserr_bad_seqid;
 			goto out;
-		} else {
-			/* If we get here, we received an OPEN for an
-			 * unconfirmed nfs4_stateowner. Since the seqid's are
-			 * different, purge the existing nfs4_stateowner, and
-			 * instantiate a new one.
-			 */
-			clp = sop->so_client;
-			release_stateowner(sop);
 		}
 	} else {
 		/* nfs4_stateowner not found.