NFSv4.x: Allow multiple callbacks in flight

Hook the callback channel into the same session management machinery
as we use for the forward channel.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 79c93b3..efd079d 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -367,7 +367,7 @@
 	if (args->csa_sequenceid == slot->seq_nr) {
 		dprintk("%s seqid %u is a replay\n",
 			__func__, args->csa_sequenceid);
-		if (tbl->highest_used_slotid != NFS4_NO_SLOT)
+		if (nfs4_test_locked_slot(tbl, slot->slot_nr))
 			return htonl(NFS4ERR_DELAY);
 		/* Signal process_op to set this error on next op */
 		if (args->csa_cachethis == 0)
@@ -476,12 +476,18 @@
 		goto out_unlock;
 	}
 
+	status = htonl(NFS4ERR_BADSLOT);
+	slot = nfs4_lookup_slot(tbl, args->csa_slotid);
+	if (IS_ERR(slot))
+		goto out_unlock;
 	status = validate_seqid(tbl, slot, args);
 	if (status)
 		goto out_unlock;
-
-	cps->slotid = args->csa_slotid;
-	tbl->highest_used_slotid = args->csa_slotid;
+	if (!nfs4_try_to_lock_slot(tbl, slot)) {
+		status = htonl(NFS4ERR_DELAY);
+		goto out_unlock;
+	}
+	cps->slot = slot;
 
 	memcpy(&res->csr_sessionid, &args->csa_sessionid,
 	       sizeof(res->csr_sessionid));