* [PATCH 0/4] NFSD: Add support for session dynamic slot management
@ 2012-11-29 3:17 Trond Myklebust
2012-11-29 3:17 ` [PATCH 1/4] NFSD: Convert the slot table to use a linked list Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2012-11-29 3:17 UTC (permalink / raw)
To: bfields; +Cc: linux-nfs
This patch series adds support for session dynamic slot management
in accordance with Section 2.10.6.1 of RFC5661.
It implements a very simple policy that is controlled by the function
nfsd4_sequence_adjust_slot_table(): If the client is matching the server
target_highest_slotid, then we increase the window size by 1/4. Otherwise
we try to shrink the window.
The window size is bounded from below by the negotiated session table size
for backward compatibility with clients that do not support dynamic slot
management.
Trond Myklebust (4):
NFSD: Convert the slot table to use a linked list
NFSD: Make DRC memory limits work with dynamic slot allocation
NFSD: Add slot table support for target_highest_slotid and
highest_slotid
NFSD: Add support for dynamic slot changes
fs/nfsd/nfs4state.c | 279 ++++++++++++++++++++++++++++++++++++++++------------
fs/nfsd/nfs4xdr.c | 7 +-
fs/nfsd/nfsd.h | 4 +-
fs/nfsd/nfssvc.c | 4 +-
fs/nfsd/state.h | 15 ++-
fs/nfsd/xdr4.h | 6 +-
6 files changed, 240 insertions(+), 75 deletions(-)
--
1.7.11.7
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] NFSD: Convert the slot table to use a linked list
2012-11-29 3:17 [PATCH 0/4] NFSD: Add support for session dynamic slot management Trond Myklebust
@ 2012-11-29 3:17 ` Trond Myklebust
2012-11-29 3:17 ` [PATCH 2/4] NFSD: Make DRC memory limits work with dynamic slot allocation Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2012-11-29 3:17 UTC (permalink / raw)
To: bfields; +Cc: linux-nfs
In preparation for the dynamic slot table allocation, convert the nfsd
slot table to a linked list model.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfsd/nfs4state.c | 151 +++++++++++++++++++++++++++++++++++++++++-----------
fs/nfsd/state.h | 10 +++-
2 files changed, 129 insertions(+), 32 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d0237f8..5717ea1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -704,15 +704,6 @@ gen_sessionid(struct nfsd4_session *ses)
*/
#define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44)
-static void
-free_session_slots(struct nfsd4_session *ses)
-{
- int i;
-
- for (i = 0; i < ses->se_fchannel.maxreqs; i++)
- kfree(ses->se_slots[i]);
-}
-
/*
* We don't actually need to cache the rpc and session headers, so we
* can allocate a little less for each slot:
@@ -758,29 +749,127 @@ static void nfsd4_put_drc_mem(int slotsize, int num)
spin_unlock(&nfsd_drc_lock);
}
-static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
+static void nfsd4_free_slot(struct nfsd4_slot *slot)
{
- struct nfsd4_session *new;
- int mem, i;
+ kfree(slot);
+}
+
+static struct nfsd4_slot *nfsd4_new_slot(size_t slotsize, gfp_t gfp_mask)
+{
+ return kzalloc(sizeof(struct nfsd4_slot) + slotsize, gfp_mask);
+}
+
+static struct nfsd4_slot *nfsd4_find_slot_locked(const struct nfsd4_slot_table *tbl,
+ u32 slotid)
+{
+ struct nfsd4_slot *slot;
+
+ list_for_each_entry(slot, &tbl->slt_head, sl_list) {
+ if (slot->sl_slotid == slotid)
+ return slot;
+ }
+ return NULL;
+}
+
+static struct nfsd4_slot *nfsd4_find_slot(struct nfsd4_slot_table *tbl,
+ u32 slotid)
+{
+ struct nfsd4_slot *slot;
+
+ spin_lock(&tbl->slt_lock);
+ slot = nfsd4_find_slot_locked(tbl, slotid);
+ spin_unlock(&tbl->slt_lock);
+ return slot;
+}
+
+static struct nfsd4_slot *nfsd4_find_last_slot_locked(const struct nfsd4_slot_table *tbl)
+{
+ if (list_empty(&tbl->slt_head))
+ return NULL;
+ return list_entry(tbl->slt_head.prev, struct nfsd4_slot, sl_list);
+}
+
+static bool nfsd4_grow_slot_table_locked(struct nfsd4_slot_table *tbl,
+ u32 slotid, gfp_t gfp_mask)
+{
+ struct nfsd4_slot *slot = NULL;
+ struct nfsd4_slot *prev;
+ u32 next_slotid;
+
+ for (;;) {
+ prev = nfsd4_find_last_slot_locked(tbl);
+ if (prev != NULL) {
+ if (prev->sl_slotid >= slotid)
+ break;
+ next_slotid = prev->sl_slotid + 1;
+ } else
+ next_slotid = 0;
+ if (slot != NULL){
+ slot->sl_slotid = next_slotid;
+ list_add_tail(&slot->sl_list, &tbl->slt_head);
+ }
+ spin_unlock(&tbl->slt_lock);
+ slot = nfsd4_new_slot(tbl->slt_slotsize, gfp_mask);
+ spin_lock(&tbl->slt_lock);
+ if (slot == NULL)
+ return false;
+ }
+ nfsd4_free_slot(slot);
+ return true;
+}
+
+static bool nfsd4_grow_slot_table(struct nfsd4_slot_table *tbl,
+ u32 slotid, gfp_t gfp_mask)
+{
+ bool ret;
+
+ spin_lock(&tbl->slt_lock);
+ ret = nfsd4_grow_slot_table_locked(tbl, slotid, gfp_mask);
+ spin_unlock(&tbl->slt_lock);
+ return ret;
+}
+
+static void nfsd4_truncate_slot_table_locked(struct nfsd4_slot_table *tbl,
+ u32 slotid)
+{
+ struct nfsd4_slot *slot;
+
+ for (;;) {
+ slot = nfsd4_find_last_slot_locked(tbl);
+ if (slot == NULL || slot->sl_slotid < slotid)
+ break;
+ list_del(&slot->sl_list);
+ nfsd4_free_slot(slot);
+ }
+}
+
+static void nfsd4_free_slot_table(struct nfsd4_slot_table *tbl)
+{
+ spin_lock(&tbl->slt_lock);
+ nfsd4_truncate_slot_table_locked(tbl, 0);
+ spin_unlock(&tbl->slt_lock);
+}
+
+static void nfsd4_init_slot_table(struct nfsd4_slot_table *tbl, size_t slotsize)
+{
+ INIT_LIST_HEAD(&tbl->slt_head);
+ spin_lock_init(&tbl->slt_lock);
+ tbl->slt_slotsize = slotsize;
+}
- BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
- + sizeof(struct nfsd4_session) > PAGE_SIZE);
- mem = numslots * sizeof(struct nfsd4_slot *);
+static struct nfsd4_session *__alloc_session(size_t slotsize, u32 highest_slotid)
+{
+ struct nfsd4_session *new;
- new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
if (!new)
return NULL;
+ nfsd4_init_slot_table(&new->se_slots, slotsize);
/* allocate each struct nfsd4_slot and data cache in one piece */
- for (i = 0; i < numslots; i++) {
- mem = sizeof(struct nfsd4_slot) + slotsize;
- new->se_slots[i] = kzalloc(mem, GFP_KERNEL);
- if (!new->se_slots[i])
- goto out_free;
- }
- return new;
-out_free:
- while (i--)
- kfree(new->se_slots[i]);
+ if (nfsd4_grow_slot_table(&new->se_slots, highest_slotid, GFP_KERNEL))
+ return new;
+
+ nfsd4_free_slot_table(&new->se_slots);
kfree(new);
return NULL;
}
@@ -899,7 +988,7 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
static void __free_session(struct nfsd4_session *ses)
{
nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
- free_session_slots(ses);
+ nfsd4_free_slot_table(&ses->se_slots);
kfree(ses);
}
@@ -936,7 +1025,7 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
if (numslots < 1)
return NULL;
- new = __alloc_session(slotsize, numslots);
+ new = __alloc_session(slotsize, numslots - 1);
if (!new) {
nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
return NULL;
@@ -2032,11 +2121,11 @@ nfsd4_sequence(struct svc_rqst *rqstp,
if (nfsd4_request_too_big(rqstp, session))
goto out;
+ /* Note: nfsd4_find_slot checks the validity of seq->slotid */
status = nfserr_badslot;
- if (seq->slotid >= session->se_fchannel.maxreqs)
+ slot = nfsd4_find_slot(&session->se_slots, seq->slotid);
+ if (slot == NULL)
goto out;
-
- slot = session->se_slots[seq->slotid];
dprintk("%s: slotid %d\n", __func__, seq->slotid);
/* We do not negotiate the number of slots yet, so set the
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index e036894..7d319e9a 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -128,6 +128,8 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
(NFSD_CACHE_SIZE_SLOTS_PER_SESSION * NFSD_SLOT_CACHE_SIZE)
struct nfsd4_slot {
+ struct list_head sl_list;
+ u32 sl_slotid;
u32 sl_seqid;
__be32 sl_status;
u32 sl_datalen;
@@ -139,6 +141,12 @@ struct nfsd4_slot {
char sl_data[];
};
+struct nfsd4_slot_table {
+ struct list_head slt_head;
+ spinlock_t slt_lock;
+ size_t slt_slotsize;
+};
+
struct nfsd4_channel_attrs {
u32 headerpadsz;
u32 maxreq_sz;
@@ -195,7 +203,7 @@ struct nfsd4_session {
struct list_head se_conns;
u32 se_cb_prog;
u32 se_cb_seq_nr;
- struct nfsd4_slot *se_slots[]; /* forward channel slots */
+ struct nfsd4_slot_table se_slots;
};
extern void nfsd4_put_session(struct nfsd4_session *ses);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] NFSD: Make DRC memory limits work with dynamic slot allocation
2012-11-29 3:17 ` [PATCH 1/4] NFSD: Convert the slot table to use a linked list Trond Myklebust
@ 2012-11-29 3:17 ` Trond Myklebust
2012-11-29 3:17 ` [PATCH 3/4] NFSD: Add slot table support for target_highest_slotid and highest_slotid Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2012-11-29 3:17 UTC (permalink / raw)
To: bfields; +Cc: linux-nfs
When growing the slot table, we always want to ensure that we're
not exceeding DRC size limits.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfsd/nfs4state.c | 56 ++++++++++++++++++++++++++---------------------------
fs/nfsd/nfsd.h | 4 ++--
fs/nfsd/nfssvc.c | 4 ++--
fs/nfsd/state.h | 1 +
4 files changed, 33 insertions(+), 32 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5717ea1..9cb2450 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -704,15 +704,6 @@ gen_sessionid(struct nfsd4_session *ses)
*/
#define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44)
-/*
- * We don't actually need to cache the rpc and session headers, so we
- * can allocate a little less for each slot:
- */
-static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
-{
- return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
-}
-
static int nfsd4_sanitize_slot_size(u32 size)
{
size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */
@@ -726,27 +717,33 @@ static int nfsd4_sanitize_slot_size(u32 size)
* re-negotiate active sessions and reduce their slot usage to make
* room for new connections. For now we just fail the create session.
*/
-static int nfsd4_get_drc_mem(int slotsize, u32 num)
+static bool nfsd4_get_drc_mem(struct nfsd4_slot_table *tbl)
{
- int avail;
-
- num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
+ unsigned long new_memused;
+ unsigned long avail;
+ bool ret = false;
+ new_memused = tbl->slt_memused + tbl->slt_slotsize;
+ if (new_memused > NFSD_MAX_MEM_PER_SESSION)
+ goto out;
spin_lock(&nfsd_drc_lock);
- avail = min_t(int, NFSD_MAX_MEM_PER_SESSION,
- nfsd_drc_max_mem - nfsd_drc_mem_used);
- num = min_t(int, num, avail / slotsize);
- nfsd_drc_mem_used += num * slotsize;
+ avail = nfsd_drc_max_mem - nfsd_drc_mem_used;
+ if (avail >= tbl->slt_slotsize) {
+ nfsd_drc_mem_used += tbl->slt_slotsize;
+ tbl->slt_memused = new_memused;
+ ret = true;
+ }
spin_unlock(&nfsd_drc_lock);
-
- return num;
+out:
+ return ret;
}
-static void nfsd4_put_drc_mem(int slotsize, int num)
+static void nfsd4_put_drc_mem(struct nfsd4_slot_table *tbl)
{
spin_lock(&nfsd_drc_lock);
- nfsd_drc_mem_used -= slotsize * num;
+ nfsd_drc_mem_used -= tbl->slt_slotsize;
spin_unlock(&nfsd_drc_lock);
+ tbl->slt_memused -= tbl->slt_slotsize;
}
static void nfsd4_free_slot(struct nfsd4_slot *slot)
@@ -795,16 +792,21 @@ static bool nfsd4_grow_slot_table_locked(struct nfsd4_slot_table *tbl,
struct nfsd4_slot *slot = NULL;
struct nfsd4_slot *prev;
u32 next_slotid;
+ bool ret;
for (;;) {
prev = nfsd4_find_last_slot_locked(tbl);
if (prev != NULL) {
+ ret = true;
if (prev->sl_slotid >= slotid)
break;
next_slotid = prev->sl_slotid + 1;
} else
next_slotid = 0;
+ ret = false;
if (slot != NULL){
+ if (!nfsd4_get_drc_mem(tbl))
+ break;
slot->sl_slotid = next_slotid;
list_add_tail(&slot->sl_list, &tbl->slt_head);
}
@@ -812,10 +814,10 @@ static bool nfsd4_grow_slot_table_locked(struct nfsd4_slot_table *tbl,
slot = nfsd4_new_slot(tbl->slt_slotsize, gfp_mask);
spin_lock(&tbl->slt_lock);
if (slot == NULL)
- return false;
+ break;
}
nfsd4_free_slot(slot);
- return true;
+ return ret;
}
static bool nfsd4_grow_slot_table(struct nfsd4_slot_table *tbl,
@@ -840,6 +842,7 @@ static void nfsd4_truncate_slot_table_locked(struct nfsd4_slot_table *tbl,
break;
list_del(&slot->sl_list);
nfsd4_free_slot(slot);
+ nfsd4_put_drc_mem(tbl);
}
}
@@ -987,7 +990,6 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
static void __free_session(struct nfsd4_session *ses)
{
- nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
nfsd4_free_slot_table(&ses->se_slots);
kfree(ses);
}
@@ -1021,15 +1023,13 @@ static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
* decrease number of slots instead of their size.
*/
slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached);
- numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs);
+ numslots = min_t(u32, fchan->maxreqs, NFSD_MAX_SLOTS_PER_SESSION);
if (numslots < 1)
return NULL;
new = __alloc_session(slotsize, numslots - 1);
- if (!new) {
- nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
+ if (!new)
return NULL;
- }
init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
return new;
}
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 80d5ce4..322eb93 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -57,8 +57,8 @@ extern u32 nfsd_supported_minorversion;
extern struct mutex nfsd_mutex;
extern struct svc_serv *nfsd_serv;
extern spinlock_t nfsd_drc_lock;
-extern unsigned int nfsd_drc_max_mem;
-extern unsigned int nfsd_drc_mem_used;
+extern unsigned long nfsd_drc_max_mem;
+extern unsigned long nfsd_drc_mem_used;
extern const struct seq_operations nfs_exports_op;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 2013aa00..180d205 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -61,8 +61,8 @@ struct svc_serv *nfsd_serv;
* nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage.
*/
spinlock_t nfsd_drc_lock;
-unsigned int nfsd_drc_max_mem;
-unsigned int nfsd_drc_mem_used;
+unsigned long nfsd_drc_max_mem;
+unsigned long nfsd_drc_mem_used;
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
static struct svc_stat nfsd_acl_svcstats;
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 7d319e9a..6bcc8a1 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -145,6 +145,7 @@ struct nfsd4_slot_table {
struct list_head slt_head;
spinlock_t slt_lock;
size_t slt_slotsize;
+ unsigned long slt_memused;
};
struct nfsd4_channel_attrs {
--
1.7.11.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] NFSD: Add slot table support for target_highest_slotid and highest_slotid
2012-11-29 3:17 ` [PATCH 2/4] NFSD: Make DRC memory limits work with dynamic slot allocation Trond Myklebust
@ 2012-11-29 3:17 ` Trond Myklebust
2012-11-29 3:17 ` [PATCH 4/4] NFSD: Add support for dynamic slot changes Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2012-11-29 3:17 UTC (permalink / raw)
To: bfields; +Cc: linux-nfs
This commit just enables the slot table to set and maintain values for
the target_highest_slotid and highest_slotid, as used in the replies
to a SEQUENCE request from the client.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfsd/nfs4state.c | 18 +++++++++++-------
fs/nfsd/nfs4xdr.c | 7 +++----
fs/nfsd/state.h | 2 ++
fs/nfsd/xdr4.h | 6 ++----
4 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9cb2450..a1208cc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -853,11 +853,14 @@ static void nfsd4_free_slot_table(struct nfsd4_slot_table *tbl)
spin_unlock(&tbl->slt_lock);
}
-static void nfsd4_init_slot_table(struct nfsd4_slot_table *tbl, size_t slotsize)
+static void nfsd4_init_slot_table(struct nfsd4_slot_table *tbl,
+ size_t slotsize, u32 highest_slotid)
{
INIT_LIST_HEAD(&tbl->slt_head);
spin_lock_init(&tbl->slt_lock);
tbl->slt_slotsize = slotsize;
+ tbl->slt_highest_slotid = highest_slotid;
+ tbl->slt_target_highest_slotid = highest_slotid;
}
static struct nfsd4_session *__alloc_session(size_t slotsize, u32 highest_slotid)
@@ -867,7 +870,7 @@ static struct nfsd4_session *__alloc_session(size_t slotsize, u32 highest_slotid
new = kzalloc(sizeof(*new), GFP_KERNEL);
if (!new)
return NULL;
- nfsd4_init_slot_table(&new->se_slots, slotsize);
+ nfsd4_init_slot_table(&new->se_slots, slotsize, highest_slotid);
/* allocate each struct nfsd4_slot and data cache in one piece */
if (nfsd4_grow_slot_table(&new->se_slots, highest_slotid, GFP_KERNEL))
return new;
@@ -2128,11 +2131,6 @@ nfsd4_sequence(struct svc_rqst *rqstp,
goto out;
dprintk("%s: slotid %d\n", __func__, seq->slotid);
- /* We do not negotiate the number of slots yet, so set the
- * maxslots to the session maxreqs which is used to encode
- * sr_highest_slotid and the sr_target_slot id to maxslots */
- seq->maxslots = session->se_fchannel.maxreqs;
-
status = check_slot_seqid(seq->seqid, slot->sl_seqid,
slot->sl_flags & NFSD4_SLOT_INUSE);
if (status == nfserr_replay_cache) {
@@ -2161,6 +2159,12 @@ nfsd4_sequence(struct svc_rqst *rqstp,
else
slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
+ /* Retrieve new target/highest slotid values */
+ spin_lock(&session->se_slots.slt_lock);
+ seq->target_highest_slotid = session->se_slots.slt_target_highest_slotid;
+ seq->highest_slotid = session->se_slots.slt_highest_slotid;
+ spin_unlock(&session->se_slots.slt_lock);
+
cstate->slot = slot;
cstate->session = session;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index fd548d1..52e2923 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1371,7 +1371,7 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
READ32(seq->seqid);
READ32(seq->slotid);
- READ32(seq->maxslots);
+ READ32(seq->highest_slotid);
READ32(seq->cachethis);
DECODE_TAIL;
@@ -3415,9 +3415,8 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
WRITE32(seq->seqid);
WRITE32(seq->slotid);
- /* Note slotid's are numbered from zero: */
- WRITE32(seq->maxslots - 1); /* sr_highest_slotid */
- WRITE32(seq->maxslots - 1); /* sr_target_highest_slotid */
+ WRITE32(seq->highest_slotid);
+ WRITE32(seq->target_highest_slotid);
WRITE32(seq->status_flags);
ADJUST_ARGS();
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 6bcc8a1..7a0d8e4 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -146,6 +146,8 @@ struct nfsd4_slot_table {
spinlock_t slt_lock;
size_t slt_slotsize;
unsigned long slt_memused;
+ u32 slt_target_highest_slotid;
+ u32 slt_highest_slotid;
};
struct nfsd4_channel_attrs {
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index acd127d..0c5c704 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -405,11 +405,9 @@ struct nfsd4_sequence {
struct nfs4_sessionid sessionid; /* request/response */
u32 seqid; /* request/response */
u32 slotid; /* request/response */
- u32 maxslots; /* request/response */
+ u32 highest_slotid; /* request/response */
u32 cachethis; /* request */
-#if 0
- u32 target_maxslots; /* response */
-#endif /* not yet */
+ u32 target_highest_slotid; /* response */
u32 status_flags; /* response */
};
--
1.7.11.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] NFSD: Add support for dynamic slot changes
2012-11-29 3:17 ` [PATCH 3/4] NFSD: Add slot table support for target_highest_slotid and highest_slotid Trond Myklebust
@ 2012-11-29 3:17 ` Trond Myklebust
2012-12-06 21:29 ` J. Bruce Fields
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2012-11-29 3:17 UTC (permalink / raw)
To: bfields; +Cc: linux-nfs
The algorithm chosen for growing/shrinking the dynamic slot table
size is as follows:
If the client is sending a sa_highest_slotid value that is greater than
or equal to the our server target_highest_slotid, then multiply the
value of the latter by 5/4.
If, on the other hand, the sa_highest_slotid value is smaller than
our target_highest_slotid, then try adjusting the latter to half its
current value, or to the value of sa_highest_slotid+1, whichever is larger.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfsd/nfs4state.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++----
fs/nfsd/state.h | 2 ++
2 files changed, 69 insertions(+), 5 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a1208cc..88d0de9 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -807,6 +807,7 @@ static bool nfsd4_grow_slot_table_locked(struct nfsd4_slot_table *tbl,
if (slot != NULL){
if (!nfsd4_get_drc_mem(tbl))
break;
+ slot->sl_generation = tbl->slt_generation - 1;
slot->sl_slotid = next_slotid;
list_add_tail(&slot->sl_list, &tbl->slt_head);
}
@@ -853,6 +854,30 @@ static void nfsd4_free_slot_table(struct nfsd4_slot_table *tbl)
spin_unlock(&tbl->slt_lock);
}
+static void nfsd4_fc_set_highest_slotid_locked(struct nfsd4_session *session,
+ struct nfsd4_slot_table *tbl,
+ u32 target_highest_slotid,
+ u32 highest_slotid)
+{
+ /* Lower limit for target_highest_slotid is negotiated limit */
+ target_highest_slotid = max(target_highest_slotid,
+ session->se_fchannel.maxreqs - 1);
+ /* Lower limit for highest_slotid is target_highest_slotid */
+ highest_slotid = max(highest_slotid, target_highest_slotid);
+
+ if (target_highest_slotid == tbl->slt_target_highest_slotid &&
+ highest_slotid == tbl->slt_highest_slotid)
+ return;
+
+ if (!nfsd4_grow_slot_table_locked(tbl, highest_slotid, GFP_KERNEL))
+ return;
+
+ tbl->slt_target_highest_slotid = target_highest_slotid;
+ tbl->slt_highest_slotid = highest_slotid;
+ tbl->slt_generation++;
+ nfsd4_truncate_slot_table_locked(tbl, tbl->slt_highest_slotid);
+}
+
static void nfsd4_init_slot_table(struct nfsd4_slot_table *tbl,
size_t slotsize, u32 highest_slotid)
{
@@ -2039,6 +2064,45 @@ out:
return status;
}
+static void nfsd4_sequence_adjust_slot_table(struct nfsd4_session *session,
+ struct nfsd4_slot *slot, u32 sa_highest_slotid,
+ struct nfsd4_sequence *res)
+{
+ struct nfsd4_slot_table *tbl = &session->se_slots;
+ u32 next_target;
+ u32 next_highest;
+
+ spin_lock(&tbl->slt_lock);
+ /*
+ * If this slot hasn't seen our previous values, then don't trust
+ * that the client has seen them. Don't adjust the slot table yet.
+ */
+ if (slot->sl_generation != tbl->slt_generation)
+ goto out;
+
+ next_target = tbl->slt_target_highest_slotid;
+
+ /* Is the client bumping against our current window limits? */
+ if (sa_highest_slotid >= tbl->slt_target_highest_slotid) {
+ /* Yes! Grow the window size by 1/4 */
+ next_target += 1 + (tbl->slt_target_highest_slotid >> 2);
+ next_highest = next_target;
+ } else {
+ /* No! Try to shrink the window size by 1/2 */
+ next_target >>= 1;
+ if (sa_highest_slotid + 1 > next_target)
+ next_target = sa_highest_slotid + 1;
+ next_highest = tbl->slt_target_highest_slotid;
+ }
+ nfsd4_fc_set_highest_slotid_locked(session, tbl,
+ next_target, next_highest);
+out:
+ slot->sl_generation = tbl->slt_generation;
+ res->highest_slotid = tbl->slt_highest_slotid;
+ res->target_highest_slotid = tbl->slt_target_highest_slotid;
+ spin_unlock(&tbl->slt_lock);
+}
+
static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
{
struct nfsd4_conn *c;
@@ -2159,11 +2223,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
else
slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
- /* Retrieve new target/highest slotid values */
- spin_lock(&session->se_slots.slt_lock);
- seq->target_highest_slotid = session->se_slots.slt_target_highest_slotid;
- seq->highest_slotid = session->se_slots.slt_highest_slotid;
- spin_unlock(&session->se_slots.slt_lock);
+ /* Adjust slot table, and retrieve new target/highest slotid values */
+ nfsd4_sequence_adjust_slot_table(session, slot,
+ seq->highest_slotid, seq);
cstate->slot = slot;
cstate->session = session;
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 7a0d8e4..c2f897f 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -129,6 +129,7 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
struct nfsd4_slot {
struct list_head sl_list;
+ unsigned long sl_generation;
u32 sl_slotid;
u32 sl_seqid;
__be32 sl_status;
@@ -146,6 +147,7 @@ struct nfsd4_slot_table {
spinlock_t slt_lock;
size_t slt_slotsize;
unsigned long slt_memused;
+ unsigned long slt_generation;
u32 slt_target_highest_slotid;
u32 slt_highest_slotid;
};
--
1.7.11.7
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] NFSD: Add support for dynamic slot changes
2012-11-29 3:17 ` [PATCH 4/4] NFSD: Add support for dynamic slot changes Trond Myklebust
@ 2012-12-06 21:29 ` J. Bruce Fields
2012-12-06 23:20 ` Myklebust, Trond
0 siblings, 1 reply; 8+ messages in thread
From: J. Bruce Fields @ 2012-12-06 21:29 UTC (permalink / raw)
To: Trond Myklebust; +Cc: linux-nfs
On Wed, Nov 28, 2012 at 10:17:43PM -0500, Trond Myklebust wrote:
> The algorithm chosen for growing/shrinking the dynamic slot table
> size is as follows:
>
> If the client is sending a sa_highest_slotid value that is greater than
> or equal to the our server target_highest_slotid, then multiply the
> value of the latter by 5/4.
>
> If, on the other hand, the sa_highest_slotid value is smaller than
> our target_highest_slotid, then try adjusting the latter to half its
> current value, or to the value of sa_highest_slotid+1, whichever is larger.
>
> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
> ---
> fs/nfsd/nfs4state.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++----
> fs/nfsd/state.h | 2 ++
> 2 files changed, 69 insertions(+), 5 deletions(-)
>
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index a1208cc..88d0de9 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -807,6 +807,7 @@ static bool nfsd4_grow_slot_table_locked(struct nfsd4_slot_table *tbl,
> if (slot != NULL){
> if (!nfsd4_get_drc_mem(tbl))
> break;
> + slot->sl_generation = tbl->slt_generation - 1;
> slot->sl_slotid = next_slotid;
> list_add_tail(&slot->sl_list, &tbl->slt_head);
> }
> @@ -853,6 +854,30 @@ static void nfsd4_free_slot_table(struct nfsd4_slot_table *tbl)
> spin_unlock(&tbl->slt_lock);
> }
>
> +static void nfsd4_fc_set_highest_slotid_locked(struct nfsd4_session *session,
> + struct nfsd4_slot_table *tbl,
> + u32 target_highest_slotid,
> + u32 highest_slotid)
> +{
> + /* Lower limit for target_highest_slotid is negotiated limit */
> + target_highest_slotid = max(target_highest_slotid,
> + session->se_fchannel.maxreqs - 1);
> + /* Lower limit for highest_slotid is target_highest_slotid */
> + highest_slotid = max(highest_slotid, target_highest_slotid);
> +
> + if (target_highest_slotid == tbl->slt_target_highest_slotid &&
> + highest_slotid == tbl->slt_highest_slotid)
> + return;
> +
> + if (!nfsd4_grow_slot_table_locked(tbl, highest_slotid, GFP_KERNEL))
> + return;
> +
> + tbl->slt_target_highest_slotid = target_highest_slotid;
> + tbl->slt_highest_slotid = highest_slotid;
> + tbl->slt_generation++;
> + nfsd4_truncate_slot_table_locked(tbl, tbl->slt_highest_slotid);
> +}
> +
> static void nfsd4_init_slot_table(struct nfsd4_slot_table *tbl,
> size_t slotsize, u32 highest_slotid)
> {
> @@ -2039,6 +2064,45 @@ out:
> return status;
> }
>
> +static void nfsd4_sequence_adjust_slot_table(struct nfsd4_session *session,
> + struct nfsd4_slot *slot, u32 sa_highest_slotid,
> + struct nfsd4_sequence *res)
> +{
> + struct nfsd4_slot_table *tbl = &session->se_slots;
> + u32 next_target;
> + u32 next_highest;
> +
> + spin_lock(&tbl->slt_lock);
> + /*
> + * If this slot hasn't seen our previous values, then don't trust
> + * that the client has seen them. Don't adjust the slot table yet.
> + */
> + if (slot->sl_generation != tbl->slt_generation)
> + goto out;
> +
> + next_target = tbl->slt_target_highest_slotid;
> +
> + /* Is the client bumping against our current window limits? */
> + if (sa_highest_slotid >= tbl->slt_target_highest_slotid) {
> + /* Yes! Grow the window size by 1/4 */
> + next_target += 1 + (tbl->slt_target_highest_slotid >> 2);
> + next_highest = next_target;
> + } else {
> + /* No! Try to shrink the window size by 1/2 */
> + next_target >>= 1;
> + if (sa_highest_slotid + 1 > next_target)
> + next_target = sa_highest_slotid + 1;
> + next_highest = tbl->slt_target_highest_slotid;
> + }
> + nfsd4_fc_set_highest_slotid_locked(session, tbl,
> + next_target, next_highest);
> +out:
> + slot->sl_generation = tbl->slt_generation;
> + res->highest_slotid = tbl->slt_highest_slotid;
> + res->target_highest_slotid = tbl->slt_target_highest_slotid;
> + spin_unlock(&tbl->slt_lock);
> +}
> +
> static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
> {
> struct nfsd4_conn *c;
> @@ -2159,11 +2223,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
> else
> slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
>
> - /* Retrieve new target/highest slotid values */
> - spin_lock(&session->se_slots.slt_lock);
> - seq->target_highest_slotid = session->se_slots.slt_target_highest_slotid;
> - seq->highest_slotid = session->se_slots.slt_highest_slotid;
> - spin_unlock(&session->se_slots.slt_lock);
> + /* Adjust slot table, and retrieve new target/highest slotid values */
> + nfsd4_sequence_adjust_slot_table(session, slot,
> + seq->highest_slotid, seq);
This is allocating under a spin lock (see the client_lock that most of
nfsd4_sequence is under.)
(But I'm not sure what we should be doing instead.)
--b.
>
> cstate->slot = slot;
> cstate->session = session;
> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index 7a0d8e4..c2f897f 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -129,6 +129,7 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)
>
> struct nfsd4_slot {
> struct list_head sl_list;
> + unsigned long sl_generation;
> u32 sl_slotid;
> u32 sl_seqid;
> __be32 sl_status;
> @@ -146,6 +147,7 @@ struct nfsd4_slot_table {
> spinlock_t slt_lock;
> size_t slt_slotsize;
> unsigned long slt_memused;
> + unsigned long slt_generation;
> u32 slt_target_highest_slotid;
> u32 slt_highest_slotid;
> };
> --
> 1.7.11.7
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH 4/4] NFSD: Add support for dynamic slot changes
2012-12-06 21:29 ` J. Bruce Fields
@ 2012-12-06 23:20 ` Myklebust, Trond
2012-12-07 13:58 ` J. Bruce Fields
0 siblings, 1 reply; 8+ messages in thread
From: Myklebust, Trond @ 2012-12-06 23:20 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: linux-nfs@vger.kernel.org
> -----Original Message-----
> From: J. Bruce Fields [mailto:bfields@fieldses.org]
> Sent: Thursday, December 06, 2012 10:29 PM
> To: Myklebust, Trond
> Cc: linux-nfs@vger.kernel.org
> Subject: Re: [PATCH 4/4] NFSD: Add support for dynamic slot changes
>
> On Wed, Nov 28, 2012 at 10:17:43PM -0500, Trond Myklebust wrote:
> > The algorithm chosen for growing/shrinking the dynamic slot table size
> > is as follows:
> >
> > If the client is sending a sa_highest_slotid value that is greater
> > than or equal to the our server target_highest_slotid, then multiply
> > the value of the latter by 5/4.
> >
> > If, on the other hand, the sa_highest_slotid value is smaller than our
> > target_highest_slotid, then try adjusting the latter to half its
> > current value, or to the value of sa_highest_slotid+1, whichever is larger.
> >
> > Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
> > ---
> > fs/nfsd/nfs4state.c | 72
> +++++++++++++++++++++++++++++++++++++++++++++++++----
> > fs/nfsd/state.h | 2 ++
> > 2 files changed, 69 insertions(+), 5 deletions(-)
> >
> > diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index
> > a1208cc..88d0de9 100644
> > --- a/fs/nfsd/nfs4state.c
> > +++ b/fs/nfsd/nfs4state.c
> > @@ -807,6 +807,7 @@ static bool nfsd4_grow_slot_table_locked(struct
> nfsd4_slot_table *tbl,
> > if (slot != NULL){
> > if (!nfsd4_get_drc_mem(tbl))
> > break;
> > + slot->sl_generation = tbl->slt_generation - 1;
> > slot->sl_slotid = next_slotid;
> > list_add_tail(&slot->sl_list, &tbl->slt_head);
> > }
> > @@ -853,6 +854,30 @@ static void nfsd4_free_slot_table(struct
> nfsd4_slot_table *tbl)
> > spin_unlock(&tbl->slt_lock);
> > }
> >
> > +static void nfsd4_fc_set_highest_slotid_locked(struct nfsd4_session
> *session,
> > + struct nfsd4_slot_table *tbl,
> > + u32 target_highest_slotid,
> > + u32 highest_slotid)
> > +{
> > + /* Lower limit for target_highest_slotid is negotiated limit */
> > + target_highest_slotid = max(target_highest_slotid,
> > + session->se_fchannel.maxreqs - 1);
> > + /* Lower limit for highest_slotid is target_highest_slotid */
> > + highest_slotid = max(highest_slotid, target_highest_slotid);
> > +
> > + if (target_highest_slotid == tbl->slt_target_highest_slotid &&
> > + highest_slotid == tbl->slt_highest_slotid)
> > + return;
> > +
> > + if (!nfsd4_grow_slot_table_locked(tbl, highest_slotid, GFP_KERNEL))
> > + return;
> > +
> > + tbl->slt_target_highest_slotid = target_highest_slotid;
> > + tbl->slt_highest_slotid = highest_slotid;
> > + tbl->slt_generation++;
> > + nfsd4_truncate_slot_table_locked(tbl, tbl->slt_highest_slotid); }
> > +
> > static void nfsd4_init_slot_table(struct nfsd4_slot_table *tbl,
> > size_t slotsize, u32 highest_slotid) { @@ -2039,6 +2064,45
> @@ out:
> > return status;
> > }
> >
> > +static void nfsd4_sequence_adjust_slot_table(struct nfsd4_session
> *session,
> > + struct nfsd4_slot *slot, u32 sa_highest_slotid,
> > + struct nfsd4_sequence *res)
> > +{
> > + struct nfsd4_slot_table *tbl = &session->se_slots;
> > + u32 next_target;
> > + u32 next_highest;
> > +
> > + spin_lock(&tbl->slt_lock);
> > + /*
> > + * If this slot hasn't seen our previous values, then don't trust
> > + * that the client has seen them. Don't adjust the slot table yet.
> > + */
> > + if (slot->sl_generation != tbl->slt_generation)
> > + goto out;
> > +
> > + next_target = tbl->slt_target_highest_slotid;
> > +
> > + /* Is the client bumping against our current window limits? */
> > + if (sa_highest_slotid >= tbl->slt_target_highest_slotid) {
> > + /* Yes! Grow the window size by 1/4 */
> > + next_target += 1 + (tbl->slt_target_highest_slotid >> 2);
> > + next_highest = next_target;
> > + } else {
> > + /* No! Try to shrink the window size by 1/2 */
> > + next_target >>= 1;
> > + if (sa_highest_slotid + 1 > next_target)
> > + next_target = sa_highest_slotid + 1;
> > + next_highest = tbl->slt_target_highest_slotid;
> > + }
> > + nfsd4_fc_set_highest_slotid_locked(session, tbl,
> > + next_target, next_highest);
> > +out:
> > + slot->sl_generation = tbl->slt_generation;
> > + res->highest_slotid = tbl->slt_highest_slotid;
> > + res->target_highest_slotid = tbl->slt_target_highest_slotid;
> > + spin_unlock(&tbl->slt_lock);
> > +}
> > +
> > static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt,
> > struct nfsd4_session *s) {
> > struct nfsd4_conn *c;
> > @@ -2159,11 +2223,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
> > else
> > slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
> >
> > - /* Retrieve new target/highest slotid values */
> > - spin_lock(&session->se_slots.slt_lock);
> > - seq->target_highest_slotid = session-
> >se_slots.slt_target_highest_slotid;
> > - seq->highest_slotid = session->se_slots.slt_highest_slotid;
> > - spin_unlock(&session->se_slots.slt_lock);
> > + /* Adjust slot table, and retrieve new target/highest slotid values */
> > + nfsd4_sequence_adjust_slot_table(session, slot,
> > + seq->highest_slotid, seq);
>
> This is allocating under a spin lock (see the client_lock that most of
> nfsd4_sequence is under.)
>
> (But I'm not sure what we should be doing instead.)
I've already fixed this issue in the latest patches: the right thing is simply to do all this after we drop the client lock. I'll send the updated patches when I get a moment: probably Saturday...
Cheers
Trond
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/4] NFSD: Add support for dynamic slot changes
2012-12-06 23:20 ` Myklebust, Trond
@ 2012-12-07 13:58 ` J. Bruce Fields
0 siblings, 0 replies; 8+ messages in thread
From: J. Bruce Fields @ 2012-12-07 13:58 UTC (permalink / raw)
To: Myklebust, Trond; +Cc: linux-nfs@vger.kernel.org
On Thu, Dec 06, 2012 at 11:20:15PM +0000, Myklebust, Trond wrote:
> > -----Original Message-----
> > From: J. Bruce Fields [mailto:bfields@fieldses.org]
> > Sent: Thursday, December 06, 2012 10:29 PM
> > To: Myklebust, Trond
> > Cc: linux-nfs@vger.kernel.org
> > Subject: Re: [PATCH 4/4] NFSD: Add support for dynamic slot changes
> >
> > On Wed, Nov 28, 2012 at 10:17:43PM -0500, Trond Myklebust wrote:
> > > @@ -2159,11 +2223,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
> > > else
> > > slot->sl_flags &= ~NFSD4_SLOT_CACHETHIS;
> > >
> > > - /* Retrieve new target/highest slotid values */
> > > - spin_lock(&session->se_slots.slt_lock);
> > > - seq->target_highest_slotid = session-
> > >se_slots.slt_target_highest_slotid;
> > > - seq->highest_slotid = session->se_slots.slt_highest_slotid;
> > > - spin_unlock(&session->se_slots.slt_lock);
> > > + /* Adjust slot table, and retrieve new target/highest slotid values */
> > > + nfsd4_sequence_adjust_slot_table(session, slot,
> > > + seq->highest_slotid, seq);
> >
> > This is allocating under a spin lock (see the client_lock that most of
> > nfsd4_sequence is under.)
> >
> > (But I'm not sure what we should be doing instead.)
>
> I've already fixed this issue in the latest patches: the right thing
> is simply to do all this after we drop the client lock.
Oh, sounds reasonable.
> I'll send the
> updated patches when I get a moment: probably Saturday...
Thanks!
--b.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-12-07 13:58 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-29 3:17 [PATCH 0/4] NFSD: Add support for session dynamic slot management Trond Myklebust
2012-11-29 3:17 ` [PATCH 1/4] NFSD: Convert the slot table to use a linked list Trond Myklebust
2012-11-29 3:17 ` [PATCH 2/4] NFSD: Make DRC memory limits work with dynamic slot allocation Trond Myklebust
2012-11-29 3:17 ` [PATCH 3/4] NFSD: Add slot table support for target_highest_slotid and highest_slotid Trond Myklebust
2012-11-29 3:17 ` [PATCH 4/4] NFSD: Add support for dynamic slot changes Trond Myklebust
2012-12-06 21:29 ` J. Bruce Fields
2012-12-06 23:20 ` Myklebust, Trond
2012-12-07 13:58 ` J. Bruce Fields
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).