diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfssvc.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 6339cb70a08d..9e2156813710 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
22 | #include <linux/freezer.h> | 22 | #include <linux/freezer.h> |
23 | #include <linux/fs_struct.h> | 23 | #include <linux/fs_struct.h> |
24 | #include <linux/kthread.h> | ||
24 | 25 | ||
25 | #include <linux/sunrpc/types.h> | 26 | #include <linux/sunrpc/types.h> |
26 | #include <linux/sunrpc/stats.h> | 27 | #include <linux/sunrpc/stats.h> |
@@ -46,7 +47,7 @@ | |||
46 | #define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT)) | 47 | #define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT)) |
47 | 48 | ||
48 | extern struct svc_program nfsd_program; | 49 | extern struct svc_program nfsd_program; |
49 | static void nfsd(struct svc_rqst *rqstp); | 50 | static int nfsd(void *vrqstp); |
50 | struct timeval nfssvc_boot; | 51 | struct timeval nfssvc_boot; |
51 | static atomic_t nfsd_busy; | 52 | static atomic_t nfsd_busy; |
52 | static unsigned long nfsd_last_call; | 53 | static unsigned long nfsd_last_call; |
@@ -407,18 +408,19 @@ update_thread_usage(int busy_threads) | |||
407 | /* | 408 | /* |
408 | * This is the NFS server kernel thread | 409 | * This is the NFS server kernel thread |
409 | */ | 410 | */ |
410 | static void | 411 | static int |
411 | nfsd(struct svc_rqst *rqstp) | 412 | nfsd(void *vrqstp) |
412 | { | 413 | { |
414 | struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; | ||
413 | struct fs_struct *fsp; | 415 | struct fs_struct *fsp; |
414 | int err; | ||
415 | sigset_t shutdown_mask, allowed_mask; | 416 | sigset_t shutdown_mask, allowed_mask; |
417 | int err, preverr = 0; | ||
418 | unsigned int signo; | ||
416 | 419 | ||
417 | /* Lock module and set up kernel thread */ | 420 | /* Lock module and set up kernel thread */ |
418 | mutex_lock(&nfsd_mutex); | 421 | mutex_lock(&nfsd_mutex); |
419 | daemonize("nfsd"); | ||
420 | 422 | ||
421 | /* After daemonize() this kernel thread shares current->fs | 423 | /* At this point, the thread shares current->fs |
422 | * with the init process. We need to create files with a | 424 | * with the init process. We need to create files with a |
423 | * umask of 0 instead of init's umask. */ | 425 | * umask of 0 instead of init's umask. */ |
424 | fsp = copy_fs_struct(current->fs); | 426 | fsp = copy_fs_struct(current->fs); |
@@ -433,14 +435,18 @@ nfsd(struct svc_rqst *rqstp) | |||
433 | siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS); | 435 | siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS); |
434 | siginitsetinv(&allowed_mask, ALLOWED_SIGS); | 436 | siginitsetinv(&allowed_mask, ALLOWED_SIGS); |
435 | 437 | ||
438 | /* | ||
439 | * thread is spawned with all signals set to SIG_IGN, re-enable | ||
440 | * the ones that matter | ||
441 | */ | ||
442 | for (signo = 1; signo <= _NSIG; signo++) { | ||
443 | if (!sigismember(&shutdown_mask, signo)) | ||
444 | allow_signal(signo); | ||
445 | } | ||
436 | 446 | ||
437 | nfsdstats.th_cnt++; | 447 | nfsdstats.th_cnt++; |
438 | |||
439 | rqstp->rq_task = current; | ||
440 | |||
441 | mutex_unlock(&nfsd_mutex); | 448 | mutex_unlock(&nfsd_mutex); |
442 | 449 | ||
443 | |||
444 | /* | 450 | /* |
445 | * We want less throttling in balance_dirty_pages() so that nfs to | 451 | * We want less throttling in balance_dirty_pages() so that nfs to |
446 | * localhost doesn't cause nfsd to lock up due to all the client's | 452 | * localhost doesn't cause nfsd to lock up due to all the client's |
@@ -462,15 +468,25 @@ nfsd(struct svc_rqst *rqstp) | |||
462 | */ | 468 | */ |
463 | while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN) | 469 | while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN) |
464 | ; | 470 | ; |
465 | if (err < 0) | 471 | if (err == -EINTR) |
466 | break; | 472 | break; |
473 | else if (err < 0) { | ||
474 | if (err != preverr) { | ||
475 | printk(KERN_WARNING "%s: unexpected error " | ||
476 | "from svc_recv (%d)\n", __func__, -err); | ||
477 | preverr = err; | ||
478 | } | ||
479 | schedule_timeout_uninterruptible(HZ); | ||
480 | continue; | ||
481 | } | ||
482 | |||
467 | update_thread_usage(atomic_read(&nfsd_busy)); | 483 | update_thread_usage(atomic_read(&nfsd_busy)); |
468 | atomic_inc(&nfsd_busy); | 484 | atomic_inc(&nfsd_busy); |
469 | 485 | ||
470 | /* Lock the export hash tables for reading. */ | 486 | /* Lock the export hash tables for reading. */ |
471 | exp_readlock(); | 487 | exp_readlock(); |
472 | 488 | ||
473 | /* Process request with signals blocked. */ | 489 | /* Process request with signals blocked. */ |
474 | sigprocmask(SIG_SETMASK, &allowed_mask, NULL); | 490 | sigprocmask(SIG_SETMASK, &allowed_mask, NULL); |
475 | 491 | ||
476 | svc_process(rqstp); | 492 | svc_process(rqstp); |
@@ -481,14 +497,10 @@ nfsd(struct svc_rqst *rqstp) | |||
481 | atomic_dec(&nfsd_busy); | 497 | atomic_dec(&nfsd_busy); |
482 | } | 498 | } |
483 | 499 | ||
484 | if (err != -EINTR) | ||
485 | printk(KERN_WARNING "nfsd: terminating on error %d\n", -err); | ||
486 | |||
487 | /* Clear signals before calling svc_exit_thread() */ | 500 | /* Clear signals before calling svc_exit_thread() */ |
488 | flush_signals(current); | 501 | flush_signals(current); |
489 | 502 | ||
490 | mutex_lock(&nfsd_mutex); | 503 | mutex_lock(&nfsd_mutex); |
491 | |||
492 | nfsdstats.th_cnt --; | 504 | nfsdstats.th_cnt --; |
493 | 505 | ||
494 | out: | 506 | out: |
@@ -498,6 +510,7 @@ out: | |||
498 | /* Release module */ | 510 | /* Release module */ |
499 | mutex_unlock(&nfsd_mutex); | 511 | mutex_unlock(&nfsd_mutex); |
500 | module_put_and_exit(0); | 512 | module_put_and_exit(0); |
513 | return 0; | ||
501 | } | 514 | } |
502 | 515 | ||
503 | static __be32 map_new_errors(u32 vers, __be32 nfserr) | 516 | static __be32 map_new_errors(u32 vers, __be32 nfserr) |