diff options
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r-- | fs/nfsd/nfsctl.c | 118 |
1 files changed, 86 insertions, 32 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 5ac00c4fee91..1955a2702e60 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -310,9 +310,12 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size) | |||
310 | 310 | ||
311 | static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) | 311 | static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) |
312 | { | 312 | { |
313 | __be32 server_ip; | 313 | struct sockaddr_in sin = { |
314 | char *fo_path, c; | 314 | .sin_family = AF_INET, |
315 | }; | ||
315 | int b1, b2, b3, b4; | 316 | int b1, b2, b3, b4; |
317 | char c; | ||
318 | char *fo_path; | ||
316 | 319 | ||
317 | /* sanity check */ | 320 | /* sanity check */ |
318 | if (size == 0) | 321 | if (size == 0) |
@@ -326,11 +329,13 @@ static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) | |||
326 | return -EINVAL; | 329 | return -EINVAL; |
327 | 330 | ||
328 | /* get ipv4 address */ | 331 | /* get ipv4 address */ |
329 | if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4) | 332 | if (sscanf(fo_path, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) != 4) |
330 | return -EINVAL; | 333 | return -EINVAL; |
331 | server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); | 334 | if (b1 > 255 || b2 > 255 || b3 > 255 || b4 > 255) |
335 | return -EINVAL; | ||
336 | sin.sin_addr.s_addr = htonl((b1 << 24) | (b2 << 16) | (b3 << 8) | b4); | ||
332 | 337 | ||
333 | return nlmsvc_unlock_all_by_ip(server_ip); | 338 | return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin); |
334 | } | 339 | } |
335 | 340 | ||
336 | static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size) | 341 | static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size) |
@@ -450,22 +455,26 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) | |||
450 | int i; | 455 | int i; |
451 | int rv; | 456 | int rv; |
452 | int len; | 457 | int len; |
453 | int npools = nfsd_nrpools(); | 458 | int npools; |
454 | int *nthreads; | 459 | int *nthreads; |
455 | 460 | ||
461 | mutex_lock(&nfsd_mutex); | ||
462 | npools = nfsd_nrpools(); | ||
456 | if (npools == 0) { | 463 | if (npools == 0) { |
457 | /* | 464 | /* |
458 | * NFS is shut down. The admin can start it by | 465 | * NFS is shut down. The admin can start it by |
459 | * writing to the threads file but NOT the pool_threads | 466 | * writing to the threads file but NOT the pool_threads |
460 | * file, sorry. Report zero threads. | 467 | * file, sorry. Report zero threads. |
461 | */ | 468 | */ |
469 | mutex_unlock(&nfsd_mutex); | ||
462 | strcpy(buf, "0\n"); | 470 | strcpy(buf, "0\n"); |
463 | return strlen(buf); | 471 | return strlen(buf); |
464 | } | 472 | } |
465 | 473 | ||
466 | nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); | 474 | nthreads = kcalloc(npools, sizeof(int), GFP_KERNEL); |
475 | rv = -ENOMEM; | ||
467 | if (nthreads == NULL) | 476 | if (nthreads == NULL) |
468 | return -ENOMEM; | 477 | goto out_free; |
469 | 478 | ||
470 | if (size > 0) { | 479 | if (size > 0) { |
471 | for (i = 0; i < npools; i++) { | 480 | for (i = 0; i < npools; i++) { |
@@ -496,14 +505,16 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) | |||
496 | mesg += len; | 505 | mesg += len; |
497 | } | 506 | } |
498 | 507 | ||
508 | mutex_unlock(&nfsd_mutex); | ||
499 | return (mesg-buf); | 509 | return (mesg-buf); |
500 | 510 | ||
501 | out_free: | 511 | out_free: |
502 | kfree(nthreads); | 512 | kfree(nthreads); |
513 | mutex_unlock(&nfsd_mutex); | ||
503 | return rv; | 514 | return rv; |
504 | } | 515 | } |
505 | 516 | ||
506 | static ssize_t write_versions(struct file *file, char *buf, size_t size) | 517 | static ssize_t __write_versions(struct file *file, char *buf, size_t size) |
507 | { | 518 | { |
508 | /* | 519 | /* |
509 | * Format: | 520 | * Format: |
@@ -566,14 +577,23 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
566 | return len; | 577 | return len; |
567 | } | 578 | } |
568 | 579 | ||
569 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | 580 | static ssize_t write_versions(struct file *file, char *buf, size_t size) |
581 | { | ||
582 | ssize_t rv; | ||
583 | |||
584 | mutex_lock(&nfsd_mutex); | ||
585 | rv = __write_versions(file, buf, size); | ||
586 | mutex_unlock(&nfsd_mutex); | ||
587 | return rv; | ||
588 | } | ||
589 | |||
590 | static ssize_t __write_ports(struct file *file, char *buf, size_t size) | ||
570 | { | 591 | { |
571 | if (size == 0) { | 592 | if (size == 0) { |
572 | int len = 0; | 593 | int len = 0; |
573 | lock_kernel(); | 594 | |
574 | if (nfsd_serv) | 595 | if (nfsd_serv) |
575 | len = svc_xprt_names(nfsd_serv, buf, 0); | 596 | len = svc_xprt_names(nfsd_serv, buf, 0); |
576 | unlock_kernel(); | ||
577 | return len; | 597 | return len; |
578 | } | 598 | } |
579 | /* Either a single 'fd' number is written, in which | 599 | /* Either a single 'fd' number is written, in which |
@@ -603,9 +623,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
603 | /* Decrease the count, but don't shutdown the | 623 | /* Decrease the count, but don't shutdown the |
604 | * the service | 624 | * the service |
605 | */ | 625 | */ |
606 | lock_kernel(); | ||
607 | nfsd_serv->sv_nrthreads--; | 626 | nfsd_serv->sv_nrthreads--; |
608 | unlock_kernel(); | ||
609 | } | 627 | } |
610 | return err < 0 ? err : 0; | 628 | return err < 0 ? err : 0; |
611 | } | 629 | } |
@@ -614,10 +632,8 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
614 | int len = 0; | 632 | int len = 0; |
615 | if (!toclose) | 633 | if (!toclose) |
616 | return -ENOMEM; | 634 | return -ENOMEM; |
617 | lock_kernel(); | ||
618 | if (nfsd_serv) | 635 | if (nfsd_serv) |
619 | len = svc_sock_names(buf, nfsd_serv, toclose); | 636 | len = svc_sock_names(buf, nfsd_serv, toclose); |
620 | unlock_kernel(); | ||
621 | if (len >= 0) | 637 | if (len >= 0) |
622 | lockd_down(); | 638 | lockd_down(); |
623 | kfree(toclose); | 639 | kfree(toclose); |
@@ -655,7 +671,6 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
655 | if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { | 671 | if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { |
656 | if (port == 0) | 672 | if (port == 0) |
657 | return -EINVAL; | 673 | return -EINVAL; |
658 | lock_kernel(); | ||
659 | if (nfsd_serv) { | 674 | if (nfsd_serv) { |
660 | xprt = svc_find_xprt(nfsd_serv, transport, | 675 | xprt = svc_find_xprt(nfsd_serv, transport, |
661 | AF_UNSPEC, port); | 676 | AF_UNSPEC, port); |
@@ -666,13 +681,23 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
666 | } else | 681 | } else |
667 | err = -ENOTCONN; | 682 | err = -ENOTCONN; |
668 | } | 683 | } |
669 | unlock_kernel(); | ||
670 | return err < 0 ? err : 0; | 684 | return err < 0 ? err : 0; |
671 | } | 685 | } |
672 | } | 686 | } |
673 | return -EINVAL; | 687 | return -EINVAL; |
674 | } | 688 | } |
675 | 689 | ||
690 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | ||
691 | { | ||
692 | ssize_t rv; | ||
693 | |||
694 | mutex_lock(&nfsd_mutex); | ||
695 | rv = __write_ports(file, buf, size); | ||
696 | mutex_unlock(&nfsd_mutex); | ||
697 | return rv; | ||
698 | } | ||
699 | |||
700 | |||
676 | int nfsd_max_blksize; | 701 | int nfsd_max_blksize; |
677 | 702 | ||
678 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | 703 | static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) |
@@ -691,13 +716,13 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | |||
691 | if (bsize > NFSSVC_MAXBLKSIZE) | 716 | if (bsize > NFSSVC_MAXBLKSIZE) |
692 | bsize = NFSSVC_MAXBLKSIZE; | 717 | bsize = NFSSVC_MAXBLKSIZE; |
693 | bsize &= ~(1024-1); | 718 | bsize &= ~(1024-1); |
694 | lock_kernel(); | 719 | mutex_lock(&nfsd_mutex); |
695 | if (nfsd_serv && nfsd_serv->sv_nrthreads) { | 720 | if (nfsd_serv && nfsd_serv->sv_nrthreads) { |
696 | unlock_kernel(); | 721 | mutex_unlock(&nfsd_mutex); |
697 | return -EBUSY; | 722 | return -EBUSY; |
698 | } | 723 | } |
699 | nfsd_max_blksize = bsize; | 724 | nfsd_max_blksize = bsize; |
700 | unlock_kernel(); | 725 | mutex_unlock(&nfsd_mutex); |
701 | } | 726 | } |
702 | return sprintf(buf, "%d\n", nfsd_max_blksize); | 727 | return sprintf(buf, "%d\n", nfsd_max_blksize); |
703 | } | 728 | } |
@@ -705,16 +730,17 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | |||
705 | #ifdef CONFIG_NFSD_V4 | 730 | #ifdef CONFIG_NFSD_V4 |
706 | extern time_t nfs4_leasetime(void); | 731 | extern time_t nfs4_leasetime(void); |
707 | 732 | ||
708 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size) | 733 | static ssize_t __write_leasetime(struct file *file, char *buf, size_t size) |
709 | { | 734 | { |
710 | /* if size > 10 seconds, call | 735 | /* if size > 10 seconds, call |
711 | * nfs4_reset_lease() then write out the new lease (seconds) as reply | 736 | * nfs4_reset_lease() then write out the new lease (seconds) as reply |
712 | */ | 737 | */ |
713 | char *mesg = buf; | 738 | char *mesg = buf; |
714 | int rv; | 739 | int rv, lease; |
715 | 740 | ||
716 | if (size > 0) { | 741 | if (size > 0) { |
717 | int lease; | 742 | if (nfsd_serv) |
743 | return -EBUSY; | ||
718 | rv = get_int(&mesg, &lease); | 744 | rv = get_int(&mesg, &lease); |
719 | if (rv) | 745 | if (rv) |
720 | return rv; | 746 | return rv; |
@@ -726,24 +752,52 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size) | |||
726 | return strlen(buf); | 752 | return strlen(buf); |
727 | } | 753 | } |
728 | 754 | ||
729 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) | 755 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size) |
756 | { | ||
757 | ssize_t rv; | ||
758 | |||
759 | mutex_lock(&nfsd_mutex); | ||
760 | rv = __write_leasetime(file, buf, size); | ||
761 | mutex_unlock(&nfsd_mutex); | ||
762 | return rv; | ||
763 | } | ||
764 | |||
765 | extern char *nfs4_recoverydir(void); | ||
766 | |||
767 | static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) | ||
730 | { | 768 | { |
731 | char *mesg = buf; | 769 | char *mesg = buf; |
732 | char *recdir; | 770 | char *recdir; |
733 | int len, status; | 771 | int len, status; |
734 | 772 | ||
735 | if (size == 0 || size > PATH_MAX || buf[size-1] != '\n') | 773 | if (size > 0) { |
736 | return -EINVAL; | 774 | if (nfsd_serv) |
737 | buf[size-1] = 0; | 775 | return -EBUSY; |
776 | if (size > PATH_MAX || buf[size-1] != '\n') | ||
777 | return -EINVAL; | ||
778 | buf[size-1] = 0; | ||
738 | 779 | ||
739 | recdir = mesg; | 780 | recdir = mesg; |
740 | len = qword_get(&mesg, recdir, size); | 781 | len = qword_get(&mesg, recdir, size); |
741 | if (len <= 0) | 782 | if (len <= 0) |
742 | return -EINVAL; | 783 | return -EINVAL; |
743 | 784 | ||
744 | status = nfs4_reset_recoverydir(recdir); | 785 | status = nfs4_reset_recoverydir(recdir); |
786 | } | ||
787 | sprintf(buf, "%s\n", nfs4_recoverydir()); | ||
745 | return strlen(buf); | 788 | return strlen(buf); |
746 | } | 789 | } |
790 | |||
791 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) | ||
792 | { | ||
793 | ssize_t rv; | ||
794 | |||
795 | mutex_lock(&nfsd_mutex); | ||
796 | rv = __write_recoverydir(file, buf, size); | ||
797 | mutex_unlock(&nfsd_mutex); | ||
798 | return rv; | ||
799 | } | ||
800 | |||
747 | #endif | 801 | #endif |
748 | 802 | ||
749 | /*----------------------------------------------------------------------------*/ | 803 | /*----------------------------------------------------------------------------*/ |