diff options
Diffstat (limited to 'fs/nfsd/nfsctl.c')
| -rw-r--r-- | fs/nfsd/nfsctl.c | 124 |
1 files changed, 103 insertions, 21 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 77dc9893b7ba..8516137cdbb0 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -304,6 +304,9 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) | |||
| 304 | struct auth_domain *dom; | 304 | struct auth_domain *dom; |
| 305 | struct knfsd_fh fh; | 305 | struct knfsd_fh fh; |
| 306 | 306 | ||
| 307 | if (size == 0) | ||
| 308 | return -EINVAL; | ||
| 309 | |||
| 307 | if (buf[size-1] != '\n') | 310 | if (buf[size-1] != '\n') |
| 308 | return -EINVAL; | 311 | return -EINVAL; |
| 309 | buf[size-1] = 0; | 312 | buf[size-1] = 0; |
| @@ -503,7 +506,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
| 503 | int len = 0; | 506 | int len = 0; |
| 504 | lock_kernel(); | 507 | lock_kernel(); |
| 505 | if (nfsd_serv) | 508 | if (nfsd_serv) |
| 506 | len = svc_sock_names(buf, nfsd_serv, NULL); | 509 | len = svc_xprt_names(nfsd_serv, buf, 0); |
| 507 | unlock_kernel(); | 510 | unlock_kernel(); |
| 508 | return len; | 511 | return len; |
| 509 | } | 512 | } |
| @@ -540,7 +543,7 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
| 540 | } | 543 | } |
| 541 | return err < 0 ? err : 0; | 544 | return err < 0 ? err : 0; |
| 542 | } | 545 | } |
| 543 | if (buf[0] == '-') { | 546 | if (buf[0] == '-' && isdigit(buf[1])) { |
| 544 | char *toclose = kstrdup(buf+1, GFP_KERNEL); | 547 | char *toclose = kstrdup(buf+1, GFP_KERNEL); |
| 545 | int len = 0; | 548 | int len = 0; |
| 546 | if (!toclose) | 549 | if (!toclose) |
| @@ -554,6 +557,53 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size) | |||
| 554 | kfree(toclose); | 557 | kfree(toclose); |
| 555 | return len; | 558 | return len; |
| 556 | } | 559 | } |
| 560 | /* | ||
| 561 | * Add a transport listener by writing it's transport name | ||
| 562 | */ | ||
| 563 | if (isalpha(buf[0])) { | ||
| 564 | int err; | ||
| 565 | char transport[16]; | ||
| 566 | int port; | ||
| 567 | if (sscanf(buf, "%15s %4d", transport, &port) == 2) { | ||
| 568 | err = nfsd_create_serv(); | ||
| 569 | if (!err) { | ||
| 570 | err = svc_create_xprt(nfsd_serv, | ||
| 571 | transport, port, | ||
| 572 | SVC_SOCK_ANONYMOUS); | ||
| 573 | if (err == -ENOENT) | ||
| 574 | /* Give a reasonable perror msg for | ||
| 575 | * bad transport string */ | ||
| 576 | err = -EPROTONOSUPPORT; | ||
| 577 | } | ||
| 578 | return err < 0 ? err : 0; | ||
| 579 | } | ||
| 580 | } | ||
| 581 | /* | ||
| 582 | * Remove a transport by writing it's transport name and port number | ||
| 583 | */ | ||
| 584 | if (buf[0] == '-' && isalpha(buf[1])) { | ||
| 585 | struct svc_xprt *xprt; | ||
| 586 | int err = -EINVAL; | ||
| 587 | char transport[16]; | ||
| 588 | int port; | ||
| 589 | if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) { | ||
| 590 | if (port == 0) | ||
| 591 | return -EINVAL; | ||
| 592 | lock_kernel(); | ||
| 593 | if (nfsd_serv) { | ||
| 594 | xprt = svc_find_xprt(nfsd_serv, transport, | ||
| 595 | AF_UNSPEC, port); | ||
| 596 | if (xprt) { | ||
| 597 | svc_close_xprt(xprt); | ||
| 598 | svc_xprt_put(xprt); | ||
| 599 | err = 0; | ||
| 600 | } else | ||
| 601 | err = -ENOTCONN; | ||
| 602 | } | ||
| 603 | unlock_kernel(); | ||
| 604 | return err < 0 ? err : 0; | ||
| 605 | } | ||
| 606 | } | ||
| 557 | return -EINVAL; | 607 | return -EINVAL; |
| 558 | } | 608 | } |
| 559 | 609 | ||
| @@ -616,7 +666,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) | |||
| 616 | char *recdir; | 666 | char *recdir; |
| 617 | int len, status; | 667 | int len, status; |
| 618 | 668 | ||
| 619 | if (size > PATH_MAX || buf[size-1] != '\n') | 669 | if (size == 0 || size > PATH_MAX || buf[size-1] != '\n') |
| 620 | return -EINVAL; | 670 | return -EINVAL; |
| 621 | buf[size-1] = 0; | 671 | buf[size-1] = 0; |
| 622 | 672 | ||
| @@ -674,6 +724,27 @@ static struct file_system_type nfsd_fs_type = { | |||
| 674 | .kill_sb = kill_litter_super, | 724 | .kill_sb = kill_litter_super, |
| 675 | }; | 725 | }; |
| 676 | 726 | ||
| 727 | #ifdef CONFIG_PROC_FS | ||
| 728 | static int create_proc_exports_entry(void) | ||
| 729 | { | ||
| 730 | struct proc_dir_entry *entry; | ||
| 731 | |||
| 732 | entry = proc_mkdir("fs/nfs", NULL); | ||
| 733 | if (!entry) | ||
| 734 | return -ENOMEM; | ||
| 735 | entry = create_proc_entry("fs/nfs/exports", 0, NULL); | ||
| 736 | if (!entry) | ||
| 737 | return -ENOMEM; | ||
| 738 | entry->proc_fops = &exports_operations; | ||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | #else /* CONFIG_PROC_FS */ | ||
| 742 | static int create_proc_exports_entry(void) | ||
| 743 | { | ||
| 744 | return 0; | ||
| 745 | } | ||
| 746 | #endif | ||
| 747 | |||
| 677 | static int __init init_nfsd(void) | 748 | static int __init init_nfsd(void) |
| 678 | { | 749 | { |
| 679 | int retval; | 750 | int retval; |
| @@ -683,32 +754,43 @@ static int __init init_nfsd(void) | |||
| 683 | if (retval) | 754 | if (retval) |
| 684 | return retval; | 755 | return retval; |
| 685 | nfsd_stat_init(); /* Statistics */ | 756 | nfsd_stat_init(); /* Statistics */ |
| 686 | nfsd_cache_init(); /* RPC reply cache */ | 757 | retval = nfsd_reply_cache_init(); |
| 687 | nfsd_export_init(); /* Exports table */ | 758 | if (retval) |
| 759 | goto out_free_stat; | ||
| 760 | retval = nfsd_export_init(); | ||
| 761 | if (retval) | ||
| 762 | goto out_free_cache; | ||
| 688 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ | 763 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ |
| 689 | nfsd_idmap_init(); /* Name to ID mapping */ | 764 | retval = nfsd_idmap_init(); |
| 690 | if (proc_mkdir("fs/nfs", NULL)) { | 765 | if (retval) |
| 691 | struct proc_dir_entry *entry; | 766 | goto out_free_lockd; |
| 692 | entry = create_proc_entry("fs/nfs/exports", 0, NULL); | 767 | retval = create_proc_exports_entry(); |
| 693 | if (entry) | 768 | if (retval) |
| 694 | entry->proc_fops = &exports_operations; | 769 | goto out_free_idmap; |
| 695 | } | ||
| 696 | retval = register_filesystem(&nfsd_fs_type); | 770 | retval = register_filesystem(&nfsd_fs_type); |
| 697 | if (retval) { | 771 | if (retval) |
| 698 | nfsd_export_shutdown(); | 772 | goto out_free_all; |
| 699 | nfsd_cache_shutdown(); | 773 | return 0; |
| 700 | remove_proc_entry("fs/nfs/exports", NULL); | 774 | out_free_all: |
| 701 | remove_proc_entry("fs/nfs", NULL); | 775 | remove_proc_entry("fs/nfs/exports", NULL); |
| 702 | nfsd_stat_shutdown(); | 776 | remove_proc_entry("fs/nfs", NULL); |
| 703 | nfsd_lockd_shutdown(); | 777 | out_free_idmap: |
| 704 | } | 778 | nfsd_idmap_shutdown(); |
| 779 | out_free_lockd: | ||
| 780 | nfsd_lockd_shutdown(); | ||
| 781 | nfsd_export_shutdown(); | ||
| 782 | out_free_cache: | ||
| 783 | nfsd_reply_cache_shutdown(); | ||
| 784 | out_free_stat: | ||
| 785 | nfsd_stat_shutdown(); | ||
| 786 | nfsd4_free_slabs(); | ||
| 705 | return retval; | 787 | return retval; |
| 706 | } | 788 | } |
| 707 | 789 | ||
| 708 | static void __exit exit_nfsd(void) | 790 | static void __exit exit_nfsd(void) |
| 709 | { | 791 | { |
| 710 | nfsd_export_shutdown(); | 792 | nfsd_export_shutdown(); |
| 711 | nfsd_cache_shutdown(); | 793 | nfsd_reply_cache_shutdown(); |
| 712 | remove_proc_entry("fs/nfs/exports", NULL); | 794 | remove_proc_entry("fs/nfs/exports", NULL); |
| 713 | remove_proc_entry("fs/nfs", NULL); | 795 | remove_proc_entry("fs/nfs", NULL); |
| 714 | nfsd_stat_shutdown(); | 796 | nfsd_stat_shutdown(); |
