public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] nfs41: fix multiple free slot calls
  2009-10-21 18:24 [PATCH 0/2] nfs41 client session bug fixes andros
@ 2009-10-21 18:24 ` andros
  0 siblings, 0 replies; 4+ messages in thread
From: andros @ 2009-10-21 18:24 UTC (permalink / raw)
  To: pnfs; +Cc: linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Reported-by: Trond Myklebust <trond.myklebust@netapp.com>

nfs41_sequence_free_slot is called multiple times on SEQUENCE operation errors.

Fix this by moving the call to nfs41_sequence_free_slot from the error path of
nfs41_sequence_done to nfs4_async_handle_error for the SEQUENCE operation
error cases.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 fs/nfs/nfs4proc.c |   63 ++++++++++++++++++++++++++++++----------------------
 1 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index c321002..eb245a1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -65,7 +65,8 @@
 struct nfs4_opendata;
 static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
-static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
+static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *,
+			 struct nfs4_state *, struct nfs4_sequence_res *);
 static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
 
@@ -370,11 +371,12 @@ static void nfs41_sequence_done(struct nfs_client *clp,
 
 	/* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
 	if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
-		goto out;
+		return;
 
 	tbl = &clp->cl_session->fc_slot_table;
 	slot = tbl->slots + res->sr_slotid;
 
+	/* Check the SEQUENCE operation status */
 	if (res->sr_status == 0) {
 		/* Update the slot's sequence and clientid lease timer */
 		++slot->seq_nr;
@@ -386,15 +388,6 @@ static void nfs41_sequence_done(struct nfs_client *clp,
 		return;
 	}
 
-	/* Do not free slot if retried while operation was in progress */
-	if (res->sr_status == -NFS4ERR_DELAY) {
-		dprintk("%s: Operation in progress\n", __func__);
-		return;
-	}
-out:
-	/* The session may be reset by one of the error handlers. */
-	dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
-	nfs41_sequence_free_slot(clp, res);
 }
 
 /*
@@ -1743,7 +1736,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
 			if (calldata->arg.fmode == 0)
 				break;
 		default:
-			if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
+			if (nfs4_async_handle_error(task, server, state,
+					&calldata->res.seq_res) == -EAGAIN) {
 				nfs4_restart_rpc(task, server->nfs_client);
 				return;
 			}
@@ -2537,7 +2531,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	struct nfs_removeres *res = task->tk_msg.rpc_resp;
 
 	nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
-	if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+	if (nfs4_async_handle_error(task, res->server, NULL,
+						&res->seq_res) == -EAGAIN)
 		return 0;
 	nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res);
 	update_changeattr(dir, &res->cinfo);
@@ -2981,7 +2976,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 	/* nfs4_sequence_free_slot called in the read rpc_call_done */
 	nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
 
-	if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
+	if (nfs4_async_handle_error(task, server, data->args.context->state,
+					&data->res.seq_res) == -EAGAIN) {
 		nfs4_restart_rpc(task, server->nfs_client);
 		return -EAGAIN;
 	}
@@ -3002,11 +2998,14 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	struct inode *inode = data->inode;
 	
+	dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
 	/* slot is freed in nfs_writeback_done */
 	nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
 			   task->tk_status);
 
-	if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
+	if (nfs4_async_handle_error(task, NFS_SERVER(inode),
+				    data->args.context->state,
+				    &data->res.seq_res) == -EAGAIN) {
 		nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
 	}
@@ -3032,9 +3031,12 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	struct inode *inode = data->inode;
 	
+	dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
+
 	nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
 			   task->tk_status);
-	if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
+	if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL,
+					&data->res.seq_res) == -EAGAIN) {
 		nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
 	}
@@ -3330,7 +3332,9 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
 }
 
 static int
-_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state)
+_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
+			 struct nfs_client *clp, struct nfs4_state *state,
+			 struct nfs4_sequence_res *res)
 {
 	if (!clp || task->tk_status >= 0)
 		return 0;
@@ -3361,6 +3365,8 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
 			dprintk("%s ERROR %d, Reset session\n", __func__,
 				task->tk_status);
 			set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+			/* Free the slot so session can drain */
+			nfs41_sequence_free_slot(clp, res);
 			task->tk_status = 0;
 			return -EAGAIN;
 #endif /* CONFIG_NFS_V4_1 */
@@ -3380,9 +3386,11 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
 }
 
 static int
-nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
+nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
+			struct nfs4_state *state, struct nfs4_sequence_res *res)
 {
-	return _nfs4_async_handle_error(task, server, server->nfs_client, state);
+	return _nfs4_async_handle_error(task, server, server->nfs_client,
+					state, res);
 }
 
 int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred)
@@ -3732,9 +3740,9 @@ static void nfs4_locku_release_calldata(void *data)
 static void nfs4_locku_done(struct rpc_task *task, void *data)
 {
 	struct nfs4_unlockdata *calldata = data;
+	struct nfs4_sequence_res *res = &calldata->res.seq_res;
 
-	nfs4_sequence_done(calldata->server, &calldata->res.seq_res,
-			   task->tk_status);
+	nfs4_sequence_done(calldata->server, res, task->tk_status);
 	if (RPC_ASSASSINATED(task))
 		return;
 	switch (task->tk_status) {
@@ -3750,12 +3758,12 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
 		case -NFS4ERR_EXPIRED:
 			break;
 		default:
-			if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
+			if (nfs4_async_handle_error(task, calldata->server,
+						    NULL, res) == -EAGAIN)
 				nfs4_restart_rpc(task,
 						calldata->server->nfs_client);
 	}
-	nfs4_sequence_free_slot(calldata->server->nfs_client,
-				&calldata->res.seq_res);
+	nfs4_sequence_free_slot(calldata->server->nfs_client, res);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4875,19 +4883,20 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
 void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 {
 	struct nfs_client *clp = (struct nfs_client *)data;
+	struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;
 
-	nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status);
+	nfs41_sequence_done(clp, res, task->tk_status);
 
 	if (task->tk_status < 0) {
 		dprintk("%s ERROR %d\n", __func__, task->tk_status);
 
-		if (_nfs4_async_handle_error(task, NULL, clp, NULL)
+		if (_nfs4_async_handle_error(task, NULL, clp, NULL, res)
 								== -EAGAIN) {
 			nfs4_restart_rpc(task, clp);
 			return;
 		}
 	}
-	nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
+	nfs41_sequence_free_slot(clp, res);
 	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
 
 	put_rpccred(task->tk_msg.rpc_cred);
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 0/2] nfs41 session bug fixes
@ 2009-10-28 14:37 andros
  2009-10-28 14:37 ` [PATCH 1/2] nfs41: fix multiple free slot calls andros
  0 siblings, 1 reply; 4+ messages in thread
From: andros @ 2009-10-28 14:37 UTC (permalink / raw)
  To: trond.myklebust; +Cc: linux-nfs

nfs41 session bug fixes. 2.6.43-rc5 tronds bugfixes branch

Fix multiple calls to nfs41_sequence_free_slot (Reported by Trond).
0001-nfs41-fix-multiple-free-slot-calls.patch

Fix a race between state manager session reset and queued RPCs calling
nfs41_setup_sequence.

0002-nfs41-fix-race-on-session-reset.patch

Passed Connectathon tests.

Passed pynfs testclient.py INJECT_ERROR_CTHON where Connectathon tests are run
against the pynfs 4.1 server configured to return a SEQUENCE error 
(NFS4ERR_SEQ_MISORDERED, NFS4ER_BADSESSION were tested) every 50th SEQUENCE
operation. The session was reset hundreds of times.

-->Andy


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] nfs41: fix multiple free slot calls
  2009-10-28 14:37 [PATCH 0/2] nfs41 session bug fixes andros
@ 2009-10-28 14:37 ` andros
  2009-10-28 14:37   ` [PATCH 2/2] nfs41: fix race on session reset andros
  0 siblings, 1 reply; 4+ messages in thread
From: andros @ 2009-10-28 14:37 UTC (permalink / raw)
  To: trond.myklebust; +Cc: linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Reported-by: Trond Myklebust <trond.myklebust@netapp.com>

nfs41_sequence_free_slot is called multiple times on SEQUENCE operation errors.

Fix this by moving the call to nfs41_sequence_free_slot from the error path of
nfs41_sequence_done to nfs4_async_handle_error for the SEQUENCE operation
error cases.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 fs/nfs/nfs4proc.c |   58 ++++++++++++++++++++++++++++++++--------------------
 1 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ff37454..3ec6406 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -65,7 +65,8 @@
 struct nfs4_opendata;
 static int _nfs4_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
-static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
+static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *,
+			 struct nfs4_state *, struct nfs4_sequence_res *);
 static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
 
@@ -375,11 +376,12 @@ static void nfs41_sequence_done(struct nfs_client *clp,
 
 	/* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
 	if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
-		goto out;
+		return;
 
 	tbl = &clp->cl_session->fc_slot_table;
 	slot = tbl->slots + res->sr_slotid;
 
+	/* Check the SEQUENCE operation status */
 	if (res->sr_status == 0) {
 		/* Update the slot's sequence and clientid lease timer */
 		++slot->seq_nr;
@@ -390,10 +392,6 @@ static void nfs41_sequence_done(struct nfs_client *clp,
 		spin_unlock(&clp->cl_lock);
 		return;
 	}
-out:
-	/* The session may be reset by one of the error handlers. */
-	dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
-	nfs41_sequence_free_slot(clp, res);
 }
 
 /*
@@ -1736,7 +1734,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
 			if (calldata->arg.fmode == 0)
 				break;
 		default:
-			if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
+			if (nfs4_async_handle_error(task, server, state,
+					&calldata->res.seq_res) == -EAGAIN) {
 				nfs4_restart_rpc(task, server->nfs_client);
 				return;
 			}
@@ -2530,7 +2529,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
 	struct nfs_removeres *res = task->tk_msg.rpc_resp;
 
 	nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
-	if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+	if (nfs4_async_handle_error(task, res->server, NULL,
+						&res->seq_res) == -EAGAIN)
 		return 0;
 	nfs4_sequence_free_slot(res->server->nfs_client, &res->seq_res);
 	update_changeattr(dir, &res->cinfo);
@@ -2974,7 +2974,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 	/* nfs4_sequence_free_slot called in the read rpc_call_done */
 	nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
 
-	if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
+	if (nfs4_async_handle_error(task, server, data->args.context->state,
+					&data->res.seq_res) == -EAGAIN) {
 		nfs4_restart_rpc(task, server->nfs_client);
 		return -EAGAIN;
 	}
@@ -2995,11 +2996,14 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	struct inode *inode = data->inode;
 	
+	dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
 	/* slot is freed in nfs_writeback_done */
 	nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
 			   task->tk_status);
 
-	if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
+	if (nfs4_async_handle_error(task, NFS_SERVER(inode),
+				    data->args.context->state,
+				    &data->res.seq_res) == -EAGAIN) {
 		nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
 	}
@@ -3025,9 +3029,12 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	struct inode *inode = data->inode;
 	
+	dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
+
 	nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res,
 			   task->tk_status);
-	if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
+	if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL,
+					&data->res.seq_res) == -EAGAIN) {
 		nfs4_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
 	}
@@ -3320,7 +3327,9 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
 }
 
 static int
-_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state)
+_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
+			 struct nfs_client *clp, struct nfs4_state *state,
+			 struct nfs4_sequence_res *res)
 {
 	if (!clp || task->tk_status >= 0)
 		return 0;
@@ -3351,6 +3360,8 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
 			dprintk("%s ERROR %d, Reset session\n", __func__,
 				task->tk_status);
 			set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+			/* Free the slot so session can drain */
+			nfs41_sequence_free_slot(clp, res);
 			task->tk_status = 0;
 			return -EAGAIN;
 #endif /* CONFIG_NFS_V4_1 */
@@ -3370,9 +3381,11 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
 }
 
 static int
-nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
+nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
+			struct nfs4_state *state, struct nfs4_sequence_res *res)
 {
-	return _nfs4_async_handle_error(task, server, server->nfs_client, state);
+	return _nfs4_async_handle_error(task, server, server->nfs_client,
+					state, res);
 }
 
 int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred)
@@ -3722,9 +3735,9 @@ static void nfs4_locku_release_calldata(void *data)
 static void nfs4_locku_done(struct rpc_task *task, void *data)
 {
 	struct nfs4_unlockdata *calldata = data;
+	struct nfs4_sequence_res *res = &calldata->res.seq_res;
 
-	nfs4_sequence_done(calldata->server, &calldata->res.seq_res,
-			   task->tk_status);
+	nfs4_sequence_done(calldata->server, res, task->tk_status);
 	if (RPC_ASSASSINATED(task))
 		return;
 	switch (task->tk_status) {
@@ -3740,12 +3753,12 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
 		case -NFS4ERR_EXPIRED:
 			break;
 		default:
-			if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
+			if (nfs4_async_handle_error(task, calldata->server,
+						    NULL, res) == -EAGAIN)
 				nfs4_restart_rpc(task,
 						calldata->server->nfs_client);
 	}
-	nfs4_sequence_free_slot(calldata->server->nfs_client,
-				&calldata->res.seq_res);
+	nfs4_sequence_free_slot(calldata->server->nfs_client, res);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4864,19 +4877,20 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
 void nfs41_sequence_call_done(struct rpc_task *task, void *data)
 {
 	struct nfs_client *clp = (struct nfs_client *)data;
+	struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;
 
-	nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status);
+	nfs41_sequence_done(clp, res, task->tk_status);
 
 	if (task->tk_status < 0) {
 		dprintk("%s ERROR %d\n", __func__, task->tk_status);
 
-		if (_nfs4_async_handle_error(task, NULL, clp, NULL)
+		if (_nfs4_async_handle_error(task, NULL, clp, NULL, res)
 								== -EAGAIN) {
 			nfs4_restart_rpc(task, clp);
 			return;
 		}
 	}
-	nfs41_sequence_free_slot(clp, task->tk_msg.rpc_resp);
+	nfs41_sequence_free_slot(clp, res);
 	dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
 
 	kfree(task->tk_msg.rpc_argp);
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] nfs41: fix race on session reset
  2009-10-28 14:37 ` [PATCH 1/2] nfs41: fix multiple free slot calls andros
@ 2009-10-28 14:37   ` andros
  0 siblings, 0 replies; 4+ messages in thread
From: andros @ 2009-10-28 14:37 UTC (permalink / raw)
  To: trond.myklebust; +Cc: linux-nfs, Andy Adamson

From: Andy Adamson <andros@netapp.com>

Do not clear the NFS4CLNT_SESSION_SETUP bit until after the session and/or the
clientid has been established.

Clear the bit in nfs4_proc_create_session on a successful CREATE_SESSION to
make the new session available for the nfs4_get_lease_time call in the
session initialization case.

In the session reset case, this prevents a race with RPC's wating on the
slot_tbl_waitq where nfs41_setup_sequence would assign a slot on a partially
reset session.

Clear the bit on session init/reset failure other than NFS4ERR_STALE_CLIENTID
in the state manager.

Signed-off-by: Andy Adamson <andros@netapp.com>
---
 fs/nfs/nfs4proc.c  |    3 +++
 fs/nfs/nfs4state.c |   10 ++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3ec6406..0f1afde 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4782,6 +4782,9 @@ int nfs4_proc_create_session(struct nfs_client *clp, int reset)
 	if (status)
 		goto out;
 
+	/* Signal nfs41_setup_sequence that the session is ready for use */
+	clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
+
 	ptr = (unsigned *)&session->sess_id.data[0];
 	dprintk("%s client>seqid %d sessionid %u:%u:%u:%u\n", __func__,
 		clp->cl_seqid, ptr[0], ptr[1], ptr[2], ptr[3]);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2ef4fec..50a1b04 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1249,8 +1249,12 @@ static void nfs4_state_manager(struct nfs_client *clp)
 			if (status != 0)
 				continue;
 		}
-		/* Initialize or reset the session */
-		if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
+		/*
+		 * Initialize or reset the session. Wait to clear the bit
+		 * (in nfs4_proc_create_session) until session and /or
+		 * clientid is established.
+		 */
+		if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
 		   && nfs4_has_session(clp)) {
 			if (clp->cl_cons_state == NFS_CS_SESSION_INITING)
 				status = nfs4_initialize_session(clp);
@@ -1259,6 +1263,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
 			if (status) {
 				if (status == -NFS4ERR_STALE_CLIENTID)
 					continue;
+				clear_bit(NFS4CLNT_SESSION_SETUP,
+					  &clp->cl_state);
 				goto out_error;
 			}
 		}
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-10-28 15:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-28 14:37 [PATCH 0/2] nfs41 session bug fixes andros
2009-10-28 14:37 ` [PATCH 1/2] nfs41: fix multiple free slot calls andros
2009-10-28 14:37   ` [PATCH 2/2] nfs41: fix race on session reset andros
  -- strict thread matches above, loose matches on Subject: below --
2009-10-21 18:24 [PATCH 0/2] nfs41 client session bug fixes andros
2009-10-21 18:24 ` [PATCH 1/2] nfs41: fix multiple free slot calls andros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox