aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfssvc.c
diff options
context:
space:
mode:
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