diff options
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r-- | fs/nfsd/nfsctl.c | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index d4041a05bc19..80e97a5ffc3f 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -24,9 +24,11 @@ | |||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/smp_lock.h> | 26 | #include <linux/smp_lock.h> |
27 | #include <linux/ctype.h> | ||
27 | 28 | ||
28 | #include <linux/nfs.h> | 29 | #include <linux/nfs.h> |
29 | #include <linux/nfsd_idmap.h> | 30 | #include <linux/nfsd_idmap.h> |
31 | #include <linux/lockd/bind.h> | ||
30 | #include <linux/sunrpc/svc.h> | 32 | #include <linux/sunrpc/svc.h> |
31 | #include <linux/sunrpc/svcsock.h> | 33 | #include <linux/sunrpc/svcsock.h> |
32 | #include <linux/nfsd/nfsd.h> | 34 | #include <linux/nfsd/nfsd.h> |
@@ -426,16 +428,55 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) | |||
426 | 428 | ||
427 | static ssize_t write_ports(struct file *file, char *buf, size_t size) | 429 | static ssize_t write_ports(struct file *file, char *buf, size_t size) |
428 | { | 430 | { |
429 | /* for now, ignore what was written and just | 431 | if (size == 0) { |
430 | * return known ports | 432 | int len = 0; |
431 | * AF proto address port | 433 | lock_kernel(); |
434 | if (nfsd_serv) | ||
435 | len = svc_sock_names(buf, nfsd_serv, NULL); | ||
436 | unlock_kernel(); | ||
437 | return len; | ||
438 | } | ||
439 | /* Either a single 'fd' number is written, in which | ||
440 | * case it must be for a socket of a supported family/protocol, | ||
441 | * and we use it as an nfsd socket, or | ||
442 | * A '-' followed by the 'name' of a socket in which case | ||
443 | * we close the socket. | ||
432 | */ | 444 | */ |
433 | int len = 0; | 445 | if (isdigit(buf[0])) { |
434 | lock_kernel(); | 446 | char *mesg = buf; |
435 | if (nfsd_serv) | 447 | int fd; |
436 | len = svc_sock_names(buf, nfsd_serv); | 448 | int err; |
437 | unlock_kernel(); | 449 | err = get_int(&mesg, &fd); |
438 | return len; | 450 | if (err) |
451 | return -EINVAL; | ||
452 | if (fd < 0) | ||
453 | return -EINVAL; | ||
454 | err = nfsd_create_serv(); | ||
455 | if (!err) { | ||
456 | int proto = 0; | ||
457 | err = svc_addsock(nfsd_serv, fd, buf, &proto); | ||
458 | /* Decrease the count, but don't shutdown the | ||
459 | * the service | ||
460 | */ | ||
461 | if (err >= 0) | ||
462 | lockd_up(proto); | ||
463 | nfsd_serv->sv_nrthreads--; | ||
464 | } | ||
465 | return err; | ||
466 | } | ||
467 | if (buf[0] == '-') { | ||
468 | char *toclose = kstrdup(buf+1, GFP_KERNEL); | ||
469 | int len = 0; | ||
470 | if (!toclose) | ||
471 | return -ENOMEM; | ||
472 | lock_kernel(); | ||
473 | if (nfsd_serv) | ||
474 | len = svc_sock_names(buf, nfsd_serv, toclose); | ||
475 | unlock_kernel(); | ||
476 | kfree(toclose); | ||
477 | return len; | ||
478 | } | ||
479 | return -EINVAL; | ||
439 | } | 480 | } |
440 | 481 | ||
441 | #ifdef CONFIG_NFSD_V4 | 482 | #ifdef CONFIG_NFSD_V4 |