aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-07-03 08:46:41 -0400
committerJ. Bruce Fields <bfields@redhat.com>2012-07-25 09:21:31 -0400
commit57c8b13e3cd0f94944c9691ce7f58e5fcef8a12d (patch)
tree1730526321faaad23aef64e3a437dc2f92752e90 /fs
parent19f7e2ca44dfc3c1b3f499fc46801f98d403500f (diff)
NFSd: set nfsd_serv to NULL after service destruction
In nfsd_destroy(): if (destroy) svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_server); svc_shutdown_net(nfsd_serv, net) calls nfsd_last_thread(), which sets nfsd_serv to NULL, causing a NULL dereference on the following line. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfsd.h2
-rw-r--r--fs/nfsd/nfssvc.c10
2 files changed, 7 insertions, 5 deletions
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 7b248a24d5c5..2244222368ab 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -82,6 +82,8 @@ static inline void nfsd_destroy(struct net *net)
82 if (destroy) 82 if (destroy)
83 svc_shutdown_net(nfsd_serv, net); 83 svc_shutdown_net(nfsd_serv, net);
84 svc_destroy(nfsd_serv); 84 svc_destroy(nfsd_serv);
85 if (destroy)
86 nfsd_serv = NULL;
85} 87}
86 88
87#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 89#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 8621e36ce8dd..240473cb708f 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -254,8 +254,6 @@ static void nfsd_shutdown(void)
254 254
255static void nfsd_last_thread(struct svc_serv *serv, struct net *net) 255static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
256{ 256{
257 /* When last nfsd thread exits we need to do some clean-up */
258 nfsd_serv = NULL;
259 nfsd_shutdown(); 257 nfsd_shutdown();
260 258
261 svc_rpcb_cleanup(serv, net); 259 svc_rpcb_cleanup(serv, net);
@@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void)
332int nfsd_create_serv(void) 330int nfsd_create_serv(void)
333{ 331{
334 int error; 332 int error;
333 struct net *net = current->nsproxy->net_ns;
335 334
336 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 335 WARN_ON(!mutex_is_locked(&nfsd_mutex));
337 if (nfsd_serv) { 336 if (nfsd_serv) {
@@ -346,7 +345,7 @@ int nfsd_create_serv(void)
346 if (nfsd_serv == NULL) 345 if (nfsd_serv == NULL)
347 return -ENOMEM; 346 return -ENOMEM;
348 347
349 error = svc_bind(nfsd_serv, current->nsproxy->net_ns); 348 error = svc_bind(nfsd_serv, net);
350 if (error < 0) { 349 if (error < 0) {
351 svc_destroy(nfsd_serv); 350 svc_destroy(nfsd_serv);
352 return error; 351 return error;
@@ -557,12 +556,13 @@ nfsd(void *vrqstp)
557 nfsdstats.th_cnt --; 556 nfsdstats.th_cnt --;
558 557
559out: 558out:
560 if (rqstp->rq_server->sv_nrthreads == 1) 559 rqstp->rq_server = NULL;
561 svc_shutdown_net(rqstp->rq_server, &init_net);
562 560
563 /* Release the thread */ 561 /* Release the thread */
564 svc_exit_thread(rqstp); 562 svc_exit_thread(rqstp);
565 563
564 nfsd_destroy(&init_net);
565
566 /* Release module */ 566 /* Release module */
567 mutex_unlock(&nfsd_mutex); 567 mutex_unlock(&nfsd_mutex);
568 module_put_and_exit(0); 568 module_put_and_exit(0);