NFSv4.1: Support dynamic resizing of the session slot table
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 20 Nov 2012 19:45:48 +0000 (14:45 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 5 Dec 2012 23:30:42 +0000 (00:30 +0100)
Allow the server to control the size of the session slot table
by adjusting the value of sr_target_max_slots in the reply to the
SEQUENCE operation.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
include/linux/nfs_fs_sb.h

index 62212231ce622f7b30f0c77a76e01497c2cbc639..1792ece8b53ce878a5497e4d218b3c0af7f6a4d4 100644 (file)
@@ -492,10 +492,17 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
 static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl,
                u32 target_highest_slotid)
 {
+       unsigned int max_slotid, i;
+
        if (tbl->target_highest_slotid == target_highest_slotid)
                return;
        tbl->target_highest_slotid = target_highest_slotid;
        tbl->generation++;
+
+       max_slotid = min(tbl->max_slots - 1, tbl->target_highest_slotid);
+       for (i = tbl->max_slotid + 1; i <= max_slotid; i++)
+               rpc_wake_up_next(&tbl->slot_tbl_waitq);
+       tbl->max_slotid = max_slotid;
 }
 
 void nfs41_set_target_slotid(struct nfs4_slot_table *tbl,
@@ -622,8 +629,8 @@ static struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl)
        dprintk("--> %s used_slots=%04lx highest_used=%u max_slots=%u\n",
                __func__, tbl->used_slots[0], tbl->highest_used_slotid,
                tbl->max_slots);
-       slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slots);
-       if (slotid >= tbl->max_slots)
+       slotid = find_first_zero_bit(tbl->used_slots, tbl->max_slotid + 1);
+       if (slotid > tbl->max_slotid)
                goto out;
        __set_bit(slotid, tbl->used_slots);
        if (slotid > tbl->highest_used_slotid ||
@@ -5744,6 +5751,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
        tbl->highest_used_slotid = NFS4_NO_SLOT;
        tbl->target_highest_slotid = max_slots - 1;
        tbl->server_highest_slotid = max_slots - 1;
+       tbl->max_slotid = max_slots - 1;
        for (i = 0; i < tbl->max_slots; i++)
                tbl->slots[i].seq_nr = ivalue;
        spin_unlock(&tbl->slot_tbl_lock);
index 842cb8c2f65deed6d3a04bb15d5c7fa5b5dc267b..1b7fa73c9436c95b1563b4480d2d54c3f62f5de4 100644 (file)
@@ -254,15 +254,14 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
 {
        struct nfs4_session *ses = clp->cl_session;
        struct nfs4_slot_table *tbl;
-       int max_slots;
+       unsigned int i;
 
        if (ses == NULL)
                return;
        tbl = &ses->fc_slot_table;
        if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
                spin_lock(&tbl->slot_tbl_lock);
-               max_slots = tbl->max_slots;
-               while (max_slots--) {
+               for (i = 0; i <= tbl->max_slotid; i++) {
                        if (rpc_wake_up_first(&tbl->slot_tbl_waitq,
                                                nfs4_set_task_privileged,
                                                NULL) == NULL)
@@ -2043,6 +2042,7 @@ static int nfs4_recall_slot(struct nfs_client *clp)
        old = fc_tbl->slots;
        fc_tbl->slots = new;
        fc_tbl->max_slots = fc_tbl->target_highest_slotid + 1;
+       fc_tbl->max_slotid = fc_tbl->target_highest_slotid;
        clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
        spin_unlock(&fc_tbl->slot_tbl_lock);
 
index 646e64bbff4c49b35b33f3b81292795df738b566..30715508fade2f399cf1862a13ac6e1dcfe05011 100644 (file)
@@ -215,6 +215,7 @@ struct nfs4_slot_table {
        spinlock_t      slot_tbl_lock;
        struct rpc_wait_queue   slot_tbl_waitq; /* allocators may wait here */
        u32             max_slots;              /* # slots in table */
+       u32             max_slotid;             /* Max allowed slotid value */
        u32             highest_used_slotid;    /* sent to server on each SEQ.
                                                 * op for dynamic resizing */
        u32             target_highest_slotid;  /* Server max_slot target */