diff options
author | NeilBrown <neilb@suse.de> | 2006-10-02 05:17:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:18 -0400 |
commit | b41b66d63c730cc45a1024e1f1e67439e507e40f (patch) | |
tree | 85f623c087a90ccf08a8264c638df5504f972c0d /fs/nfsd/nfsctl.c | |
parent | 80212d59e32a8a8e030c2ddc5861d8ff70542c56 (diff) |
[PATCH] knfsd: allow sockets to be passed to nfsd via 'portlist'
Userspace should create and bind a socket (but not connectted) and write the
'fd' to portlist. This will cause the nfs server to listen on that socket.
To close a socket, the name of the socket - as read from 'portlist' can be
written to 'portlist' with a preceding '-'.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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 |