From: andros@netapp.com
To: trond.myklebust@netapp.com
Cc: linux-nfs@vger.kernel.org, Andy Adamson <andros@netapp.com>
Subject: [PATCH 1/3] NFSv4.1: dynamic session slots
Date: Thu, 13 Oct 2011 17:14:28 -0400 [thread overview]
Message-ID: <1318540470-15181-1-git-send-email-andros@netapp.com> (raw)
From: Andy Adamson <andros@netapp.com>
The session fore/backchannel slot tables implementation is changed from a
static array to an hlist hashed on slotid. Slotid's are values 0..N where N
is initially negotiated between the client and server via the CREATE_SESSION
call, and can be dynamically changed by the server during an active session.
The back channel use of dynamic session slots are in a separate patch.
The slot table init/reset code called by nfs4_proc_create_session has been
refactored: nfs4_setup_slot_tables calls either nfs4_init_slot_table OR
nfs4_reset_slot_table.
A new struct nfs4_slot_table field, allocated_slots, counts the
number of dynamically allocated_slots and is dec'ed/inc'ed in the
nfs4_remove_slot_locked/nfs4_insert_slot_locked functions.
When there are no allocated slots (mount), nfs4_setup_slot_tables calls
nfs4_init_slot_tbl on both the fc and bc tables which allocates an initial
number of session slots equal to the inital number of dynamic rpc_slots
created upon transport creation (xprt->min_reqs).
Slots are dynamically allocated as needed upto the CREATE_SESSION negotiated
max_reqs value. An upcoming patch set will respond to the NFSv4.1 server's
increase in the max_reqs of the slot table (via SEQUENCE target_highest_slotid)
by dynamically adding slots in this same manner.
For session reset the session is drained (inactive). The (old) session has
allocated fc/bc slot tables which we will reuse. nfs4_reset_slot_table
only reduces the allocated_slots if the new max_reqs negotiated by the reset
CREATE_SESSION is less than the number of allocated_slots. The resultant slot
table is then re-initialized.
CB_SLOT_RECALL is changed only in that it now shares code with session
reset - it also calls nfs4_reduce_slots_locked.
Slots are referenced while in use so that the slot table size can be
adjusted down without session draining (an upcoming patch) for CB_SLOT_RECALL
and for responding to an NFSv4.1 server's decreasing the number of slots
via SEQUENCE target_highest_slotid.
Signed-off-by: Andy Adamson <andros@netapp.com>
---
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4proc.c | 335 +++++++++++++++++++++++++++++++++------------
fs/nfs/nfs4state.c | 12 +--
fs/nfs/nfs4xdr.c | 19 ++--
include/linux/nfs_fs_sb.h | 12 +-
include/linux/nfs_xdr.h | 5 +-
6 files changed, 265 insertions(+), 119 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 3e93e9a..cbc94f3 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -266,6 +266,7 @@ extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
extern int nfs4_proc_create_session(struct nfs_client *);
extern int nfs4_proc_destroy_session(struct nfs4_session *);
extern int nfs4_init_session(struct nfs_server *server);
+extern void nfs4_reduce_slots_locked(struct nfs4_slot_table *tbl);
extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
struct nfs_fsinfo *fsinfo);
extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4700fae..aacab11 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -349,6 +349,174 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
#if defined(CONFIG_NFS_V4_1)
/*
+ * Session dynamic slot table helper functions
+ */
+
+static inline u32 slot_tbl_hash(const u8 slotid)
+{
+ return (u32)slotid % SLOT_TABLE_SIZE;
+}
+
+static void nfs4_init_slot(struct nfs4_slot *new, u8 slotid, int ivalue)
+{
+ INIT_HLIST_NODE(&new->slot_node);
+ new->slotid = slotid;
+ new->seq_nr = ivalue;
+ atomic_set(&new->ref, 1);
+}
+
+static void nfs4_insert_slot_locked(struct nfs4_slot_table *tbl,
+ struct nfs4_slot *new)
+{
+ u32 hash = slot_tbl_hash(new->slotid);
+
+ hlist_add_head(&new->slot_node, &tbl->slots[hash]);
+ tbl->allocated_slots++;
+}
+
+static struct nfs4_slot *nfs4_alloc_add_slot(struct nfs4_slot_table *tbl,
+ int ivalue, int slotid,
+ gfp_t gfp_flags)
+{
+ struct nfs4_slot *new;
+
+ dprintk("--> %s slotid=%u tbl->allocated_slots=%d\n", __func__,
+ slotid, tbl->allocated_slots);
+ new = kzalloc(sizeof(struct nfs4_slot), gfp_flags);
+ if (!new)
+ return NULL;
+ /* tbl->allocated_slots holds the next unallocated slotid */
+ nfs4_init_slot(new, slotid, ivalue);
+ spin_lock(&tbl->slot_tbl_lock);
+ if (tbl->allocated_slots != slotid) {
+ spin_unlock(&tbl->slot_tbl_lock);
+ kfree(new);
+ dprintk("%s slotid %u already allocated\n", __func__,
+ slotid);
+ return NULL;
+ }
+ nfs4_insert_slot_locked(tbl, new);
+ spin_unlock(&tbl->slot_tbl_lock);
+ return new;
+}
+
+static int nfs4_prealloc_slots(struct nfs4_slot_table *tbl, int num, int ivalue)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < num; i++) {
+ if (nfs4_alloc_add_slot(tbl, ivalue, tbl->allocated_slots,
+ GFP_NOFS) == NULL)
+ break;
+ }
+ if (i != num)
+ ret = -ENOMEM;
+ return ret;
+}
+
+static struct nfs4_slot *
+nfs4_dynamic_alloc_slot(struct nfs4_slot_table *tbl, u8 slotid)
+{
+
+ /* only allocate the next slotid */
+ if (slotid != tbl->allocated_slots) {
+ dprintk("%s slotid %u already allocated\n", __func__, slotid);
+ return NULL;
+ }
+ return nfs4_alloc_add_slot(tbl, 1, slotid, GFP_NOWAIT);
+}
+
+/*
+ * Return the slot associated with the slotid returned by nfs4_find_slot
+ * which returns only slotids between 0 and tbl->max_slots.
+ * If the slot is not found, it has not been allocated: the NULL return
+ * puts the request on the slot table waitq and dynamically allocates a
+ * new slot.
+ */
+static struct nfs4_slot *
+nfs4_lookup_slot_locked(struct nfs4_slot_table *tbl, u8 slotid)
+{
+ struct nfs4_slot *sp;
+ struct hlist_node *n;
+ u32 hash = slot_tbl_hash(slotid);
+
+ dprintk("--> %s input slotid %u\n", __func__, slotid);
+ hlist_for_each_entry(sp, n, &tbl->slots[hash], slot_node) {
+ if (sp->slotid == slotid)
+ return sp;
+ else
+ continue;
+ }
+ return NULL;
+}
+
+static inline void nfs4_put_slot_locked(struct nfs4_slot *slot)
+{
+ if (atomic_dec_and_test(&slot->ref)) {
+ BUG_ON(!hlist_unhashed(&slot->slot_node));
+ kfree(slot);
+ }
+}
+
+static inline void nfs4_get_slot(struct nfs4_slot *slot)
+{
+ atomic_inc(&slot->ref);
+}
+
+static void nfs4_remove_slot_locked(struct nfs4_slot_table *tbl,
+ struct nfs4_slot *slot)
+{
+ dprintk("--> %s slotid %d\n", __func__, slot->slotid);
+ hlist_del_init(&slot->slot_node);
+ tbl->allocated_slots--;
+ nfs4_put_slot_locked(slot);
+}
+
+static void nfs4_free_all_slots(struct nfs4_slot_table *tbl)
+{
+ struct nfs4_slot *slotp;
+ int i;
+
+ dprintk("--> %s\n", __func__);
+ spin_lock(&tbl->slot_tbl_lock);
+ for (i = 0; i < SLOT_TABLE_SIZE; i++) {
+ while (!hlist_empty(&tbl->slots[i])) {
+ slotp = hlist_entry(tbl->slots[i].first,
+ struct nfs4_slot, slot_node);
+ nfs4_remove_slot_locked(tbl, slotp);
+ }
+ /* re-initialize hlist_head */
+ tbl->slots[i].first = NULL;
+ }
+ spin_unlock(&tbl->slot_tbl_lock);
+}
+
+/*
+ * Remove num_dec number of contiguous slotids starting from highest
+ * allocated slotid
+ *
+ * Note: set the new tbl->max_slots prior to calling.
+ */
+void nfs4_reduce_slots_locked(struct nfs4_slot_table *tbl)
+{
+ struct nfs4_slot *removeme;
+ int i, rm_slotid = tbl->allocated_slots - 1;
+ int num_dec = tbl->allocated_slots - tbl->max_slots;
+
+ dprintk("--> %s num_dec=%d\n", __func__, num_dec);
+
+ /* nothing to do */
+ if (num_dec <= 0)
+ return;
+ for (i = 0; i < num_dec; i++) {
+ removeme = nfs4_lookup_slot_locked(tbl, rm_slotid);
+ BUG_ON(removeme == NULL);
+ nfs4_remove_slot_locked(tbl, removeme);
+ rm_slotid--;
+ }
+}
+
+/*
* nfs4_free_slot - free a slot and efficiently update slot table.
*
* freeing a slot is trivially done by clearing its respective bit
@@ -364,9 +532,8 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
* Must be called while holding tbl->slot_tbl_lock
*/
static void
-nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
+nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
{
- int free_slotid = free_slot - tbl->slots;
int slotid = free_slotid;
BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
@@ -431,7 +598,8 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
}
spin_lock(&tbl->slot_tbl_lock);
- nfs4_free_slot(tbl, res->sr_slot);
+ nfs4_free_slot(tbl, res->sr_slot->slotid);
+ nfs4_put_slot_locked(res->sr_slot);
nfs4_check_drain_fc_complete(res->sr_session);
spin_unlock(&tbl->slot_tbl_lock);
res->sr_slot = NULL;
@@ -472,10 +640,9 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
* returned NFS4ERR_DELAY as per Section 2.10.6.2
* of RFC5661.
*/
- dprintk("%s: slot=%td seq=%d: Operation in progress\n",
+ dprintk("%s: slot=%u seq=%d: Operation in progress\n",
__func__,
- res->sr_slot - res->sr_session->fc_slot_table.slots,
- res->sr_slot->seq_nr);
+ res->sr_slot->slotid, res->sr_slot->seq_nr);
goto out_retry;
default:
/* Just update the slot sequence no. */
@@ -560,7 +727,7 @@ int nfs41_setup_sequence(struct nfs4_session *session,
*/
rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
spin_unlock(&tbl->slot_tbl_lock);
- dprintk("%s Schedule Session Reset\n", __func__);
+ dprintk("%s Schedule Session Draining\n", __func__);
return -EAGAIN;
}
@@ -579,12 +746,21 @@ int nfs41_setup_sequence(struct nfs4_session *session,
dprintk("<-- %s: no free slots\n", __func__);
return -EAGAIN;
}
+ slot = nfs4_lookup_slot_locked(tbl, slotid);
+ if (slot == NULL) {
+ rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
+ nfs4_free_slot(tbl, slotid);
+ spin_unlock(&tbl->slot_tbl_lock);
+ nfs4_dynamic_alloc_slot(tbl, slotid);
+ dprintk("<-- %s: allocate slotid %u\n", __func__, slotid);
+ return -EAGAIN;
+ }
+ nfs4_get_slot(slot);
spin_unlock(&tbl->slot_tbl_lock);
rpc_task_set_priority(task, RPC_PRIORITY_NORMAL);
- slot = tbl->slots + slotid;
args->sa_session = session;
- args->sa_slotid = slotid;
+ args->sa_slot = slot;
args->sa_cache_this = cache_reply;
dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
@@ -617,9 +793,9 @@ int nfs4_setup_sequence(const struct nfs_server *server,
goto out;
}
- dprintk("--> %s clp %p session %p sr_slot %td\n",
+ dprintk("--> %s clp %p session %p sr_slot %d\n",
__func__, session->clp, session, res->sr_slot ?
- res->sr_slot - session->fc_slot_table.slots : -1);
+ res->sr_slot->slotid : -1);
ret = nfs41_setup_sequence(session, args, res, cache_reply,
task);
@@ -4997,127 +5173,110 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
}
/*
- * Reset a slot table
+ * Reset a slot table. Session has been drained and reset with new slot table
+ * parameters from create_session.
+ * Keep all allocated slots that fit into new slot table max_reqs parameter.
+ * Set tbl->max_slots to new value.
+ * Adjust tbl->allocated_slots if needed.
+ * Initiaize allocated slots seq_nr to ivalue.
+ * Reset highest_used_slotid to -1.
*/
-static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
+static void nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 new_max_reqs,
int ivalue)
{
- struct nfs4_slot *new = NULL;
+ struct nfs4_slot *sp;
+ struct hlist_node *n;
int i;
- int ret = 0;
-
- dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
- max_reqs, tbl->max_slots);
- /* Does the newly negotiated max_reqs match the existing slot table? */
- if (max_reqs != tbl->max_slots) {
- ret = -ENOMEM;
- new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
- GFP_NOFS);
- if (!new)
- goto out;
- ret = 0;
- kfree(tbl->slots);
- }
spin_lock(&tbl->slot_tbl_lock);
- if (new) {
- tbl->slots = new;
- tbl->max_slots = max_reqs;
- }
- for (i = 0; i < tbl->max_slots; ++i)
- tbl->slots[i].seq_nr = ivalue;
- spin_unlock(&tbl->slot_tbl_lock);
- dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
- tbl, tbl->slots, tbl->max_slots);
-out:
- dprintk("<-- %s: return %d\n", __func__, ret);
- return ret;
-}
-/*
- * Reset the forechannel and backchannel slot tables
- */
-static int nfs4_reset_slot_tables(struct nfs4_session *session)
-{
- int status;
+ dprintk("--> %s new_max_reqs %d tbl->allocated_slots %d\n", __func__,
+ new_max_reqs, tbl->allocated_slots);
- status = nfs4_reset_slot_table(&session->fc_slot_table,
- session->fc_attrs.max_reqs, 1);
- if (status)
- return status;
+ tbl->max_slots = new_max_reqs;
+ nfs4_reduce_slots_locked(tbl);
+ tbl->highest_used_slotid = -1;
- status = nfs4_reset_slot_table(&session->bc_slot_table,
- session->bc_attrs.max_reqs, 0);
- return status;
+ for (i = 0; i < SLOT_TABLE_SIZE; i++) {
+ hlist_for_each_entry(sp, n, &tbl->slots[i], slot_node)
+ sp->seq_nr = ivalue;
+ }
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("<-- %s: tbl=%p max_slots=%d tbl->allocated_slots=%d\n",
+ __func__, tbl, tbl->max_slots, tbl->allocated_slots);
+ return;
}
-/* Destroy the slot table */
+/* Destroy the sessions slot tables */
static void nfs4_destroy_slot_tables(struct nfs4_session *session)
{
- if (session->fc_slot_table.slots != NULL) {
- kfree(session->fc_slot_table.slots);
- session->fc_slot_table.slots = NULL;
- }
- if (session->bc_slot_table.slots != NULL) {
- kfree(session->bc_slot_table.slots);
- session->bc_slot_table.slots = NULL;
- }
- return;
+ dprintk("--> %s\n", __func__);
+
+ nfs4_free_all_slots(&session->fc_slot_table);
+ nfs4_free_all_slots(&session->bc_slot_table);
}
-/*
- * Initialize slot table
- */
static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
- int max_slots, int ivalue)
+ int max_slots, int num_prealloc, int ivalue)
{
- struct nfs4_slot *slot;
- int ret = -ENOMEM;
+ int ret;
BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE);
dprintk("--> %s: max_reqs=%u\n", __func__, max_slots);
- slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_NOFS);
- if (!slot)
+ ret = nfs4_prealloc_slots(tbl, num_prealloc, ivalue);
+ if (ret) {
+ nfs4_free_all_slots(tbl);
goto out;
+ }
ret = 0;
spin_lock(&tbl->slot_tbl_lock);
tbl->max_slots = max_slots;
- tbl->slots = slot;
tbl->highest_used_slotid = -1; /* no slot is currently used */
spin_unlock(&tbl->slot_tbl_lock);
- dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
- tbl, tbl->slots, tbl->max_slots);
+ dprintk("%s: tbl=%p max_slots=%d, tbl->allocated_slots=%d\n", __func__,
+ tbl, tbl->max_slots, tbl->allocated_slots);
out:
dprintk("<-- %s: return %d\n", __func__, ret);
return ret;
}
/*
- * Initialize the forechannel and backchannel tables
+ * Initialize or reset the forechannel and backchannel tables
+ * Note: kzalloc of nfs4_sessions initiallizes tbl->slots[] hlist heads
*/
-static int nfs4_init_slot_tables(struct nfs4_session *session)
+static int nfs4_setup_slot_tables(struct nfs4_session *session)
{
struct nfs4_slot_table *tbl;
int status = 0;
+ dprintk("--> %s\n", __func__);
tbl = &session->fc_slot_table;
- if (tbl->slots == NULL) {
+ if (tbl->allocated_slots == 0) {
status = nfs4_init_slot_table(tbl,
- session->fc_attrs.max_reqs, 1);
+ session->fc_attrs.max_reqs,
+ session->clp->cl_rpcclient->cl_xprt->min_reqs,
+ 1);
if (status)
return status;
- }
+ } else
+ nfs4_reset_slot_table(&session->fc_slot_table,
+ session->fc_attrs.max_reqs, 1);
tbl = &session->bc_slot_table;
- if (tbl->slots == NULL) {
+ if (tbl->allocated_slots == 0) {
status = nfs4_init_slot_table(tbl,
- session->bc_attrs.max_reqs, 0);
+ session->bc_attrs.max_reqs,
+ /* Backchannel max_reqs == 1 */
+ session->bc_attrs.max_reqs,
+ 0);
if (status)
nfs4_destroy_slot_tables(session);
- }
+ } else
+ nfs4_reset_slot_table(&session->bc_slot_table,
+ session->bc_attrs.max_reqs, 0);
return status;
}
@@ -5306,13 +5465,9 @@ int nfs4_proc_create_session(struct nfs_client *clp)
if (status)
goto out;
- /* Init and reset the fore channel */
- status = nfs4_init_slot_tables(session);
- dprintk("slot table initialization returned %d\n", status);
- if (status)
- goto out;
- status = nfs4_reset_slot_tables(session);
- dprintk("slot table reset returned %d\n", status);
+ /* Setup the fore and back channel slot tables */
+ status = nfs4_setup_slot_tables(session);
+ dprintk("slot table setup returned %d\n", status);
if (status)
goto out;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 39914be..8260865 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1573,26 +1573,16 @@ static int nfs4_recall_slot(struct nfs_client *clp)
{
struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table;
struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs;
- struct nfs4_slot *new, *old;
- int i;
nfs4_begin_drain_session(clp);
- new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
- GFP_NOFS);
- if (!new)
- return -ENOMEM;
spin_lock(&fc_tbl->slot_tbl_lock);
- for (i = 0; i < fc_tbl->target_max_slots; 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;
+ nfs4_reduce_slots_locked(fc_tbl);
fc_tbl->target_max_slots = 0;
fc_attrs->max_reqs = fc_tbl->max_slots;
spin_unlock(&fc_tbl->slot_tbl_lock);
- kfree(old);
nfs4_end_drain_session(clp);
return 0;
}
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1dce12f..5a22a9b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1872,7 +1872,6 @@ static void encode_sequence(struct xdr_stream *xdr,
#if defined(CONFIG_NFS_V4_1)
struct nfs4_session *session = args->sa_session;
struct nfs4_slot_table *tp;
- struct nfs4_slot *slot;
__be32 *p;
if (!session)
@@ -1880,9 +1879,6 @@ static void encode_sequence(struct xdr_stream *xdr,
tp = &session->fc_slot_table;
- WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
- slot = tp->slots + args->sa_slotid;
-
p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16);
*p++ = cpu_to_be32(OP_SEQUENCE);
@@ -1896,11 +1892,11 @@ static void encode_sequence(struct xdr_stream *xdr,
((u32 *)session->sess_id.data)[1],
((u32 *)session->sess_id.data)[2],
((u32 *)session->sess_id.data)[3],
- slot->seq_nr, args->sa_slotid,
+ args->sa_slot->seq_nr, args->sa_slot->slotid,
tp->highest_used_slotid, args->sa_cache_this);
p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
- *p++ = cpu_to_be32(slot->seq_nr);
- *p++ = cpu_to_be32(args->sa_slotid);
+ *p++ = cpu_to_be32(args->sa_slot->seq_nr);
+ *p++ = cpu_to_be32(args->sa_slot->slotid);
*p++ = cpu_to_be32(tp->highest_used_slotid);
*p = cpu_to_be32(args->sa_cache_this);
hdr->nops++;
@@ -5361,13 +5357,16 @@ static int decode_sequence(struct xdr_stream *xdr,
/* seqid */
dummy = be32_to_cpup(p++);
if (dummy != res->sr_slot->seq_nr) {
- dprintk("%s Invalid sequence number\n", __func__);
+ dprintk("%s Invalid sequence number %d for "
+ "[slotid:seq_nr] [%d:%d]\n", __func__,
+ dummy, res->sr_slot->slotid, res->sr_slot->seq_nr);
goto out_err;
}
/* slot id */
dummy = be32_to_cpup(p++);
- if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
- dprintk("%s Invalid slot id\n", __func__);
+ if (dummy != res->sr_slot->slotid) {
+ dprintk("%s Invalid slot id %d for [slotid:seq_nr] [%d:%d]\n",
+ __func__, dummy, res->sr_slot->slotid, res->sr_slot->seq_nr);
goto out_err;
}
/* highest slot id - currently not processed */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index b5479df..1b393ae 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -193,12 +193,15 @@ struct nfs_server {
/* Sessions */
#define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long)))
+#define SLOT_TABLE_BITS 4
+#define SLOT_TABLE_SIZE (1 << SLOT_TABLE_BITS)
struct nfs4_slot_table {
- struct nfs4_slot *slots; /* seqid per slot */
+ struct hlist_head slots[SLOT_TABLE_SIZE]; /* seqid per slot */
unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
spinlock_t slot_tbl_lock;
struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
- int max_slots; /* # slots in table */
+ int allocated_slots; /* # slots in table */
+ int max_slots; /* max # slots in table */
int highest_used_slotid; /* sent to server on each SEQ.
* op for dynamic resizing */
int target_max_slots; /* Set by CB_RECALL_SLOT as
@@ -206,11 +209,6 @@ struct nfs4_slot_table {
struct completion complete;
};
-static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
-{
- return sp - tbl->slots;
-}
-
/*
* Session related parameters
*/
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index abd615d..c7fe490 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -168,12 +168,15 @@ struct nfs4_channel_attrs {
/* nfs41 sessions slot seqid */
struct nfs4_slot {
+ struct hlist_node slot_node;
+ atomic_t ref;
u32 seq_nr;
+ u8 slotid;
};
struct nfs4_sequence_args {
struct nfs4_session *sa_session;
- u8 sa_slotid;
+ struct nfs4_slot *sa_slot;
u8 sa_cache_this;
};
--
1.7.4.4
next reply other threads:[~2011-10-13 21:14 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-13 21:14 andros [this message]
2011-10-13 21:14 ` [PATCH 2/3] NFSv4.1: backchannel dynamic session slots andros
2011-10-13 21:14 ` [PATCH 3/3] NFSv4.1: rename nfs4_free_slot and nfs4_find_slot andros
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1318540470-15181-1-git-send-email-andros@netapp.com \
--to=andros@netapp.com \
--cc=linux-nfs@vger.kernel.org \
--cc=trond.myklebust@netapp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).