* [PATCH 1/1] nfs: fix race between renewd, umount, and the state manager in V4.1
@ 2010-01-22 4:51 Alexandros Batsakis
2010-01-22 18:47 ` Trond Myklebust
0 siblings, 1 reply; 9+ messages in thread
From: Alexandros Batsakis @ 2010-01-22 4:51 UTC (permalink / raw)
To: linux-nfs; +Cc: trond, Alexandros Batsakis
Signed-off-by: Alexandros Batsakis <batsakis@netapp.com>
---
fs/nfs/client.c | 38 ++++++++++----------------------------
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4proc.c | 3 +++
fs/nfs/nfs4state.c | 17 ++++++++++++++++-
4 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index d0b060a..3efde50 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -164,19 +164,6 @@ error_0:
return ERR_PTR(err);
}
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
-#ifdef CONFIG_NFS_V4
- if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
- nfs4_kill_renewd(clp);
- BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
- if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
- nfs_idmap_delete(clp);
-
- rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
-#endif
-}
-
/*
* Destroy the NFS4 callback service
*/
@@ -188,22 +175,18 @@ static void nfs4_destroy_callback(struct nfs_client *clp)
#endif /* CONFIG_NFS_V4 */
}
-/*
- * Clears/puts all minor version specific parts from an nfs_client struct
- * reverting it to minorversion 0.
- */
-static void nfs4_clear_client_minor_version(struct nfs_client *clp)
+static void nfs4_shutdown_client(struct nfs_client *clp)
{
-#ifdef CONFIG_NFS_V4_1
- if (nfs4_has_session(clp)) {
- nfs4_destroy_session(clp->cl_session);
- clp->cl_session = NULL;
- }
-
- clp->cl_call_sync = _nfs4_call_sync;
-#endif /* CONFIG_NFS_V4_1 */
-
+#ifdef CONFIG_NFS_V4
+ if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+ nfs4_kill_renewd(clp);
+ nfs4_clear_session(clp);
nfs4_destroy_callback(clp);
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ nfs_idmap_delete(clp);
+
+ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+#endif
}
/*
@@ -213,7 +196,6 @@ static void nfs_free_client(struct nfs_client *clp)
{
dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
- nfs4_clear_client_minor_version(clp);
nfs4_shutdown_client(clp);
nfs_fscache_release_client_cookie(clp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index cd93dfc..fbeec98 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -263,6 +263,7 @@ extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
+void nfs4_clear_session(struct nfs_client *clp);
#if defined(CONFIG_NFS_V4_1)
struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ec9f075..a99c7d3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5004,6 +5004,9 @@ void nfs41_sequence_call_done(struct rpc_task *task, void *data)
{
struct nfs_client *clp = (struct nfs_client *)data;
+ if (!nfs4_has_session(clp))
+ return;
+
nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status);
if (task->tk_status < 0) {
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 069dcb3..dc3cfbf 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -199,6 +199,16 @@ struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
return cred;
}
+void nfs4_clear_session(struct nfs_client *clp)
+{
+ if (nfs4_has_session(clp)) {
+ nfs4_begin_drain_session(clp);
+ nfs4_destroy_session(clp->cl_session);
+ clp->cl_session = NULL;
+ }
+ clp->cl_call_sync = _nfs4_call_sync;
+}
+
#endif /* CONFIG_NFS_V4_1 */
struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
@@ -878,7 +888,11 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
return;
__module_get(THIS_MODULE);
- atomic_inc(&clp->cl_count);
+ if (!atomic_inc_not_zero(&clp->cl_count)) {
+ nfs4_clear_state_manager_bit(clp);
+ module_put(THIS_MODULE);
+ return;
+ }
task = kthread_run(nfs4_run_state_manager, clp, "%s-manager",
rpc_peeraddr2str(clp->cl_rpcclient,
RPC_DISPLAY_ADDR));
@@ -1336,6 +1350,7 @@ static int nfs4_recall_slot(struct nfs_client *clp)
#else /* CONFIG_NFS_V4_1 */
static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
+void nfs4_clear_session(struct nfs_client *clp) { return 0; }
static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
#endif /* CONFIG_NFS_V4_1 */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH 1/1] nfs: fix race between renewd, umount, and the state manager in V4.1
2010-01-22 4:51 [PATCH 1/1] nfs: fix race between renewd, umount, and the state manager in V4.1 Alexandros Batsakis
@ 2010-01-22 18:47 ` Trond Myklebust
2010-01-22 19:30 ` Batsakis, Alexandros
0 siblings, 1 reply; 9+ messages in thread
From: Trond Myklebust @ 2010-01-22 18:47 UTC (permalink / raw)
To: Alexandros Batsakis; +Cc: linux-nfs, trond
On Thu, 2010-01-21 at 20:51 -0800, Alexandros Batsakis wrote:
> struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
> @@ -878,7 +888,11 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
> if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
> return;
> __module_get(THIS_MODULE);
> - atomic_inc(&clp->cl_count);
> + if (!atomic_inc_not_zero(&clp->cl_count)) {
> + nfs4_clear_state_manager_bit(clp);
> + module_put(THIS_MODULE);
> + return;
> + }
The use of atomic_inc_not_zero() should not be necessary here. Anybody
who is calling this function without holding a reference to clp is doing
something fundamentally wrong.
Trond
^ permalink raw reply [flat|nested] 9+ messages in thread* RE: [PATCH 1/1] nfs: fix race between renewd, umount, and the state manager in V4.1
2010-01-22 18:47 ` Trond Myklebust
@ 2010-01-22 19:30 ` Batsakis, Alexandros
[not found] ` <B9364369CA66BF45806C2CD86EAB8BA604F35537-hX7t0kiaRRqx3DEm5hsDiAK/GNPrWCqfQQ4Iyu8u01E@public.gmane.org>
0 siblings, 1 reply; 9+ messages in thread
From: Batsakis, Alexandros @ 2010-01-22 19:30 UTC (permalink / raw)
To: Myklebust, Trond; +Cc: linux-nfs
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogTXlrbGVidXN0LCBUcm9u
ZA0KPiBTZW50OiBGcmlkYXksIEphbnVhcnkgMjIsIDIwMTAgMTA6NDcgQU0NCj4gVG86IEJhdHNh
a2lzLCBBbGV4YW5kcm9zDQo+IENjOiBsaW51eC1uZnNAdmdlci5rZXJuZWwub3JnOyBNeWtsZWJ1
c3QsIFRyb25kDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggMS8xXSBuZnM6IGZpeCByYWNlIGJldHdl
ZW4gcmVuZXdkLCB1bW91bnQsIGFuZCB0aGUNCj4gc3RhdGUgbWFuYWdlciBpbiBWNC4xDQo+IA0K
PiBPbiBUaHUsIDIwMTAtMDEtMjEgYXQgMjA6NTEgLTA4MDAsIEFsZXhhbmRyb3MgQmF0c2FraXMg
d3JvdGU6DQo+IA0KPiA+IHN0cnVjdCBycGNfY3JlZCAqbmZzNF9nZXRfc2V0Y2xpZW50aWRfY3Jl
ZChzdHJ1Y3QgbmZzX2NsaWVudCAqY2xwKQ0KPiA+IEBAIC04NzgsNyArODg4LDExIEBAIHZvaWQg
bmZzNF9zY2hlZHVsZV9zdGF0ZV9tYW5hZ2VyKHN0cnVjdA0KPiBuZnNfY2xpZW50ICpjbHApDQo+
ID4gIAlpZiAodGVzdF9hbmRfc2V0X2JpdChORlM0Q0xOVF9NQU5BR0VSX1JVTk5JTkcsICZjbHAt
PmNsX3N0YXRlKSAhPQ0KPiAwKQ0KPiA+ICAJCXJldHVybjsNCj4gPiAgCV9fbW9kdWxlX2dldChU
SElTX01PRFVMRSk7DQo+ID4gLQlhdG9taWNfaW5jKCZjbHAtPmNsX2NvdW50KTsNCj4gPiArCWlm
ICghYXRvbWljX2luY19ub3RfemVybygmY2xwLT5jbF9jb3VudCkpIHsNCj4gPiArCQluZnM0X2Ns
ZWFyX3N0YXRlX21hbmFnZXJfYml0KGNscCk7DQo+ID4gKwkJbW9kdWxlX3B1dChUSElTX01PRFVM
RSk7DQo+ID4gKwkJcmV0dXJuOw0KPiA+ICsJfQ0KPiANCj4gVGhlIHVzZSBvZiBhdG9taWNfaW5j
X25vdF96ZXJvKCkgc2hvdWxkIG5vdCBiZSBuZWNlc3NhcnkgaGVyZS4gQW55Ym9keQ0KPiB3aG8g
aXMgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIHdpdGhvdXQgaG9sZGluZyBhIHJlZmVyZW5jZSB0byBj
bHAgaXMNCj4gZG9pbmcNCj4gc29tZXRoaW5nIGZ1bmRhbWVudGFsbHkgd3JvbmcuDQoNCkFncmVl
ZCwgYnV0IGhvdyBjYW4gd2UgZW5mb3JjZSB0aGlzIChlc3BlY2lhbGx5IHdpdGggYXN5bmNocm9u
b3VzIFJQQykgPw0KRm9yIGV4YW1wbGUgd2hhdCB3aWxsIGhhcHBlbiBpZiBfZHVyaW5nXyB1bW91
bnQgKGFmdGVyIG5mc19wdXRfY2xpZW50KCkpLCBhbiBORlMgY2FsbCB0aGF0IHdhcyBzbGVlcGlu
ZyBlLmcuIHdhaXRpbmcgZm9yIHRoZSBzZXJ2ZXIgdG8gY29tZSB1cCwgcmVhY2hlcyB0aGUgc2Vy
dmVyIGFuZCB0aGUgcmVzcG9uc2UgY2F1c2VzIHRoZSBzdGF0ZSBtYW5hZ2VyIHRvIHN0YXJ0ID8N
CkFueSBpZGVhcyA/DQoNCi1hDQoNCj4gDQo+IFRyb25kDQo=
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/1] nfs: fix race between renewd, umount, and the state manager in V4.1
@ 2010-01-14 0:15 Alexandros Batsakis
0 siblings, 0 replies; 9+ messages in thread
From: Alexandros Batsakis @ 2010-01-14 0:15 UTC (permalink / raw)
To: linux-nfs; +Cc: Alexandros Batsakis
Signed-off-by: Alexandros Batsakis <batsakis@netapp.com>
---
fs/nfs/client.c | 27 +++++++++++++--------------
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4proc.c | 4 ++++
fs/nfs/nfs4state.c | 8 ++++++--
4 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index d0b060a..6c7d407 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -164,19 +164,6 @@ error_0:
return ERR_PTR(err);
}
-static void nfs4_shutdown_client(struct nfs_client *clp)
-{
-#ifdef CONFIG_NFS_V4
- if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
- nfs4_kill_renewd(clp);
- BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
- if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
- nfs_idmap_delete(clp);
-
- rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
-#endif
-}
-
/*
* Destroy the NFS4 callback service
*/
@@ -206,6 +193,19 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp)
nfs4_destroy_callback(clp);
}
+static void nfs4_shutdown_client(struct nfs_client *clp)
+{
+#ifdef CONFIG_NFS_V4
+ if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
+ nfs4_kill_renewd(clp);
+ nfs4_clear_client_minor_version(clp);
+ if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
+ nfs_idmap_delete(clp);
+
+ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
+#endif
+}
+
/*
* Destroy a shared client record
*/
@@ -213,7 +213,6 @@ static void nfs_free_client(struct nfs_client *clp)
{
dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
- nfs4_clear_client_minor_version(clp);
nfs4_shutdown_client(clp);
nfs_fscache_release_client_cookie(clp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 865265b..783c986 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -262,6 +262,7 @@ extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp);
+int nfs4_begin_drain_session(struct nfs_client *clp);
#if defined(CONFIG_NFS_V4_1)
struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp);
struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a4b7d69..f424b1a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4728,6 +4728,7 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
void nfs4_destroy_session(struct nfs4_session *session)
{
+ nfs4_begin_drain_session(session->clp);
nfs4_proc_destroy_session(session);
dprintk("%s Destroy backchannel for xprt %p\n",
__func__, session->clp->cl_rpcclient->cl_xprt);
@@ -4996,6 +4997,9 @@ 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;
+
+ if (!nfs4_has_session(clp))
+ return;
nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 6d263ed..09f4402 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -156,7 +156,7 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
}
}
-static int nfs4_begin_drain_session(struct nfs_client *clp)
+int nfs4_begin_drain_session(struct nfs_client *clp)
{
struct nfs4_session *ses = clp->cl_session;
struct nfs4_slot_table *tbl = &ses->fc_slot_table;
@@ -878,7 +878,11 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
return;
__module_get(THIS_MODULE);
- atomic_inc(&clp->cl_count);
+ if (!atomic_inc_not_zero(&clp->cl_count)) {
+ nfs4_clear_state_manager_bit(clp);
+ module_put(THIS_MODULE);
+ return;
+ }
task = kthread_run(nfs4_run_state_manager, clp, "%s-manager",
rpc_peeraddr2str(clp->cl_rpcclient,
RPC_DISPLAY_ADDR));
--
1.6.2.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-01-22 20:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-22 4:51 [PATCH 1/1] nfs: fix race between renewd, umount, and the state manager in V4.1 Alexandros Batsakis
2010-01-22 18:47 ` Trond Myklebust
2010-01-22 19:30 ` Batsakis, Alexandros
[not found] ` <B9364369CA66BF45806C2CD86EAB8BA604F35537-hX7t0kiaRRqx3DEm5hsDiAK/GNPrWCqfQQ4Iyu8u01E@public.gmane.org>
2010-01-22 19:41 ` Trond Myklebust
2010-01-22 20:01 ` Batsakis, Alexandros
[not found] ` <B9364369CA66BF45806C2CD86EAB8BA604F35581-hX7t0kiaRRqx3DEm5hsDiAK/GNPrWCqfQQ4Iyu8u01E@public.gmane.org>
2010-01-22 20:11 ` Trond Myklebust
2010-01-22 20:21 ` Trond Myklebust
2010-01-22 20:24 ` Batsakis, Alexandros
-- strict thread matches above, loose matches on Subject: below --
2010-01-14 0:15 Alexandros Batsakis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox