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

Benny Halevy bhalevy at panasas.com
Fri Mar 16 05:24:12 EDT 2007


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.

> +			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;



More information about the pNFS mailing list