aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-11-20 12:49:27 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-12-05 18:29:47 -0500
commit464ee9f966404786ba4c6be35dc8362ee8e6ba4e (patch)
tree1a095938b9b674a1617050e2cc824837686d7af6 /fs/nfs
parentf4af6e2abc8efb1695203a2b76876edf80f79960 (diff)
NFSv4.1: Ensure that the client tracks the server target_highest_slotid
Dynamic slot allocation in NFSv4.1 depends on the client being able to track the server's target value for the highest slotid in the slot table. See the reference in Section 2.10.6.1 of RFC5661. To avoid ordering problems in the case where 2 SEQUENCE replies contain conflicting updates to this target value, we also introduce a generation counter, to track whether or not an RPC containing a SEQUENCE operation was launched before or after the last update. Also rename the nfs4_slot_table target_max_slots field to 'target_highest_slotid' to avoid confusion with a slot table size or number of slots. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/callback_proc.c2
-rw-r--r--fs/nfs/nfs4proc.c25
-rw-r--r--fs/nfs/nfs4state.c7
-rw-r--r--fs/nfs/nfs4xdr.c4
4 files changed, 31 insertions, 7 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 0be08b964f38..0ef047b7d28d 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -576,7 +576,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
576 if (args->crsa_target_max_slots == fc_tbl->max_slots) 576 if (args->crsa_target_max_slots == fc_tbl->max_slots)
577 goto out; 577 goto out;
578 578
579 fc_tbl->target_max_slots = args->crsa_target_max_slots; 579 fc_tbl->target_highest_slotid = args->crsa_target_max_slots;
580 nfs41_handle_recall_slot(cps->clp); 580 nfs41_handle_recall_slot(cps->clp);
581out: 581out:
582 dprintk("%s: exit with status = %d\n", __func__, ntohl(status)); 582 dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 197ef3e4e1f7..d91abaa522e8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -488,6 +488,28 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
488 res->sr_slot = NULL; 488 res->sr_slot = NULL;
489} 489}
490 490
491/* Update the client's idea of target_highest_slotid */
492static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl,
493 u32 target_highest_slotid)
494{
495 if (tbl->target_highest_slotid == target_highest_slotid)
496 return;
497 tbl->target_highest_slotid = target_highest_slotid;
498 tbl->generation++;
499}
500
501static void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
502 struct nfs4_slot *slot,
503 struct nfs4_sequence_res *res)
504{
505 spin_lock(&tbl->slot_tbl_lock);
506 if (tbl->generation != slot->generation)
507 goto out;
508 nfs41_set_target_slotid_locked(tbl, res->sr_target_highest_slotid);
509out:
510 spin_unlock(&tbl->slot_tbl_lock);
511}
512
491static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) 513static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
492{ 514{
493 struct nfs4_session *session; 515 struct nfs4_session *session;
@@ -522,6 +544,7 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
522 /* Check sequence flags */ 544 /* Check sequence flags */
523 if (res->sr_status_flags != 0) 545 if (res->sr_status_flags != 0)
524 nfs4_schedule_lease_recovery(clp); 546 nfs4_schedule_lease_recovery(clp);
547 nfs41_update_target_slotid(slot->table, slot, res);
525 break; 548 break;
526 case -NFS4ERR_DELAY: 549 case -NFS4ERR_DELAY:
527 /* The server detected a resend of the RPC call and 550 /* The server detected a resend of the RPC call and
@@ -583,6 +606,7 @@ static struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl)
583 tbl->highest_used_slotid = slotid; 606 tbl->highest_used_slotid = slotid;
584 ret = &tbl->slots[slotid]; 607 ret = &tbl->slots[slotid];
585 ret->renewal_time = jiffies; 608 ret->renewal_time = jiffies;
609 ret->generation = tbl->generation;
586 610
587out: 611out:
588 dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n", 612 dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
@@ -5693,6 +5717,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
5693 tbl->max_slots = max_slots; 5717 tbl->max_slots = max_slots;
5694 } 5718 }
5695 tbl->highest_used_slotid = NFS4_NO_SLOT; 5719 tbl->highest_used_slotid = NFS4_NO_SLOT;
5720 tbl->target_highest_slotid = max_slots - 1;
5696 for (i = 0; i < tbl->max_slots; i++) 5721 for (i = 0; i < tbl->max_slots; i++)
5697 tbl->slots[i].seq_nr = ivalue; 5722 tbl->slots[i].seq_nr = ivalue;
5698 spin_unlock(&tbl->slot_tbl_lock); 5723 spin_unlock(&tbl->slot_tbl_lock);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 9495789c425b..842cb8c2f65d 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -2033,17 +2033,16 @@ static int nfs4_recall_slot(struct nfs_client *clp)
2033 return 0; 2033 return 0;
2034 nfs4_begin_drain_session(clp); 2034 nfs4_begin_drain_session(clp);
2035 fc_tbl = &clp->cl_session->fc_slot_table; 2035 fc_tbl = &clp->cl_session->fc_slot_table;
2036 new = nfs4_alloc_slots(fc_tbl, fc_tbl->target_max_slots, GFP_NOFS); 2036 new = nfs4_alloc_slots(fc_tbl, fc_tbl->target_highest_slotid + 1, GFP_NOFS);
2037 if (!new) 2037 if (!new)
2038 return -ENOMEM; 2038 return -ENOMEM;
2039 2039
2040 spin_lock(&fc_tbl->slot_tbl_lock); 2040 spin_lock(&fc_tbl->slot_tbl_lock);
2041 for (i = 0; i < fc_tbl->target_max_slots; i++) 2041 for (i = 0; i <= fc_tbl->target_highest_slotid; i++)
2042 new[i].seq_nr = fc_tbl->slots[i].seq_nr; 2042 new[i].seq_nr = fc_tbl->slots[i].seq_nr;
2043 old = fc_tbl->slots; 2043 old = fc_tbl->slots;
2044 fc_tbl->slots = new; 2044 fc_tbl->slots = new;
2045 fc_tbl->max_slots = fc_tbl->target_max_slots; 2045 fc_tbl->max_slots = fc_tbl->target_highest_slotid + 1;
2046 fc_tbl->target_max_slots = 0;
2047 clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots; 2046 clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
2048 spin_unlock(&fc_tbl->slot_tbl_lock); 2047 spin_unlock(&fc_tbl->slot_tbl_lock);
2049 2048
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 27b0fec1a6b0..05d34f1fcc19 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -5552,8 +5552,8 @@ static int decode_sequence(struct xdr_stream *xdr,
5552 } 5552 }
5553 /* highest slot id - currently not processed */ 5553 /* highest slot id - currently not processed */
5554 dummy = be32_to_cpup(p++); 5554 dummy = be32_to_cpup(p++);
5555 /* target highest slot id - currently not processed */ 5555 /* target highest slot id */
5556 dummy = be32_to_cpup(p++); 5556 res->sr_target_highest_slotid = be32_to_cpup(p++);
5557 /* result flags */ 5557 /* result flags */
5558 res->sr_status_flags = be32_to_cpup(p); 5558 res->sr_status_flags = be32_to_cpup(p);
5559 status = 0; 5559 status = 0;