[pnfs] [PATCH 1/2] Slot Table Implementation

William A. (Andy) Adamson andros at citi.umich.edu
Tue Mar 20 05:33:49 EDT 2007


On 3/19/07, Benny Halevy <bhalevy at panasas.com> wrote:
>
> Iyer, Rahul wrote:
>
> >Yes, this seems to be a good optimization. I can work on the
> >optimizations once I have the callback path implemented. I'd rather have
> >a  full featured prototype than an efficient but incomplete one. Does
> >that sound fine? I've added an issue to the pNFS wiki.
> >
> >
> Sounds good.
> Thank you,
> Benny




ok. so i will add  the latest client slot patches to  the tree.

-->Andy

>Thanks
> >Regards
> >Rahul
> >
> >
> >
> >
> >>-----Original Message-----
> >>From: Benny Halevy [mailto:bhalevy at panasas.com]
> >>Sent: Monday, March 19, 2007 10:48 AM
> >>To: Iyer, Rahul
> >>Cc: pnfs at linux-nfs.org
> >>Subject: Re: [pnfs] [PATCH 1/2] Slot Table Implementation
> >>
> >>One more optimization that Brent suggests is keeping a single
> >>"lowest free slot" index per slot table which would help
> >>reduce the table scan cost.
> >>
> >>When you allocate that slot mark the index as "used".
> >>When you free a slot that has a lower id, or if the index is
> >>marked as used, just update that index.
> >>When you want to allocate a slot and the index is marked as
> >>used, just scan from there upward until you find the next
> >>free one and update the index as "used".
> >>
> >>Benny
> >>
> >>Benny Halevy wrote:
> >>
> >>
> >>
> >>>Hmm, keeping the free list in order has the same O(n) complexity as
> >>>scanning for the first free slot.  We just need a fast way
> >>>
> >>>
> >>to tell if
> >>
> >>
> >>>there are any free slots (a list, or a counter) for the queue sleep
> >>>condition.  A single spin_lock for scanning the slot table
> >>>
> >>>
> >>(or for the
> >>
> >>
> >>>list) should more efficient than a test_and_set bit per slot (when
> >>>there's enough load) and so is a single queue rather than a
> >>>
> >>>
> >>queue per
> >>
> >>
> >>>slot.  The latter is crucial for getting to the first slot
> >>>
> >>>
> >>that becomes
> >>
> >>
> >>>available and not waiting on average half the response time in the
> >>>system.
> >>>
> >>>Benny
> >>>
> >>>Iyer, Rahul wrote:
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>>Hi Benny,
> >>>>My first idea was similar to this. That was the reason I had the
> >>>>unused slots and used slots lists. The reason I abandoned that was
> >>>>because it would be difficult to get the lowest numbered slot. The
> >>>>draft suggests that the client should use the lowest
> >>>>
> >>>>
> >>numbered slot so
> >>
> >>
> >>>>that the server can reclaim slots from the client if it
> >>>>
> >>>>
> >>sees that they
> >>
> >>
> >>>>are under-utilized (at least that's what I understand).It is not a
> >>>>hard requirement, but one that is recommended.
> >>>>>From draft 10, Section 2.4.10.1, Paragraph 12
> >>>>"The requester is required to use the lowest available slot when
> >>>>issuing a new request. This way, the replier may be able to retire
> >>>>slot entries faster."
> >>>>
> >>>>Further, this email exchange adds some more insight:
> >>>>http://www1.ietf.org/mail-archive/web/nfsv4/current/msg03997.html
> >>>>
> >>>>The problem I foresaw with the lists is that keeping the
> >>>>
> >>>>
> >>lists ordered
> >>
> >>
> >>>>is almost as much work as having separate lists. As for the
> >>>>
> >>>>
> >>atomic_t
> >>
> >>
> >>>>variables, I'm not too hot about the atomic variables.
> >>>>
> >>>>
> >>test_and_set is
> >>
> >>
> >>>>a bus locking instruction and so isn't such a great idea... the
> >>>>spin_locks are "optimized for the fast path", which is getting the
> >>>>spin_locks, but they're too much of a big hammer maybe.
> >>>>
> >>>>
> >>rw_locks might
> >>
> >>
> >>>>be a better idea, but i'm not 100% convinced... I'm pretty
> >>>>
> >>>>
> >>sure they
> >>
> >>
> >>>>use some sort of bus locking instruction too. As for the current
> >>>>implementation, scaling shouldn't be too much of a problem as the
> >>>>number of slots is likely to be small (few tens) and the
> >>>>
> >>>>
> >>worst case is
> >>
> >>
> >>>>bounded. I agree it is linear time, but at least the worst case
> >>>>doesn't run away from us. Since the RPC slots is a tunable
> >>>>
> >>>>
> >>parameter,
> >>
> >>
> >>>>it would be interesting to see what an "optimal" rpc slot
> >>>>
> >>>>
> >>count is...
> >>
> >>
> >>>>as in at what point does adding more slots make no difference to
> >>>>performance. Is there such a study?
> >>>>
> >>>>Another idea I can think of is to have a single lock that
> >>>>
> >>>>
> >>protects the
> >>
> >>
> >>>>whole slot table. We grab the lock and run down the slot table to
> >>>>select our slot (and set need_to_sleep if required), and
> >>>>
> >>>>
> >>then release
> >>
> >>
> >>>>the lock. Then, if need_to_sleep is set, we grab the lock,
> >>>>
> >>>>
> >>increment
> >>
> >>
> >>>>nr_waiters for the slot, release the lock and sleep.
> >>>>Should this be a spin_lock or an rw_lock, I'm not sure...
> >>>>
> >>>>
> >>spin_locks
> >>
> >>
> >>>>will harm the concurrency because it would lock out
> >>>>
> >>>>
> >>parallel reads. On
> >>
> >>
> >>>>the other hand, rw_locks are biased towards readers or writers (not
> >>>>sure which for Linux), so that may not be a good thing.
> >>>>
> >>>>That being said, I'm not wedded to the current
> >>>>
> >>>>
> >>implementation in any
> >>
> >>
> >>>>way... comments and better algorithms are welcome. This was
> >>>>
> >>>>
> >>just one
> >>
> >>
> >>>>way that I thought made sense.
> >>>>Thanks,
> >>>>Regards
> >>>>Rahul
> >>>>
> >>>>
> >>>>-----Original Message-----
> >>>>From: Benny Halevy [mailto:bhalevy at panasas.com]
> >>>>Sent: Sat 3/17/2007 3:54 AM
> >>>>To: Iyer, Rahul
> >>>>Cc: pnfs at linux-nfs.org
> >>>>Subject: Re: [pnfs] [PATCH 1/2] Slot Table Implementation
> >>>>
> >>>>Rahul, this is not urgent but I really think we should move to a
> >>>>single queue for several reason.  With your implementation when all
> >>>>slots are used you have to do max_slots test_and_set operations to
> >>>>discover that.  This will just not scale.   I agree with your point
> >>>>about semaphores and renegotiating the number of slots so how about
> >>>>this (sketch) instead:
> >>>>
> >>>>nfs41_proc_sequence_done()
> >>>>{
> >>>>       int need_wakeup = 0;
> >>>>
> >>>>       spin_lock(&res->channel->channel_lock);
> >>>>       list_add(&res->slot->slot_list,
> >>>>
> >>>>
> >>&res->channel->unused_slots);
> >>
> >>
> >>>>       spin_unlock(&res->channel->channel_lock);
> >>>>
> >>>>       /* Wake up the threads waiting on this session */
> >>>>       rpc_wake_up(&res->channel->sl_waitq);
> >>>>
> >>>>       return status;
> >>>>}
> >>>>
> >>>>struct nfs4_slot *nfs4_find_slot(struct nfs4_channel *channel) {
> >>>>       struct nfs4_slot *slot;
> >>>>
> >>>>       might_sleep();
> >>>>
> >>>>       for (;;) {
> >>>>               int ret =
> >>>>
> >>>>
> >>wait_event_interruptible(&channel->sl_waitq,
> >>
> >>
> >>>>
> >>>>!list_empty(&channel->unused_slots));
> >>>>               if (unlikely(ret) {
> >>>>                       BUG_ON(ret != -ERESTARTSYS);
> >>>>                       break;
> >>>>               }
> >>>>
> >>>>               spin_lock(&channel->channel_lock);
> >>>>               if (unlikely(list_empty(&channel->unused_slots))) {
> >>>>                       spin_unlock(&channel->channel_lock);
> >>>>                       continue;
> >>>>               }
> >>>>               slot = list_entry(channel->unused_slots.next,
> >>>>                                 struct nfs4_slot,
> >>>>                                 slot_list);
> >>>>               list_del(&slot->slot_list);
> >>>>               spin_unlock(&channel->channel_lock);
> >>>>               return slot;
> >>>>       }
> >>>>
> >>>>       return NULL;
> >>>>}
> >>>>
> >>>>
> >>>>Iyer, Rahul wrote:
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>>Hi Benny,
> >>>>>A comment inline...
> >>>>>Regards
> >>>>>Rahul
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>>-----Original Message-----
> >>>>>>From: Benny Halevy [mailto:bhalevy at panasas.com]
> >>>>>>Sent: Friday, March 16, 2007 2:24 AM
> >>>>>>To: Iyer, Rahul
> >>>>>>Cc: pnfs at linux-nfs.org
> >>>>>>Subject: Re: [pnfs] [PATCH 1/2] Slot Table Implementation
> >>>>>>
> >>>>>>Rahul, my comments below...
> >>>>>>
> >>>>>>Benny
> >>>>>>
> >>>>>>iyer at netapp.com wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>From: iyer <iyer at netapp.com>
> >>>>>>>
> >>>>>>>Added code to implement a slot table.
> >>>>>>>
> >>>>>>>Signed-off-by: iyer <iyer at netapp.com>
> >>>>>>>---
> >>>>>>>fs/nfs/nfs41_sessions.h        |   62 --------
> >>>>>>>fs/nfs/nfs4_fs.h               |    2 +-
> >>>>>>>fs/nfs/nfs4proc.c              |  326
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>+++++++++++++++++++++++++++++++++++-----
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>fs/nfs/nfs4xdr.c               |   24 ++--
> >>>>>>>fs/nfs/super.c                 |    6 +-
> >>>>>>>include/linux/nfs41_sessions.h |   72 +++++++++
> >>>>>>>include/linux/nfs_xdr.h        |    4 +
> >>>>>>>include/linux/nfsd/state.h     |    2 -
> >>>>>>>8 files changed, 378 insertions(+), 120 deletions(-)  delete mode
> >>>>>>>100644 fs/nfs/nfs41_sessions.h  create mode 100644
> >>>>>>>include/linux/nfs41_sessions.h
> >>>>>>>
> >>>>>>>diff --git a/fs/nfs/nfs41_sessions.h
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>b/fs/nfs/nfs41_sessions.h deleted
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>file mode 100644 index fc658c5..0000000
> >>>>>>>--- a/fs/nfs/nfs41_sessions.h
> >>>>>>>+++ /dev/null
> >>>>>>>@@ -1,62 +0,0 @@
> >>>>>>>-#ifndef __NFS4_1_SESSIONS_H__
> >>>>>>>-#define __NFS4_1_SESSIONS_H__
> >>>>>>>-
> >>>>>>>-typedef unsigned char               sessionid_t[16];
> >>>>>>>-typedef u32                 streamchannel_attrs;
> >>>>>>>-typedef u32                 rdmachannel_attrs;
> >>>>>>>-
> >>>>>>>-struct nfs4_channel_attrs {
> >>>>>>>-    unsigned long           max_rqst_sz;
> >>>>>>>-    unsigned long           max_resp_sz;
> >>>>>>>-    unsigned long           max_resp_sz_cached;
> >>>>>>>-    unsigned long           max_ops;
> >>>>>>>-    unsigned long           max_reqs;
> >>>>>>>-    streamchannel_attrs     stream_attrs;
> >>>>>>>-    rdmachannel_attrs       rdma_attrs;
> >>>>>>>-};
> >>>>>>>-
> >>>>>>>-struct nfs4_channel {
> >>>>>>>-    struct nfs4_channel_attrs       chan_attrs;
> >>>>>>>-    unsigned long                   nr_conns;
> >>>>>>>-    struct list_head                rpc_clients;
> >>>>>>>-};
> >>>>>>>-
> >>>>>>>-struct nfs4_session {
> >>>>>>>-    /* Session related params */
> >>>>>>>-    sessionid_t             sess_id;
> >>>>>>>-    u32                     seqid;  /* The seqid returned
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>by exchange_id */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>-    u32                     persist;
> >>>>>>>-    u32                     header_padding;
> >>>>>>>-    u32                     hash_alg;
> >>>>>>>-    u32                     ssv_len;
> >>>>>>>-    u32                     use_for_back_chan;
> >>>>>>>-    u32                     rdma_mode;
> >>>>>>>-
> >>>>>>>-    /* Slotid management */
> >>>>>>>-    unsigned long           nr_slots_in_use;
> >>>>>>>-    struct list_head        slots_in_use;
> >>>>>>>-    struct list_head        unused_slots;
> >>>>>>>-    struct rpc_wait_queue   slot_waitq;
> >>>>>>>-
> >>>>>>>-    /* The fore and back channel */
> >>>>>>>-    struct nfs4_channel     fore_channel;
> >>>>>>>-    struct nfs4_channel     back_channel;
> >>>>>>>-
> >>>>>>>-    unsigned int            expired;
> >>>>>>>-    struct nfs4_client *    client;
> >>>>>>>-    struct list_head        session_hashtbl;
> >>>>>>>-    spinlock_t              session_lock;
> >>>>>>>-    /* To prevent races between create_session and sequence */
> >>>>>>>-    int                     mutating;
> >>>>>>>-    struct semaphore        session_sem;
> >>>>>>>-    atomic_t        ref_count;
> >>>>>>>-};
> >>>>>>>-
> >>>>>>>-struct nfs4_slot {
> >>>>>>>-    u32                     slot_nr;
> >>>>>>>-    u32                     seq_nr;
> >>>>>>>-    struct nfs4_session *   session;
> >>>>>>>-    struct list_head        slot_list;
> >>>>>>>-};
> >>>>>>>-
> >>>>>>>-#endif
> >>>>>>>diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index
> >>>>>>>195d757..e50657e 100644
> >>>>>>>--- a/fs/nfs/nfs4_fs.h
> >>>>>>>+++ b/fs/nfs/nfs4_fs.h
> >>>>>>>@@ -9,7 +9,7 @@
> >>>>>>>#ifndef __LINUX_FS_NFS_NFS4_FS_H
> >>>>>>>#define __LINUX_FS_NFS_NFS4_FS_H
> >>>>>>>
> >>>>>>>-#include "nfs41_sessions.h"
> >>>>>>>+#include <linux/nfs41_sessions.h>
> >>>>>>>
> >>>>>>>#ifdef CONFIG_NFS_V4
> >>>>>>>#define NFSV4_MAX_MINORVERSION 1
> >>>>>>>diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index
> >>>>>>>167ff4a..28513a1 100644
> >>>>>>>--- a/fs/nfs/nfs4proc.c
> >>>>>>>+++ b/fs/nfs/nfs4proc.c
> >>>>>>>@@ -49,6 +49,7 @@
> >>>>>>>#include <linux/namei.h>
> >>>>>>>#include <linux/mount.h>
> >>>>>>>#include <linux/module.h>
> >>>>>>>+#include <linux/bitops.h>
> >>>>>>>
> >>>>>>>#include "nfs4_fs.h"
> >>>>>>>#include "delegation.h"
> >>>>>>>@@ -221,8 +222,10 @@ static int
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs41_proc_sequence_done(struct nfs4_session *session, struct
> >>>>>>nfs41_s
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   unsigned long timestamp;
> >>>>>>>   struct nfs4_client *clp;
> >>>>>>>
> >>>>>>>-    if (!session || !(clp = session->client))
> >>>>>>>-            return 0;
> >>>>>>>+    if (!session || !(clp = session->client)) {
> >>>>>>>+            printk(KERN_EMERG "%s is NULL!!!\n",
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>(!session)?"session":"clp");
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+            BUG();
> >>>>>>>+    }
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>For performance reasons the defensive code should only be active
> >>>>>>with kernel debugging.  The conditional statement above is always
> >>>>>>executed needlessly and is not as clean as it could be because of
> >>>>>>the assignment embedded in the boolean expression.
> >>>>>>
> >>>>>>
> >>Therefore, this
> >>
> >>
> >>>>>>better be coded like this:
> >>>>>>
> >>>>>>    BUG_ON(!session);
> >>>>>>    clp = session->client;
> >>>>>>    BUG_ON(!clp);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   if (!status) {
> >>>>>>>           timestamp = jiffies;
> >>>>>>>@@ -233,17 +236,131 @@ static int
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs41_proc_sequence_done(struct nfs4_session *session, struct
> >>>>>>nfs41_s
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>           spin_unlock(&clp->cl_lock);
> >>>>>>>   }
> >>>>>>>
> >>>>>>>+    /* Clear the 'busy' bit on the slot that was used */
> >>>>>>>+    smp_mb__before_clear_bit();
> >>>>>>>+    clear_bit(NFS4_SLOT_BUSY, &res->slot->flags);
> >>>>>>>+    smp_mb__after_clear_bit();
> >>>>>>>+
> >>>>>>>+    printk(KERN_EMERG "waking up waiters on slot %d\n",
> >>>>>>>+res->slot->slot_nr);
> >>>>>>>+
> >>>>>>>+    /* Wake up the threads waiting on this slot */
> >>>>>>>+    wake_up_bit(&res->slot->flags, NFS4_SLOT_BUSY);
> >>>>>>>+
> >>>>>>>   return status;
> >>>>>>>}
> >>>>>>>
> >>>>>>>+static int nfs4_wait_bit_interruptible(void *word) {
> >>>>>>>+    if (signal_pending(current))
> >>>>>>>+            return -ERESTARTSYS;
> >>>>>>>+    schedule();
> >>>>>>>+    return 0;
> >>>>>>>+}
> >>>>>>>+
> >>>>>>>+/* Find the lowest numbered slot or sleep on the least
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>loaded slot */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+struct nfs4_slot *nfs4_find_slot(struct nfs4_channel *channel) {
> >>>>>>>+    struct nfs4_slot_table *tbl;
> >>>>>>>+    struct nfs4_slot *slot;
> >>>>>>>+    struct nfs4_slot *target_slot;
> >>>>>>>+    u32 max_slots;
> >>>>>>>+    u32 min_waiters;
> >>>>>>>+    int i;
> >>>>>>>+    int need_to_sleep;
> >>>>>>>+
> >>>>>>>+    might_sleep();
> >>>>>>>+
> >>>>>>>+    tbl = &channel->slot_table;
> >>>>>>>+    min_waiters = tbl->slots[0].nr_waiters;
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>atomic_read()
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    target_slot = &tbl->slots[0];
> >>>>>>>+
> >>>>>>>+    spin_lock(&tbl->slot_tbl_lock);
> >>>>>>>+    /* Make a local copy of max slots so we don't need to
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>hold it through
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+     * out.
> >>>>>>>+     * XXX Will need to revalidate this if slots are reclaimed
> >>>>>>>+     */
> >>>>>>>+    max_slots = tbl->max_slots;
> >>>>>>>+    spin_unlock(&tbl->slot_tbl_lock);
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>Using a spinlock here is unreasonably expensive when you
> >>>>>>
> >>>>>>
> >>could use
> >>
> >>
> >>>>>>atomic counters since the lock overhead is not amortized over
> >>>>>>multiple accesses to the structure.
> >>>>>>max_slots and nr_waiters should be defined as atomic_t and atomic
> >>>>>>operations be used to access them; Alternatively use one spinlock
> >>>>>>for the whole channel around the outer loop
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+
> >>>>>>>+    do {
> >>>>>>>+            need_to_sleep = 1;
> >>>>>>>+            for (i = 0; i <  max_slots; ++i) {
> >>>>>>>+                    slot = &tbl->slots[i];
> >>>>>>>+                    if (!test_and_set_bit(NFS4_SLOT_BUSY,
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>&slot->flags)){
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                            /* We found an empty slot */
> >>>>>>>+                            target_slot = slot;
> >>>>>>>+                            need_to_sleep = 0;
> >>>>>>>+                            break;
> >>>>>>>+                    }
> >>>>>>>+
> >>>>>>>+                    spin_lock(&slot->slot_lock);
> >>>>>>>+                    if (min_waiters > slot->nr_waiters) {
> >>>>>>>+                            min_waiters = slot->nr_waiters;
> >>>>>>>+                            target_slot = slot;
> >>>>>>>+                    }
> >>>>>>>+                    spin_unlock(&slot->slot_lock);
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>why lock? use atomic_read(&slot->nr_waiters) also, if several
> >>>>>>threads go through this code in parallel they will pick the same
> >>>>>>target_slot so you want to increment.
> >>>>>>That's another reason to use a bigger lock.
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>Using atomic_t is a bit hard when you have to do compare
> >>>>>
> >>>>>
> >>and set kind
> >>
> >>
> >>>>>of operations...
> >>>>>Like for instance:
> >>>>>
> >>>>>If (min_waiters > slot->nr_waiters) {
> >>>>>     min_waiters = slot->nr_waiters;
> >>>>>     target_slot = slot;
> >>>>>}
> >>>>>
> >>>>>Doing the above atomically is hard with atomic variables
> >>>>>
> >>>>>
> >>only because
> >>
> >>
> >>>>>the whole sequence needs to be atomic. However, I can change the
> >>>>>spin_lock used to rwlock_t. This should better solve the
> >>>>>
> >>>>>
> >>problem. Right?
> >>
> >>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>>>+                    printk(KERN_EMERG "slot %d has busy bit
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>%s and nr_waiters is %u\n"
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                                    , slot->slot_nr,
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>(need_to_sleep)?"set":"unset",
> >>
> >>
> >>>>>>>+                                    slot->nr_waiters);
> >>>>>>>+            }
> >>>>>>>+
> >>>>>>>+            /* Check whether we need to sleep. If so, sleep
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>on the BUSY bit
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+             * Increment the nr_waiters before sleeping and
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>decrement it
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+             * when woken up
> >>>>>>>+             */
> >>>>>>>+            if (need_to_sleep) {
> >>>>>>>+                    printk(KERN_EMERG "sleeping on slot %d;
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>seq_nr: %d\n",
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                                    target_slot->slot_nr,
> >>>>>>>+                                    target_slot->seq_nr);
> >>>>>>>+                    spin_lock(&target_slot->slot_lock);
> >>>>>>>+                    ++target_slot->nr_waiters;
> >>>>>>>+                    spin_unlock(&target_slot->slot_lock);
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>atomic_inc()
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+
> >>>>>>>+                    /* XXX: We need to check the return value of
> >>>>>>>+                     * eait_on_bit so that we can check if it's
> >>>>>>>+                     * interrupted.
> >>>>>>>+                     */
> >>>>>>>+                    wait_on_bit(&target_slot->flags,
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>NFS4_SLOT_BUSY,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                                    nfs4_wait_bit_interruptible,
> >>>>>>>+                                    TASK_INTERRUPTIBLE);
> >>>>>>>+
> >>>>>>>+                    spin_lock(&target_slot->slot_lock);
> >>>>>>>+                    --target_slot->nr_waiters;
> >>>>>>>+                    spin_unlock(&target_slot->slot_lock);
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>atomic_dec()
> >>>>>>
> >>>>>>But wait a second, why do you want a queue per slot to begin with?
> >>>>>>It seems like you can just go with a semaphore initialized to the
> >>>>>>number of slots, do down_interruptible before scanning for a free
> >>>>>>slot and up in nfs41_proc_sequence_done. Take a spin lock to scan
> >>>>>>the slot table (last index can be saved and rotated for
> >>>>>>
> >>>>>>
> >>uniformity)
> >>
> >>
> >>>>>>and if not free slot is found do a
> >>>>>>BUG() since the semaphore should prevent that from happening;
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+            }
> >>>>>>>+            else
> >>>>>>>+                    break;
> >>>>>>>+    }while (test_and_set_bit(NFS4_SLOT_BUSY,
> >>>>>>>+ &target_slot->flags));
> >>>>>>>+
> >>>>>>>+    printk(KERN_EMERG "slot id: %u\nseqid: %u\n
> >>>>>>>
> >>>>>>>
> >>max_slots: %u\n",
> >>
> >>
> >>>>>>>+                    target_slot->slot_nr, target_slot->seq_nr,
> >>>>>>>+                            max_slots);
> >>>>>>>+
> >>>>>>>+    return target_slot;
> >>>>>>>+}
> >>>>>>>+
> >>>>>>>static int _nfs41_proc_setup_sequence(struct nfs4_session
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>*session,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>struct nfs41_sequence_args *args, struct
> >>>>>>>
> >>>>>>>
> >>nfs41_sequence_res *res)  {
> >>
> >>
> >>>>>>>   u32 *ptr;
> >>>>>>>-
> >>>>>>>+    struct nfs4_slot *slot;
> >>>>>>>+
> >>>>>>>   ptr = (u32 *)session->sess_id;
> >>>>>>>   dprintk("%s: %u:%u:%u:%u\n", __FUNCTION__, ptr[0],
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>ptr[1], ptr[2],
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>ptr[3]);
> >>>>>>>
> >>>>>>>-    memcpy(args->sessionid, (unsigned char
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>*)session->sess_id, NFS4_MAX_SESSIONID_LEN);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    memcpy(args->sessionid, (unsigned char *)session->sess_id,
> >>>>>>>+                                    NFS4_MAX_SESSIONID_LEN);
> >>>>>>>+
> >>>>>>>+       slot = nfs4_find_slot(&session->fore_channel);
> >>>>>>>+
> >>>>>>>+       /* XXX: Do we always increment this? Are there any
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>errors for which we
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    * don't increment the sequence number?
> >>>>>>>+    */
> >>>>>>>+       args->seqid = slot->seq_nr++;
> >>>>>>>+       args->slotid = slot->slot_nr;
> >>>>>>>+       args->maxslots =
> >>>>>>>+ session->fore_channel.slot_table.max_slots;
> >>>>>>>+
> >>>>>>>+       res->slot = slot;
> >>>>>>>
> >>>>>>>   return 0;
> >>>>>>>}
> >>>>>>>@@ -1685,11 +1802,6 @@ static int nfs4_proc_get_root(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs_server *server, struct nfs_fh *fhandle,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   };
> >>>>>>>   int status;
> >>>>>>>
> >>>>>>>-    if (server->rpc_ops->setup_sequence && (status =
> >>>>>>>-
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>server->rpc_ops->setup_sequence(server->nfs4_state->cl_session,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>-        &seqargs, &seqres)))
> >>>>>>>-            return status;
> >>>>>>>-
> >>>>>>>   /*
> >>>>>>>    * Now we do a separate LOOKUP for each component of
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>the mount path.
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>    * The LOOKUPs are done separately so that we can
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>conveniently @@
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>-1714,9 +1826,21 @@ static int nfs4_proc_get_root(struct
> >>>>>>>
> >>>>>>>
> >>nfs_server
> >>
> >>
> >>>>>>>*server, struct nfs_fh *fhandle,
> >>>>>>>
> >>>>>>>           do {
> >>>>>>>                   nfs_fattr_init(fattr);
> >>>>>>>+                    if (server->rpc_ops->setup_sequence &&
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>(status =
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                            server->rpc_ops->setup_sequence(
> >>>>>>>+                            server->nfs4_state->cl_session,
> >>>>>>>+                            &seqargs, &seqres)))
> >>>>>>>+                            return status;
> >>>>>>>+
> >>>>>>>                   status = nfs4_handle_exception(server,
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>rpc_call_sync(server->client, &msg, 0),
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>                                   &exception);
> >>>>>>>+
> >>>>>>>+                    if (server->rpc_ops->sequence_done)
> >>>>>>>+                            server->rpc_ops->sequence_done(
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>server->nfs4_state->cl_session,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                                            &seqres, status);
> >>>>>>>+
> >>>>>>>           } while (exception.retry);
> >>>>>>>           if (status == 0)
> >>>>>>>                   continue;
> >>>>>>>@@ -1731,10 +1855,6 @@ static int nfs4_proc_get_root(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs_server *server, struct nfs_fh *fhandle,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   if (status == 0)
> >>>>>>>           status = nfs4_do_fsinfo(server, fhandle, info);
> >>>>>>>out:
> >>>>>>>-    if (server->rpc_ops->sequence_done)
> >>>>>>>-
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>server->rpc_ops->sequence_done(server->nfs4_state->cl_session,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>-                                            &seqres, status);
> >>>>>>>-
> >>>>>>>   return nfs4_map_errors(status); }
> >>>>>>>
> >>>>>>>@@ -3268,6 +3388,7 @@ int nfs4_proc_async_sequence(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs4_client *clp, struct rpc_cred *cred)
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   ret = rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
> >>>>>>>   &nfs4_sequence_ops, (void *)jiffies);
> >>>>>>>
> >>>>>>>+        nfs41_proc_sequence_done(clp->cl_session, res, ret);
> >>>>>>>out:
> >>>>>>>   return ret;
> >>>>>>>out_free:
> >>>>>>>@@ -3581,14 +3702,6 @@ nfs4_async_handle_error(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>rpc_task *task, const struct nfs_server *server)
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   return 0;
> >>>>>>>}
> >>>>>>>
> >>>>>>>-static int nfs4_wait_bit_interruptible(void *word) -{
> >>>>>>>-    if (signal_pending(current))
> >>>>>>>-            return -ERESTARTSYS;
> >>>>>>>-    schedule();
> >>>>>>>-    return 0;
> >>>>>>>-}
> >>>>>>>-
> >>>>>>>static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct
> >>>>>>>nfs4_client *clp)  {
> >>>>>>>   sigset_t oldset;
> >>>>>>>@@ -3823,6 +3936,111 @@ int nfs4_proc_get_lease_time(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs4_client *clp, struct nfs_fsinfo *fsinfo)
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   return status;
> >>>>>>>}
> >>>>>>>
> >>>>>>>+/* Initialize a slot table */
> >>>>>>>+int nfs4_init_slot_table(struct nfs4_channel *channel) {
> >>>>>>>+    int i;
> >>>>>>>+    struct nfs4_slot_table *tbl;
> >>>>>>>+    struct nfs4_slot *slot;
> >>>>>>>+
> >>>>>>>+    tbl = &channel->slot_table;
> >>>>>>>+    tbl->max_slots = channel->chan_attrs.max_reqs;
> >>>>>>>+
> >>>>>>>+    tbl->slots = kzalloc(tbl->max_slots * sizeof(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs4_slot), GFP_ATOMIC);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    if (!tbl->slots)
> >>>>>>>+            return -ENOMEM;
> >>>>>>>+
> >>>>>>>+    spin_lock_init(&tbl->slot_tbl_lock);
> >>>>>>>+
> >>>>>>>+    for (i = 0; i < tbl->max_slots; ++i) {
> >>>>>>>+            slot = &tbl->slots[i];
> >>>>>>>+
> >>>>>>>+            slot->slot_nr = i;
> >>>>>>>+            slot->seq_nr = 1;
> >>>>>>>+            slot->flags = 0;
> >>>>>>>+            slot->nr_waiters = 0;
> >>>>>>>+            spin_lock_init(&slot->slot_lock);
> >>>>>>>+    }
> >>>>>>>+
> >>>>>>>+    return 0;
> >>>>>>>+}
> >>>>>>>+
> >>>>>>>+/* Destroy the slot table */
> >>>>>>>+void nfs4_destroy_slot_table(struct nfs4_channel *channel) {
> >>>>>>>+    int i;
> >>>>>>>+    struct nfs4_slot *slot;
> >>>>>>>+    struct nfs4_slot_table *tbl;
> >>>>>>>+
> >>>>>>>+    tbl = &channel->slot_table;
> >>>>>>>+
> >>>>>>>+    for (i = 0; i < tbl->max_slots;++i) {
> >>>>>>>+            slot = &tbl->slots[i];
> >>>>>>>+
> >>>>>>>+            if (slot->nr_waiters)
> >>>>>>>+                    BUG();
> >>>>>>>+    }
> >>>>>>>+
> >>>>>>>+    kfree(channel->slot_table.slots);
> >>>>>>>+    channel->slot_table.slots = NULL;
> >>>>>>>+
> >>>>>>>+    return;
> >>>>>>>+}
> >>>>>>>+
> >>>>>>>+/* dump the channel attributes */
> >>>>>>>+void nfs4_dump_channel_attrs(struct nfs4_channel_attrs *attrs) {
> >>>>>>>+    printk(KERN_INFO "max_rqst_sz: %u\n", attrs->max_rqst_sz);
> >>>>>>>+    printk(KERN_INFO "max_resp_sz: %u\n", attrs->max_resp_sz);
> >>>>>>>+    printk(KERN_INFO "max_resp_sz_cached: %u\n",
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>attrs->max_resp_sz_cached);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    printk(KERN_INFO "max_ops: %u\n", attrs->max_ops);
> >>>>>>>+    printk(KERN_INFO "max_reqs: %u\n", attrs->max_reqs); }
> >>>>>>>+
> >>>>>>>+/* Initialize the values to be used by the client in
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>CREATE_SESSION
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+*/ void nfs4_init_channel_attrs(struct nfs4_client *clp,
> >>>>>>>+                            struct nfs4_channel_attrs *fc_attrs,
> >>>>>>>+                            struct nfs4_channel_attrs
> >>>>>>>
> >>>>>>>
> >>*bc_attrs) {
> >>
> >>
> >>>>>>>+    /* XXX: We need to have good values here... 32K is a
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>wild guess */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    fc_attrs->max_rqst_sz = bc_attrs->max_rqst_sz = 32768;
> >>>>>>>+    fc_attrs->max_resp_sz = bc_attrs->max_resp_sz = 32768;
> >>>>>>>+    fc_attrs->max_resp_sz_cached =
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>bc_attrs->max_resp_sz_cached = 32768;
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    fc_attrs->max_ops = bc_attrs->max_ops = 0xFFFFFFFF;
> >>>>>>>+    fc_attrs->max_reqs = bc_attrs->max_reqs =
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>clp->cl_rpcclient->cl_xprt->max_reqs;
> >>
> >>
> >>>>>>>+    fc_attrs->stream_attrs = bc_attrs->stream_attrs = 0;
> >>>>>>>+    fc_attrs->rdma_attrs = bc_attrs->rdma_attrs = 0;
> >>>>>>>+
> >>>>>>>+}
> >>>>>>>+
> >>>>>>>+/* Check the values returned by the server for
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>CREATE_SESSION. Since
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+we made
> >>>>>>>+ * our needs known, if the server gives us more than we
> >>>>>>>
> >>>>>>>
> >>need, we
> >>
> >>
> >>>>>>>+don't bother
> >>>>>>>+ * with it.
> >>>>>>>+ */
> >>>>>>>+void nfs4_adjust_channel_attrs(struct nfs4_channel_attrs
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>*req_attrs,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                            struct nfs4_channel_attrs
> >>>>>>>
> >>>>>>>
> >>*resp_attrs) {
> >>
> >>
> >>>>>>>+    if (req_attrs->max_rqst_sz < resp_attrs->max_rqst_sz)
> >>>>>>>+            resp_attrs->max_rqst_sz = req_attrs->max_rqst_sz;
> >>>>>>>+
> >>>>>>>+    if (req_attrs->max_resp_sz < resp_attrs->max_resp_sz)
> >>>>>>>+            resp_attrs->max_resp_sz = req_attrs->max_resp_sz;
> >>>>>>>+
> >>>>>>>+    if (req_attrs->max_resp_sz_cached < resp_attrs->max_resp_sz)
> >>>>>>>+            resp_attrs->max_resp_sz =
> >>>>>>>+ req_attrs->max_resp_sz_cached;
> >>>>>>>+
> >>>>>>>+    if (req_attrs->max_ops < resp_attrs->max_ops)
> >>>>>>>+            resp_attrs->max_ops = req_attrs->max_ops;
> >>>>>>>+
> >>>>>>>+    if (req_attrs->max_reqs < resp_attrs->max_reqs)
> >>>>>>>+            resp_attrs->max_reqs = req_attrs->max_reqs;
> >>>>>>>+
> >>>>>>>+    /* XXX: We ignore the stream channel attributes... we
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>have no idea what
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+     * to do with them anyways!
> >>>>>>>+     */
> >>>>>>>+}
> >>>>>>>+
> >>>>>>>int _nfs4_proc_create_session(struct nfs4_client *clp, struct
> >>>>>>>nfs4_session *session, struct rpc_clnt *clnt)  {
> >>>>>>>   struct nfs41_create_session_args args = { @@ -3845,7
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>+4063,19 @@ int
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>_nfs4_proc_create_session(struct nfs4_client *clp, struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs4_session *sess
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   };
> >>>>>>>   int status;
> >>>>>>>
> >>>>>>>-    status = rpc_call_sync(clnt, &msg, 0);
> >>>>>>>+    nfs4_init_channel_attrs(clp, &args.fc_attrs,
> >>>>>>>
> >>>>>>>
> >>&args.bc_attrs);
> >>
> >>
> >>>>>>>+
> >>>>>>>+        status = rpc_call_sync(clnt, &msg, 0);
> >>>>>>>+
> >>>>>>>+    /* Set the negotiated values in the session's
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>channel_attrs struct
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+*/
> >>>>>>>+
> >>>>>>>+    if (!status) {
> >>>>>>>+            nfs4_adjust_channel_attrs(&args.fc_attrs,
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>&session->fore_channel.chan_attrs);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+            nfs4_adjust_channel_attrs(&args.bc_attrs,
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>&session->back_channel.chan_attrs);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    }
> >>>>>>>+
> >>>>>>>   return status;
> >>>>>>>}
> >>>>>>>EXPORT_SYMBOL(_nfs4_proc_create_session);
> >>>>>>>@@ -3853,29 +4083,28 @@ EXPORT_SYMBOL(_nfs4_proc_create_session);
> >>>>>>>int nfs4_proc_create_session(struct nfs4_client *clp)  {
> >>>>>>>   int status;
> >>>>>>>-    unsigned long now;
> >>>>>>>   struct nfs4_session *session;
> >>>>>>>-    struct nfs_fsinfo fsinfo;
> >>>>>>>   u32 *ptr;
> >>>>>>>
> >>>>>>>-    now = jiffies;
> >>>>>>>-
> >>>>>>>   status = _nfs4_proc_create_session(clp,
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>clp->cl_session, clp->cl_rpcclient);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   if (status)
> >>>>>>>           return status;
> >>>>>>>
> >>>>>>>-    status = nfs4_proc_get_lease_time(clp, &fsinfo);
> >>>>>>>-    if (status == 0) {
> >>>>>>>-            /* Update lease time and schedule renewal */
> >>>>>>>-            spin_lock(&clp->cl_lock);
> >>>>>>>-            clp->cl_lease_time = fsinfo.lease_time * HZ;
> >>>>>>>-            clp->cl_last_renewal = now;
> >>>>>>>-            clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
> >>>>>>>-            spin_unlock(&clp->cl_lock);
> >>>>>>>+    session = clp->cl_session;
> >>>>>>>
> >>>>>>>-            nfs4_schedule_state_renewal(clp);
> >>>>>>>+    /* Init the fore channel */
> >>>>>>>+    status = nfs4_init_slot_table(&session->fore_channel);
> >>>>>>>+    dprintk("fc init returned %d\n", status);
> >>>>>>>+    if (status)
> >>>>>>>+            return status;
> >>>>>>>+
> >>>>>>>+    /* Init the back channel */
> >>>>>>>+    status = nfs4_init_slot_table(&session->back_channel);
> >>>>>>>+    dprintk("bc init returned %d\n", status);
> >>>>>>>+    if (status) {
> >>>>>>>+            nfs4_destroy_slot_table(&session->fore_channel);
> >>>>>>>+            return status;
> >>>>>>>   }
> >>>>>>>-    session = clp->cl_session;
> >>>>>>>
> >>>>>>>   ptr = (int *)session->sess_id;
> >>>>>>>   dprintk("sessionid is: %d:%d:%d:%d\n", ptr[0],
> >>>>>>>
> >>>>>>>
> >>ptr[1], ptr[2],
> >>
> >>
> >>>>>>>ptr[3]); @@ -4769,11 +4998,8 @@ struct nfs4_session
> >>>>>>>*nfs41_alloc_session(void)
> >>>>>>>
> >>>>>>>   session->expired = 1;
> >>>>>>>
> >>>>>>>-    INIT_LIST_HEAD(&session->slots_in_use);
> >>>>>>>-    INIT_LIST_HEAD(&session->unused_slots);
> >>>>>>>   INIT_LIST_HEAD(&session->session_hashtbl);
> >>>>>>>
> >>>>>>>-    //rpc_init_wait_queue(&session->slot_waitq, "Slot
> >>>>>>>
> >>>>>>>
> >>waitqueue");
> >>
> >>
> >>>>>>>   spin_lock_init(&session->session_lock);
> >>>>>>>
> >>>>>>>   sema_init(&session->session_sem, 1); @@ -4797,6
> >>>>>>>
> >>>>>>>
> >>+5023,8 @@ void
> >>
> >>
> >>>>>>>nfs4_get_session(struct nfs4_session *session)  void
> >>>>>>>nfs4_put_session(struct nfs4_session **session)  {
> >>>>>>>   if (atomic_dec_and_test(&((*session)->ref_count))) {
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>nfs4_destroy_slot_table(&((*session)->fore_channel));
> >>
> >>
> >>>>>>>+
> >>>>>>>
> >>>>>>>
> >>nfs4_destroy_slot_table(&((*session)->back_channel));
> >>
> >>
> >>>>>>>           nfs41_free_session(*session);
> >>>>>>>           *session = NULL;
> >>>>>>>   }
> >>>>>>>@@ -4806,7 +5034,11 @@ int nfs41_proc_setup_session(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs4_client
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>*clp)  {
> >>>>>>>   int status;
> >>>>>>>
> >>>>>>>-    dprintk("in %s!\n", __FUNCTION__);
> >>>>>>>+        struct nfs_fsinfo fsinfo;
> >>>>>>>+    unsigned long now;
> >>>>>>>+
> >>>>>>>+    now = jiffies;
> >>>>>>>+
> >>>>>>>   if (!clp->cl_session) {
> >>>>>>>           /* create the session struct to hold the
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>session parameters */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>           clp->cl_session = nfs41_alloc_session(); @@
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>-4844,6 +5076,20 @@ int
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>nfs41_proc_setup_session(struct nfs4_client *clp)
> >>>>>>>   clp->cl_session->expired = 0;
> >>>>>>>   clp->cl_session->client = clp;
> >>>>>>>
> >>>>>>>+    status = nfs4_proc_get_lease_time(clp, &fsinfo);
> >>>>>>>+
> >>>>>>>+    if (status)
> >>>>>>>+            goto out_free;
> >>>>>>>+
> >>>>>>>+    /* Update lease time and schedule renewal */
> >>>>>>>+    spin_lock(&clp->cl_lock);
> >>>>>>>+    clp->cl_lease_time = fsinfo.lease_time * HZ;
> >>>>>>>+    clp->cl_last_renewal = now;
> >>>>>>>+    clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
> >>>>>>>+    spin_unlock(&clp->cl_lock);
> >>>>>>>+
> >>>>>>>+    nfs4_schedule_state_renewal(clp);
> >>>>>>>+
> >>>>>>>   clp->cl_session->mutating = 0;
> >>>>>>>out:
> >>>>>>>   up(&clp->cl_session->session_sem);
> >>>>>>>diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index
> >>>>>>>5ef6d70..7da9a6a 100644
> >>>>>>>--- a/fs/nfs/nfs4xdr.c
> >>>>>>>+++ b/fs/nfs/nfs4xdr.c
> >>>>>>>@@ -1429,20 +1429,22 @@ static int
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>encode_create_session(struct xdr_stream *xdr, struct
> >>>>>>nfs41_create_ses
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   RESERVE_SPACE(2*28);                    /* 2 channel_attrs */
> >>>>>>>
> >>>>>>>   /* Fore Channel */
> >>>>>>>-    WRITE32(32768);                         /* max req size */
> >>>>>>>-    WRITE32(32768);                         /* max resp size */
> >>>>>>>-    WRITE32(32768);                         /* Max resp
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>size cached */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>-    WRITE32(RPC_DEF_SLOT_TABLE);            /* max operations */
> >>>>>>>-    WRITE32(RPC_DEF_SLOT_TABLE);            /* max requests */
> >>>>>>>+    WRITE32(args->fc_attrs.max_rqst_sz);    /* max req size */
> >>>>>>>+    WRITE32(args->fc_attrs.max_resp_sz);    /* max resp size */
> >>>>>>>+    WRITE32(args->fc_attrs.max_resp_sz_cached);     /* Max
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>resp sz cached */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    WRITE32(args->fc_attrs.max_ops);        /* max operations */
> >>>>>>>+    WRITE32(args->fc_attrs.max_reqs);       /* max requests */
> >>>>>>>+
> >>>>>>>   WRITE32(0);                             /*
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>Streamchannel attrs */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   WRITE32(0);
> >>>>>>>
> >>>>>>>
> >>/*rdmachannel_attrs */
> >>
> >>
> >>>>>>>   /* Back Channel */
> >>>>>>>-    WRITE32(32768);                         /* max req size */
> >>>>>>>-    WRITE32(32768);                         /* max resp size */
> >>>>>>>-    WRITE32(32768);                         /* Max resp
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>size cached */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>-    WRITE32(RPC_DEF_SLOT_TABLE);            /* max operations */
> >>>>>>>-    WRITE32(RPC_DEF_SLOT_TABLE);            /* max requests */
> >>>>>>>+    WRITE32(args->bc_attrs.max_rqst_sz);    /* max req size */
> >>>>>>>+    WRITE32(args->bc_attrs.max_resp_sz);    /* max resp size */
> >>>>>>>+    WRITE32(args->bc_attrs.max_resp_sz_cached);     /* Max
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>resp sz cached */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    WRITE32(args->bc_attrs.max_ops);        /* max operations */
> >>>>>>>+    WRITE32(args->bc_attrs.max_reqs);       /* max requests */
> >>>>>>>+
> >>>>>>>   WRITE32(0);                             /*
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>Streamchannel attrs */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>   WRITE32(0);
> >>>>>>>
> >>>>>>>
> >>/*rdmachannel_attrs */
> >>
> >>
> >>>>>>>@@ -6404,7 +6406,7 @@ static int
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>nfs41_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
> >>>>>>str
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>           status = decode_putrootfh(&xdr);
> >>>>>>>   if (!status)
> >>>>>>>           status = decode_fsinfo(&xdr, res->fsinfo);
> >>>>>>>-    if (!status)
> >>>>>>>+    if (status)
> >>>>>>>           status = -nfs_stat_to_errno(hdr.status);
> >>>>>>>   return status;
> >>>>>>>}
> >>>>>>>diff --git a/fs/nfs/super.c b/fs/nfs/super.c index
> >>>>>>>
> >>>>>>>
> >>a3bc630..89eb564
> >>
> >>
> >>>>>>>100644
> >>>>>>>--- a/fs/nfs/super.c
> >>>>>>>+++ b/fs/nfs/super.c
> >>>>>>>@@ -1260,15 +1260,13 @@ static int nfs4_fill_super(struct
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>super_block *sb, struct nfs4_mount_data *data,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>               server->nfs4_state->cl_minorversion = i;
> >>>>>>>
> >>>>>>>               if (server->rpc_ops->setup_session) {
> >>>>>>>-                        int status;
> >>>>>>>-
> >>>>>>>                       lock_kernel();
> >>>>>>>                       down_write(&server->nfs4_state->cl_sem);
> >>>>>>>-                        status =
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>server->rpc_ops->setup_session(server->nfs4_state);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                        err =
> >>>>>>>+ server->rpc_ops->setup_session(server->nfs4_state);
> >>>>>>>                       up_write(&server->nfs4_state->cl_sem);
> >>>>>>>                       unlock_kernel();
> >>>>>>>
> >>>>>>>-                        if (status) {
> >>>>>>>+                        if (err) {
> >>>>>>>                               printk(KERN_EMERG
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>"Couldn't mount using minorversion %d\n", i);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>rpc_shutdown_client(server->client);
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>                       }
> >>>>>>>diff --git a/include/linux/nfs41_sessions.h
> >>>>>>>b/include/linux/nfs41_sessions.h new file mode 100644 index
> >>>>>>>0000000..02f45db
> >>>>>>>--- /dev/null
> >>>>>>>+++ b/include/linux/nfs41_sessions.h
> >>>>>>>@@ -0,0 +1,72 @@
> >>>>>>>+#ifndef __NFS4_1_SESSIONS_H__
> >>>>>>>+#define __NFS4_1_SESSIONS_H__
> >>>>>>>+
> >>>>>>>+/* The flags for the nfs4_slot struct */
> >>>>>>>+#define NFS4_SLOT_BUSY              0X0     /* Slot in use */
> >>>>>>>+#define NFS4_SLOT_RECLAIMED 0x1     /* Slot has
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>been reclaimed by
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                                       the server */
> >>>>>>>+
> >>>>>>>+typedef unsigned char               sessionid_t[16];
> >>>>>>>+typedef u32                 streamchannel_attrs;
> >>>>>>>+typedef u32                 rdmachannel_attrs;
> >>>>>>>+
> >>>>>>>+struct nfs4_channel_attrs {
> >>>>>>>+    u32                     max_rqst_sz;
> >>>>>>>+    u32                     max_resp_sz;
> >>>>>>>+    u32                     max_resp_sz_cached;
> >>>>>>>+    u32                     max_ops;
> >>>>>>>+    u32                     max_reqs;
> >>>>>>>+    streamchannel_attrs     stream_attrs;
> >>>>>>>+    rdmachannel_attrs       rdma_attrs;
> >>>>>>>+};
> >>>>>>>+
> >>>>>>>+struct nfs4_slot {
> >>>>>>>+    u32                     slot_nr;
> >>>>>>>+    u32                     seq_nr;
> >>>>>>>+    unsigned long           flags;
> >>>>>>>+    u32                     nr_waiters;
> >>>>>>>+    spinlock_t              slot_lock;
> >>>>>>>+};
> >>>>>>>+
> >>>>>>>+struct nfs4_slot_table {
> >>>>>>>+    struct nfs4_slot        *slots;
> >>>>>>>+    u32                     max_slots;
> >>>>>>>+    spinlock_t              slot_tbl_lock;
> >>>>>>>+};
> >>>>>>>+
> >>>>>>>+struct nfs4_channel {
> >>>>>>>+    struct nfs4_channel_attrs       chan_attrs;
> >>>>>>>+    struct rpc_clnt                 *rpc_client;
> >>>>>>>+    struct nfs4_slot_table          slot_table;
> >>>>>>>+};
> >>>>>>>+
> >>>>>>>+struct nfs4_session {
> >>>>>>>+    /* Session related params */
> >>>>>>>+    sessionid_t                     sess_id;
> >>>>>>>+    u32                             seqid;  /* The seqid
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>returned by
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+                                               exchange_id */
> >>>>>>>+    u32                             persist;
> >>>>>>>+    u32                             header_padding;
> >>>>>>>+    u32                             hash_alg;
> >>>>>>>+    u32                             ssv_len;
> >>>>>>>+    u32                             use_for_back_chan;
> >>>>>>>+    u32                             rdma_mode;
> >>>>>>>+
> >>>>>>>+    /* The fore and back channel */
> >>>>>>>+    struct nfs4_channel             fore_channel;
> >>>>>>>+    struct nfs4_channel             back_channel;
> >>>>>>>+
> >>>>>>>+    unsigned int                    expired;
> >>>>>>>+    struct nfs4_client *            client;
> >>>>>>>+    struct list_head                session_hashtbl;
> >>>>>>>+    spinlock_t                      session_lock;
> >>>>>>>+    /* To prevent races between create_session and sequence */
> >>>>>>>+    int                             mutating;
> >>>>>>>+    struct semaphore                session_sem;
> >>>>>>>+    atomic_t                        ref_count;
> >>>>>>>+};
> >>>>>>>+
> >>>>>>>+
> >>>>>>>+#endif
> >>>>>>>+
> >>>>>>>+
> >>>>>>>diff --git a/include/linux/nfs_xdr.h
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>b/include/linux/nfs_xdr.h index
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>4648707..52b9e38 100644
> >>>>>>>--- a/include/linux/nfs_xdr.h
> >>>>>>>+++ b/include/linux/nfs_xdr.h
> >>>>>>>@@ -3,6 +3,7 @@
> >>>>>>>
> >>>>>>>#include <linux/sunrpc/xprt.h>
> >>>>>>>#include <linux/nfsacl.h>
> >>>>>>>+#include <linux/nfs41_sessions.h>
> >>>>>>>
> >>>>>>>/*
> >>>>>>>* To change the maximum rsize and wsize supported by the
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>NFS client,
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>adjust @@ -778,6 +779,8 @@ struct nfs41_create_session_args {
> >>>>>>>   uint32_t                        use_for_backchannel;
> >>>>>>>   uint32_t                        use_for_rdma;
> >>>>>>>   uint32_t                        cb_program;
> >>>>>>>+    struct nfs4_channel_attrs       fc_attrs;       /* Fore
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>Channel */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>+    struct nfs4_channel_attrs       bc_attrs;       /* Back
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>Channel */
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>};
> >>>>>>>
> >>>>>>>struct nfs41_create_session_res {
> >>>>>>>@@ -805,6 +808,7 @@ struct nfs41_sequence_res {
> >>>>>>>   u32                             target_maxslots;
> >>>>>>>   u32                             status_flags;
> >>>>>>>   struct nfs4_state_owner         *sp;
> >>>>>>>+    struct nfs4_slot                *slot;
> >>>>>>>};
> >>>>>>>
> >>>>>>>struct nfs4_get_lease_time_args {
> >>>>>>>diff --git a/include/linux/nfsd/state.h
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>b/include/linux/nfsd/state.h
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>index 8f699b4..fde667e 100644
> >>>>>>>--- a/include/linux/nfsd/state.h
> >>>>>>>+++ b/include/linux/nfsd/state.h
> >>>>>>>@@ -47,8 +47,6 @@ typedef struct {
> >>>>>>>   u32             cl_id;
> >>>>>>>} clientid_t;
> >>>>>>>
> >>>>>>>-typedef unsigned char sessionid_t[16];
> >>>>>>>-
> >>>>>>>typedef struct {
> >>>>>>>   u32             so_boot;
> >>>>>>>   u32             so_stateownerid;
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>_______________________________________________
> >>>pNFS mailing list
> >>>pNFS at linux-nfs.org
> >>>http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
> >>>
> >>>
> >>>
> >>>
>
> _______________________________________________
> pNFS mailing list
> pNFS at linux-nfs.org
> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://linux-nfs.org/pipermail/pnfs/attachments/20070320/ada9a943/attachment-0001.htm 


More information about the pNFS mailing list