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 | /*----------------------------------------------------------------------------*/ |
