Re: [PATCH] nfs41: Initialize slot->seq_nr at nfs4_init_slot_table()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Please don't merge nfs4_reset_slot_tables and nfs4_init_slot_tables.  It  assumes a static array (realloc) which goes away with the dynamic slot table code. Instead, take a look at the patch set I sent on Feb 12

[PATCH Version 7 3/3] NFSv4.1 avoid freeing slot when tasks are waiting
[PATCH Version 1 2/3] NFSv4.1 prepare for dyamic session slots
[PATCH Version 7 1/3] NFS4.1 clean up nfs4_alloc_session

-->Andy

On Feb 14, 2012, at 9:30 PM, Myklebust, Trond wrote:

> On Tue, 2012-02-14 at 20:50 -0500, Trond Myklebust wrote:
>> Hang on... Looking at 3.2, I think you're correct. We used to initialise
>> to 1, and now we're initialising to 0.
>> 
>> Ah... I see what happened.
>> 
>> commit aacd5537270a752fe12a9914a207284fc2341c6d (NFSv4.1: cleanup init
>> and reset of session slot tables) seems to have removed the call to
>> nfs4_reset_slot_tables() that was doing that initialisation. OK... So
>> this is a Linux 3.3-rcX only regression, and should be treated as
>> such...
>> 
>> How about the following instead so that we ensure we fully share the
>> initialisation code between nfs4_reset_slot_tables and
>> nfs4_init_slot_tables?
>> 
> 
> Here's a version 2 that does a few more cleanups by merging the
> nfs4_init_slot_table() and nfs4_reset_slot_table() into a single
> function.
> 
> 8<-------------------------------------------------------------------------
> From dea20ac15be192d0b4c4e367b7b61740ceee8dc4 Mon Sep 17 00:00:00 2001
> From: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx>
> Date: Tue, 14 Feb 2012 20:33:19 -0500
> Subject: [PATCH v2] NFSv4.1: Fix a NFSv4.1 session initialisation regression
> 
> Commit aacd553 (NFSv4.1: cleanup init and reset of session slot tables)
> introduces a regression in the session initialisation code. New tables
> now find their sequence ids initialised to 0, rather than the mandated
> value of 1 (see RFC5661).
> 
> Fix the problem by merging nfs4_reset_slot_table() and nfs4_init_slot_table().
> Since the tbl->max_slots is initialised to 0, the test in
> nfs4_reset_slot_table for max_reqs != tbl->max_slots will automatically
> pass for an empty table.
> 
> Reported-by: Vitaliy Gusev <gusev.vitaliy@xxxxxxxxxxx>
> Signed-off-by: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx>
> ---
> fs/nfs/nfs4proc.c |  109 ++++++++++++++++++++--------------------------------
> 1 files changed, 42 insertions(+), 67 deletions(-)
> 
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index d202e04..1684c9b 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -5008,37 +5008,53 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
> 	return status;
> }
> 
> +static struct nfs4_slot *nfs4_alloc_slots(u32 max_slots, gfp_t gfp_flags)
> +{
> +	return kcalloc(max_slots, sizeof(struct nfs4_slot), gfp_flags);
> +}
> +
> +static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
> +		struct nfs4_slot *new,
> +		u32 max_slots,
> +		u32 ivalue)
> +{
> +	struct nfs4_slot *old = NULL;
> +	u32 i;
> +
> +	spin_lock(&tbl->slot_tbl_lock);
> +	if (new) {
> +		old = tbl->slots;
> +		tbl->slots = new;
> +		tbl->max_slots = max_slots;
> +	}
> +	tbl->highest_used_slotid = -1;	/* no slot is currently used */
> +	for (i = 0; i < tbl->max_slots; i++)
> +		tbl->slots[i].seq_nr = ivalue;
> +	spin_unlock(&tbl->slot_tbl_lock);
> +	kfree(old);
> +}
> +
> /*
> - * Reset a slot table
> + * (re)Initialise a slot table
>  */
> -static int nfs4_reset_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
> -				 int ivalue)
> +static int nfs4_realloc_slot_table(struct nfs4_slot_table *tbl, u32 max_reqs,
> +				 u32 ivalue)
> {
> 	struct nfs4_slot *new = NULL;
> -	int i;
> -	int ret = 0;
> +	int ret = -ENOMEM;
> 
> 	dprintk("--> %s: max_reqs=%u, tbl->max_slots %d\n", __func__,
> 		max_reqs, tbl->max_slots);
> 
> 	/* Does the newly negotiated max_reqs match the existing slot table? */
> 	if (max_reqs != tbl->max_slots) {
> -		ret = -ENOMEM;
> -		new = kmalloc(max_reqs * sizeof(struct nfs4_slot),
> -			      GFP_NOFS);
> +		new = nfs4_alloc_slots(max_reqs, GFP_NOFS);
> 		if (!new)
> 			goto out;
> -		ret = 0;
> -		kfree(tbl->slots);
> -	}
> -	spin_lock(&tbl->slot_tbl_lock);
> -	if (new) {
> -		tbl->slots = new;
> -		tbl->max_slots = max_reqs;
> 	}
> -	for (i = 0; i < tbl->max_slots; ++i)
> -		tbl->slots[i].seq_nr = ivalue;
> -	spin_unlock(&tbl->slot_tbl_lock);
> +	ret = 0;
> +
> +	nfs4_add_and_init_slots(tbl, new, max_reqs, ivalue);
> 	dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
> 		tbl, tbl->slots, tbl->max_slots);
> out:
> @@ -5061,36 +5077,6 @@ static void nfs4_destroy_slot_tables(struct nfs4_session *session)
> }
> 
> /*
> - * Initialize slot table
> - */
> -static int nfs4_init_slot_table(struct nfs4_slot_table *tbl,
> -		int max_slots, int ivalue)
> -{
> -	struct nfs4_slot *slot;
> -	int ret = -ENOMEM;
> -
> -	BUG_ON(max_slots > NFS4_MAX_SLOT_TABLE);
> -
> -	dprintk("--> %s: max_reqs=%u\n", __func__, max_slots);
> -
> -	slot = kcalloc(max_slots, sizeof(struct nfs4_slot), GFP_NOFS);
> -	if (!slot)
> -		goto out;
> -	ret = 0;
> -
> -	spin_lock(&tbl->slot_tbl_lock);
> -	tbl->max_slots = max_slots;
> -	tbl->slots = slot;
> -	tbl->highest_used_slotid = -1;  /* no slot is currently used */
> -	spin_unlock(&tbl->slot_tbl_lock);
> -	dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
> -		tbl, tbl->slots, tbl->max_slots);
> -out:
> -	dprintk("<-- %s: return %d\n", __func__, ret);
> -	return ret;
> -}
> -
> -/*
>  * Initialize or reset the forechannel and backchannel tables
>  */
> static int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
> @@ -5101,25 +5087,16 @@ static int nfs4_setup_session_slot_tables(struct nfs4_session *ses)
> 	dprintk("--> %s\n", __func__);
> 	/* Fore channel */
> 	tbl = &ses->fc_slot_table;
> -	if (tbl->slots == NULL) {
> -		status = nfs4_init_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
> -		if (status) /* -ENOMEM */
> -			return status;
> -	} else {
> -		status = nfs4_reset_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
> -		if (status)
> -			return status;
> -	}
> +	status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1);
> +	if (status) /* -ENOMEM */
> +		return status;
> 	/* Back channel */
> 	tbl = &ses->bc_slot_table;
> -	if (tbl->slots == NULL) {
> -		status = nfs4_init_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
> -		if (status)
> -			/* Fore and back channel share a connection so get
> -			 * both slot tables or neither */
> -			nfs4_destroy_slot_tables(ses);
> -	} else
> -		status = nfs4_reset_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
> +	status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0);
> +	if (status && tbl->slots == NULL)
> +		/* Fore and back channel share a connection so get
> +		 * both slot tables or neither */
> +		nfs4_destroy_slot_tables(ses);
> 	return status;
> }
> 
> @@ -5133,13 +5110,11 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
> 		return NULL;
> 
> 	tbl = &session->fc_slot_table;
> -	tbl->highest_used_slotid = -1;
> 	spin_lock_init(&tbl->slot_tbl_lock);
> 	rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
> 	init_completion(&tbl->complete);
> 
> 	tbl = &session->bc_slot_table;
> -	tbl->highest_used_slotid = -1;
> 	spin_lock_init(&tbl->slot_tbl_lock);
> 	rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
> 	init_completion(&tbl->complete);
> -- 
> 1.7.7.6
> 
> 
> -- 
> Trond Myklebust
> Linux NFS client maintainer
> 
> NetApp
> Trond.Myklebust@xxxxxxxxxx
> www.netapp.com
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux