aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r--fs/nfsd/nfsctl.c124
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
728static 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 */
742static int create_proc_exports_entry(void)
743{
744 return 0;
745}
746#endif
747
677static int __init init_nfsd(void) 748static 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); 774out_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(); 777out_free_idmap:
704 } 778 nfsd_idmap_shutdown();
779out_free_lockd:
780 nfsd_lockd_shutdown();
781 nfsd_export_shutdown();
782out_free_cache:
783 nfsd_reply_cache_shutdown();
784out_free_stat:
785 nfsd_stat_shutdown();
786 nfsd4_free_slabs();
705 return retval; 787 return retval;
706} 788}
707 789
708static void __exit exit_nfsd(void) 790static 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();