diff options
Diffstat (limited to 'fs/nfsd/nfssvc.c')
-rw-r--r-- | fs/nfsd/nfssvc.c | 45 |
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 @@ | |||
53 | extern struct svc_program nfsd_program; | 53 | extern struct svc_program nfsd_program; |
54 | static void nfsd(struct svc_rqst *rqstp); | 54 | static void nfsd(struct svc_rqst *rqstp); |
55 | struct timeval nfssvc_boot; | 55 | struct timeval nfssvc_boot; |
56 | struct svc_serv *nfsd_serv; | ||
57 | static atomic_t nfsd_busy; | 56 | static atomic_t nfsd_busy; |
58 | static unsigned long nfsd_last_call; | 57 | static unsigned long nfsd_last_call; |
59 | static DEFINE_SPINLOCK(nfsd_call_lock); | 58 | static 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 | */ | ||
74 | DEFINE_MUTEX(nfsd_mutex); | ||
75 | struct 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) |
62 | static struct svc_stat nfsd_acl_svcstats; | 78 | static struct svc_stat nfsd_acl_svcstats; |
63 | static struct svc_version * nfsd_acl_version[] = { | 79 | static struct svc_version * nfsd_acl_version[] = { |
@@ -190,13 +206,14 @@ void nfsd_reset_versions(void) | |||
190 | } | 206 | } |
191 | } | 207 | } |
192 | 208 | ||
209 | |||
193 | int nfsd_create_serv(void) | 210 | int 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 | |||
334 | nfsd_svc(unsigned short port, int nrservs) | 351 | nfsd_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 | ||