Skip to content

Commit

Permalink
NFSv4.1: Ensure that the client tracks the server target_highest_slotid
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Dec 5, 2012
1 parent f4af6e2 commit 464ee9f
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 9 deletions.
2 changes: 1 addition & 1 deletion fs/nfs/callback_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
if (args->crsa_target_max_slots == fc_tbl->max_slots)
goto out;

fc_tbl->target_max_slots = args->crsa_target_max_slots;
fc_tbl->target_highest_slotid = args->crsa_target_max_slots;
nfs41_handle_recall_slot(cps->clp);
out:
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
Expand Down
25 changes: 25 additions & 0 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,28 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
res->sr_slot = NULL;
}

/* Update the client's idea of target_highest_slotid */
static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl,
u32 target_highest_slotid)
{
if (tbl->target_highest_slotid == target_highest_slotid)
return;
tbl->target_highest_slotid = target_highest_slotid;
tbl->generation++;
}

static void nfs41_update_target_slotid(struct nfs4_slot_table *tbl,
struct nfs4_slot *slot,
struct nfs4_sequence_res *res)
{
spin_lock(&tbl->slot_tbl_lock);
if (tbl->generation != slot->generation)
goto out;
nfs41_set_target_slotid_locked(tbl, res->sr_target_highest_slotid);
out:
spin_unlock(&tbl->slot_tbl_lock);
}

static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
{
struct nfs4_session *session;
Expand Down Expand Up @@ -522,6 +544,7 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
/* Check sequence flags */
if (res->sr_status_flags != 0)
nfs4_schedule_lease_recovery(clp);
nfs41_update_target_slotid(slot->table, slot, res);
break;
case -NFS4ERR_DELAY:
/* The server detected a resend of the RPC call and
Expand Down Expand Up @@ -583,6 +606,7 @@ static struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl)
tbl->highest_used_slotid = slotid;
ret = &tbl->slots[slotid];
ret->renewal_time = jiffies;
ret->generation = tbl->generation;

out:
dprintk("<-- %s used_slots=%04lx highest_used=%d slotid=%d \n",
Expand Down Expand Up @@ -5693,6 +5717,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
tbl->max_slots = max_slots;
}
tbl->highest_used_slotid = NFS4_NO_SLOT;
tbl->target_highest_slotid = max_slots - 1;
for (i = 0; i < tbl->max_slots; i++)
tbl->slots[i].seq_nr = ivalue;
spin_unlock(&tbl->slot_tbl_lock);
Expand Down
7 changes: 3 additions & 4 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -2033,17 +2033,16 @@ static int nfs4_recall_slot(struct nfs_client *clp)
return 0;
nfs4_begin_drain_session(clp);
fc_tbl = &clp->cl_session->fc_slot_table;
new = nfs4_alloc_slots(fc_tbl, fc_tbl->target_max_slots, GFP_NOFS);
new = nfs4_alloc_slots(fc_tbl, fc_tbl->target_highest_slotid + 1, GFP_NOFS);
if (!new)
return -ENOMEM;

spin_lock(&fc_tbl->slot_tbl_lock);
for (i = 0; i < fc_tbl->target_max_slots; i++)
for (i = 0; i <= fc_tbl->target_highest_slotid; i++)
new[i].seq_nr = fc_tbl->slots[i].seq_nr;
old = fc_tbl->slots;
fc_tbl->slots = new;
fc_tbl->max_slots = fc_tbl->target_max_slots;
fc_tbl->target_max_slots = 0;
fc_tbl->max_slots = fc_tbl->target_highest_slotid + 1;
clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
spin_unlock(&fc_tbl->slot_tbl_lock);

Expand Down
4 changes: 2 additions & 2 deletions fs/nfs/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -5552,8 +5552,8 @@ static int decode_sequence(struct xdr_stream *xdr,
}
/* highest slot id - currently not processed */
dummy = be32_to_cpup(p++);
/* target highest slot id - currently not processed */
dummy = be32_to_cpup(p++);
/* target highest slot id */
res->sr_target_highest_slotid = be32_to_cpup(p++);
/* result flags */
res->sr_status_flags = be32_to_cpup(p);
status = 0;
Expand Down
5 changes: 3 additions & 2 deletions include/linux/nfs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,9 @@ struct nfs4_slot_table {
u32 max_slots; /* # slots in table */
u32 highest_used_slotid; /* sent to server on each SEQ.
* op for dynamic resizing */
u32 target_max_slots; /* Set by CB_RECALL_SLOT as
* the new max_slots */
u32 target_highest_slotid; /* Server max_slot target */
unsigned long generation; /* Generation counter for
target_highest_slotid */
struct completion complete;
};

Expand Down
2 changes: 2 additions & 0 deletions include/linux/nfs_xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ struct nfs4_channel_attrs {
/* nfs41 sessions slot seqid */
struct nfs4_slot {
struct nfs4_slot_table *table;
unsigned long generation;
unsigned long renewal_time;
u32 slot_nr;
u32 seq_nr;
Expand All @@ -202,6 +203,7 @@ struct nfs4_sequence_res {
struct nfs4_slot *sr_slot; /* slot used to send request */
int sr_status; /* sequence operation status */
u32 sr_status_flags;
u32 sr_target_highest_slotid;
};

struct nfs4_get_lease_time_args {
Expand Down

0 comments on commit 464ee9f

Please sign in to comment.