aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback_proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-01-23 15:18:18 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-01-25 09:36:21 -0500
commit810d82e6830100615e7481813a862d26ffcff6bd (patch)
tree800222904c927e881b0d469f0b2f3de229ba132d /fs/nfs/callback_proc.c
parentNFSv4.x: Fix wraparound issues when validing the callback sequence id (diff)
downloadlinux-dev-810d82e6830100615e7481813a862d26ffcff6bd.tar.xz
linux-dev-810d82e6830100615e7481813a862d26ffcff6bd.zip
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>
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r--fs/nfs/callback_proc.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 79c93b3bbfec..efd079d28946 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -367,7 +367,7 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
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 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
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));