diff options
author | Neil Brown <neilb@suse.de> | 2008-06-10 08:40:35 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-06-23 13:02:49 -0400 |
commit | bedbdd8bada194a690d2901801bf8451965086b3 (patch) | |
tree | dc7ea15dd52370429bd63cd6803d6402cebbd50b /fs/nfsd/nfsctl.c | |
parent | 0d169ca136357d51a65d686f3c84866a8ba20ae9 (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/nfsctl.c')
-rw-r--r-- | fs/nfsd/nfsctl.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 5ac00c4fee91..049d2a9c7715 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -450,22 +450,26 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) | |||
450 | int i; | 450 | int i; |
451 | int rv; | 451 | int rv; |
452 | int len; | 452 | int len; |
453 | int npools = nfsd_nrpools(); | 453 | int npools; |
454 | int *nthreads; | 454 | int *nthreads; |
455 | 455 | ||
456 | mutex_lock(&nfsd_mutex); | ||
457 | npools = nfsd_nrpools(); | ||
456 | if (npools == 0) { | 458 | if (npools == 0) { |
457 | /* | 459 | /* |
458 | * NFS is shut down. The admin can start it by | 460 | * NFS is shut down. The admin can start it by |
459 | * writing to the threads file but NOT the pool_threads | 461 | * writing to the threads file but NOT the pool_threads |
460 | * file, sorry. Report zero threads. | 462 | * file, sorry. Report zero threads. |
461 | */ | 463 | */ |
464 | mutex_unlock(&nfsd_mutex); | ||
462 | strcpy(buf, "0\n"); | 465 | strcpy(buf, "0\n"); |
463 | return strlen(buf); | 466 | return strlen(buf); |
464 | } | 467 | } |
465 | 468 | ||
466 | nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); | 469 | nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); |
470 | rv = -ENOMEM; | ||
467 | if (nthreads == NULL) | 471 | if (nthreads == NULL) |
468 | return -ENOMEM; | 472 | goto out_free; |
469 | 473 | ||
470 | if (size > 0) { | 474 | if (size > 0) { |
471 | for (i = 0; i < npools; i++) { | 475 | for (i = 0; i < npools; i++) { |
@@ -496,10 +500,12 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) | |||
496 | mesg += len; | 500 | mesg += len; |
497 | } | 501 | } |
498 | 502 | ||
503 | mutex_unlock(&nfsd_mutex); | ||
499 | return (mesg-buf); | 504 | return (mesg-buf); |
500 | 505 | ||
501 | out_free: | 506 | out_free: |
502 | kfree(nthreads); | 507 | kfree(nthreads); |
508 | mutex_unlock(&nfsd_mutex); | ||
503 | return rv; | 509 | return rv; |
504 | } | 510 | } |
505 | 511 | ||
@@ -566,14 +572,13 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
566 | return len; | 572 | return len; |
567 | } | 573 | } |
568 | 574 | ||
569 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | 575 | static ssize_t __write_ports(struct file *file, char *buf, size_t size) |
570 | { | 576 | { |
571 | if (size == 0) { | 577 | if (size == 0) { |
572 | int len = 0; | 578 | int len = 0; |
573 | lock_kernel(); | 579 | |
574 | if (nfsd_serv) | 580 | if (nfsd_serv) |
575 | len = svc_xprt_names(nfsd_serv, buf, 0); | 581 | len = svc_xprt_names(nfsd_serv, buf, 0); |
576 | unlock_kernel(); | ||
577 | return len; | 582 | return len; |
578 | } | 583 | } |
579 | /* Either a single 'fd' number is written, in which | 584 | /* Either a single 'fd' number is written, in which |
@@ -603,9 +608,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
603 | /* Decrease the count, but don't shutdown the | 608 | /* Decrease the count, but don't shutdown the |
604 | * the service | 609 | * the service |
605 | */ | 610 | */ |
606 | lock_kernel(); | ||
607 | nfsd_serv->sv_nrthreads--; | 611 | nfsd_serv->sv_nrthreads--; |
608 | unlock_kernel(); | ||
609 | } | 612 | } |
610 | return err < 0 ? err : 0; | 613 | return err < 0 ? err : 0; |
611 | } | 614 | } |
@@ -614,10 +617,8 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
614 | int len = 0; | 617 | int len = 0; |
615 | if (!toclose) | 618 | if (!toclose) |
616 | return -ENOMEM; | 619 | return -ENOMEM; |
617 | lock_kernel(); | ||
618 | if (nfsd_serv) | 620 | if (nfsd_serv) |
619 | len = svc_sock_names(buf, nfsd_serv, toclose); | 621 | len = svc_sock_names(buf, nfsd_serv, toclose); |
620 | unlock_kernel(); | ||
621 | if (len >= 0) | 622 | if (len >= 0) |
622 | lockd_down(); | 623 | lockd_down(); |
623 | kfree(toclose); | 624 | kfree(toclose); |
@@ -655,7 +656,6 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
655 | if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { | 656 | if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { |
656 | if (port == 0) | 657 | if (port == 0) |
657 | return -EINVAL; | 658 | return -EINVAL; |
658 | lock_kernel(); | ||
659 | if (nfsd_serv) { | 659 | if (nfsd_serv) { |
660 | xprt = svc_find_xprt(nfsd_serv, transport, | 660 | xprt = svc_find_xprt(nfsd_serv, transport, |
661 | AF_UNSPEC, port); | 661 | AF_UNSPEC, port); |
@@ -666,13 +666,22 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
666 | } else | 666 | } else |
667 | err = -ENOTCONN; | 667 | err = -ENOTCONN; |
668 | } | 668 | } |
669 | unlock_kernel(); | ||
670 | return err < 0 ? err : 0; | 669 | return err < 0 ? err : 0; |
671 | } | 670 | } |
672 | } | 671 | } |
673 | return -EINVAL; | 672 | return -EINVAL; |
674 | } | 673 | } |
675 | 674 | ||
675 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | ||
676 | { | ||
677 | ssize_t rv; | ||
678 | mutex_lock(&nfsd_mutex); | ||
679 | rv = __write_ports(file, buf, size); | ||
680 | mutex_unlock(&nfsd_mutex); | ||
681 | return rv; | ||
682 | } | ||
683 | |||
684 | |||
676 | int nfsd_max_blksize; | 685 | int nfsd_max_blksize; |
677 | 686 | ||
678 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | 687 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) |
@@ -691,13 +700,13 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | |||
691 | if (bsize > NFSSVC_MAXBLKSIZE) | 700 | if (bsize > NFSSVC_MAXBLKSIZE) |
692 | bsize = NFSSVC_MAXBLKSIZE; | 701 | bsize = NFSSVC_MAXBLKSIZE; |
693 | bsize &= ~(1024-1); | 702 | bsize &= ~(1024-1); |
694 | lock_kernel(); | 703 | mutex_lock(&nfsd_mutex); |
695 | if (nfsd_serv && nfsd_serv->sv_nrthreads) { | 704 | if (nfsd_serv && nfsd_serv->sv_nrthreads) { |
696 | unlock_kernel(); | 705 | mutex_unlock(&nfsd_mutex); |
697 | return -EBUSY; | 706 | return -EBUSY; |
698 | } | 707 | } |
699 | nfsd_max_blksize = bsize; | 708 | nfsd_max_blksize = bsize; |
700 | unlock_kernel(); | 709 | mutex_unlock(&nfsd_mutex); |
701 | } | 710 | } |
702 | return sprintf(buf, "%d\n", nfsd_max_blksize); | 711 | return sprintf(buf, "%d\n", nfsd_max_blksize); |
703 | } | 712 | } |