aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfssvc.c
diff options
context:
space:
mode:
authorNeil Brown <neilb@suse.de>2008-06-10 08:40:35 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-06-23 13:02:49 -0400
commitbedbdd8bada194a690d2901801bf8451965086b3 (patch)
treedc7ea15dd52370429bd63cd6803d6402cebbd50b /fs/nfsd/nfssvc.c
parent0d169ca136357d51a65d686f3c84866a8ba20ae9 (diff)
knfsd: Replace lock_kernel with a mutex for nfsd thread startup/shutdown locking.
This removes the BKL from the RPC service creation codepath. The BKL really isn't adequate for this job since some of this info needs protection across sleeps. Also, add some comments to try and clarify how the locking should work and to make it clear that the BKL isn't necessary as long as there is adequate locking between tasks when touching the svc_serv fields. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfssvc.c')
-rw-r--r--fs/nfsd/nfssvc.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 941041f4b136..512bd04c6dda 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -53,11 +53,27 @@
53extern struct svc_program nfsd_program; 53extern struct svc_program nfsd_program;
54static void nfsd(struct svc_rqst *rqstp); 54static void nfsd(struct svc_rqst *rqstp);
55struct timeval nfssvc_boot; 55struct timeval nfssvc_boot;
56 struct svc_serv *nfsd_serv;
57static atomic_t nfsd_busy; 56static atomic_t nfsd_busy;
58static unsigned long nfsd_last_call; 57static unsigned long nfsd_last_call;
59static DEFINE_SPINLOCK(nfsd_call_lock); 58static DEFINE_SPINLOCK(nfsd_call_lock);
60 59
60/*
61 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
62 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
63 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
64 *
65 * If (out side the lock) nfsd_serv is non-NULL, then it must point to a
66 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
67 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
68 * entry of ->sv_pools[].
69 *
70 * Transitions of the thread count between zero and non-zero are of particular
71 * interest since the svc_serv needs to be created and initialized at that
72 * point, or freed.
73 */
74DEFINE_MUTEX(nfsd_mutex);
75struct svc_serv *nfsd_serv;
76
61#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 77#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
62static struct svc_stat nfsd_acl_svcstats; 78static struct svc_stat nfsd_acl_svcstats;
63static struct svc_version * nfsd_acl_version[] = { 79static struct svc_version * nfsd_acl_version[] = {
@@ -190,13 +206,14 @@ void nfsd_reset_versions(void)
190 } 206 }
191} 207}
192 208
209
193int nfsd_create_serv(void) 210int nfsd_create_serv(void)
194{ 211{
195 int err = 0; 212 int err = 0;
196 lock_kernel(); 213
214 WARN_ON(!mutex_is_locked(&nfsd_mutex));
197 if (nfsd_serv) { 215 if (nfsd_serv) {
198 svc_get(nfsd_serv); 216 svc_get(nfsd_serv);
199 unlock_kernel();
200 return 0; 217 return 0;
201 } 218 }
202 if (nfsd_max_blksize == 0) { 219 if (nfsd_max_blksize == 0) {
@@ -223,7 +240,7 @@ int nfsd_create_serv(void)
223 nfsd, SIG_NOCLEAN, THIS_MODULE); 240 nfsd, SIG_NOCLEAN, THIS_MODULE);
224 if (nfsd_serv == NULL) 241 if (nfsd_serv == NULL)
225 err = -ENOMEM; 242 err = -ENOMEM;
226 unlock_kernel(); 243
227 do_gettimeofday(&nfssvc_boot); /* record boot time */ 244 do_gettimeofday(&nfssvc_boot); /* record boot time */
228 return err; 245 return err;
229} 246}
@@ -282,6 +299,8 @@ int nfsd_set_nrthreads(int n, int *nthreads)
282 int tot = 0; 299 int tot = 0;
283 int err = 0; 300 int err = 0;
284 301
302 WARN_ON(!mutex_is_locked(&nfsd_mutex));
303
285 if (nfsd_serv == NULL || n <= 0) 304 if (nfsd_serv == NULL || n <= 0)
286 return 0; 305 return 0;
287 306
@@ -316,7 +335,6 @@ int nfsd_set_nrthreads(int n, int *nthreads)
316 nthreads[0] = 1; 335 nthreads[0] = 1;
317 336
318 /* apply the new numbers */ 337 /* apply the new numbers */
319 lock_kernel();
320 svc_get(nfsd_serv); 338 svc_get(nfsd_serv);
321 for (i = 0; i < n; i++) { 339 for (i = 0; i < n; i++) {
322 err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i], 340 err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i],
@@ -325,7 +343,6 @@ int nfsd_set_nrthreads(int n, int *nthreads)
325 break; 343 break;
326 } 344 }
327 svc_destroy(nfsd_serv); 345 svc_destroy(nfsd_serv);
328 unlock_kernel();
329 346
330 return err; 347 return err;
331} 348}
@@ -334,8 +351,8 @@ int
334nfsd_svc(unsigned short port, int nrservs) 351nfsd_svc(unsigned short port, int nrservs)
335{ 352{
336 int error; 353 int error;
337 354
338 lock_kernel(); 355 mutex_lock(&nfsd_mutex);
339 dprintk("nfsd: creating service\n"); 356 dprintk("nfsd: creating service\n");
340 error = -EINVAL; 357 error = -EINVAL;
341 if (nrservs <= 0) 358 if (nrservs <= 0)
@@ -363,7 +380,7 @@ nfsd_svc(unsigned short port, int nrservs)
363 failure: 380 failure:
364 svc_destroy(nfsd_serv); /* Release server */ 381 svc_destroy(nfsd_serv); /* Release server */
365 out: 382 out:
366 unlock_kernel(); 383 mutex_unlock(&nfsd_mutex);
367 return error; 384 return error;
368} 385}
369 386
@@ -399,7 +416,7 @@ nfsd(struct svc_rqst *rqstp)
399 sigset_t shutdown_mask, allowed_mask; 416 sigset_t shutdown_mask, allowed_mask;
400 417
401 /* Lock module and set up kernel thread */ 418 /* Lock module and set up kernel thread */
402 lock_kernel(); 419 mutex_lock(&nfsd_mutex);
403 daemonize("nfsd"); 420 daemonize("nfsd");
404 421
405 /* After daemonize() this kernel thread shares current->fs 422 /* After daemonize() this kernel thread shares current->fs
@@ -417,11 +434,13 @@ nfsd(struct svc_rqst *rqstp)
417 siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS); 434 siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS);
418 siginitsetinv(&allowed_mask, ALLOWED_SIGS); 435 siginitsetinv(&allowed_mask, ALLOWED_SIGS);
419 436
437
420 nfsdstats.th_cnt++; 438 nfsdstats.th_cnt++;
421 439
422 rqstp->rq_task = current; 440 rqstp->rq_task = current;
423 441
424 unlock_kernel(); 442 mutex_unlock(&nfsd_mutex);
443
425 444
426 /* 445 /*
427 * We want less throttling in balance_dirty_pages() so that nfs to 446 * We want less throttling in balance_dirty_pages() so that nfs to
@@ -477,7 +496,7 @@ nfsd(struct svc_rqst *rqstp)
477 /* Clear signals before calling svc_exit_thread() */ 496 /* Clear signals before calling svc_exit_thread() */
478 flush_signals(current); 497 flush_signals(current);
479 498
480 lock_kernel(); 499 mutex_lock(&nfsd_mutex);
481 500
482 nfsdstats.th_cnt --; 501 nfsdstats.th_cnt --;
483 502
@@ -486,7 +505,7 @@ out:
486 svc_exit_thread(rqstp); 505 svc_exit_thread(rqstp);
487 506
488 /* Release module */ 507 /* Release module */
489 unlock_kernel(); 508 mutex_unlock(&nfsd_mutex);
490 module_put_and_exit(0); 509 module_put_and_exit(0);
491} 510}
492 511