diff options
author | NeilBrown <neilb@suse.de> | 2006-10-02 09:17:48 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 14:57:18 (GMT) |
commit | b41b66d63c730cc45a1024e1f1e67439e507e40f (patch) | |
tree | 85f623c087a90ccf08a8264c638df5504f972c0d /fs/nfsd/nfsctl.c | |
parent | 80212d59e32a8a8e030c2ddc5861d8ff70542c56 (diff) | |
download | linux-b41b66d63c730cc45a1024e1f1e67439e507e40f.tar.xz |
[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 d4041a0..80e97a5 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -24,9 +24,11 @@ #include <linux/init.h> #include <linux/string.h> #include <linux/smp_lock.h> +#include <linux/ctype.h> #include <linux/nfs.h> #include <linux/nfsd_idmap.h> +#include <linux/lockd/bind.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/svcsock.h> #include <linux/nfsd/nfsd.h> @@ -426,16 +428,55 @@ static ssize_t write_versions(struct file *file, char *buf, size_t size) static ssize_t write_ports(struct file *file, char *buf, size_t size) { - /* for now, ignore what was written and just - * return known ports - * AF proto address port + if (size == 0) { + int len = 0; + lock_kernel(); + if (nfsd_serv) + len = svc_sock_names(buf, nfsd_serv, NULL); + unlock_kernel(); + return len; + } + /* Either a single 'fd' number is written, in which + * case it must be for a socket of a supported family/protocol, + * and we use it as an nfsd socket, or + * A '-' followed by the 'name' of a socket in which case + * we close the socket. */ - int len = 0; - lock_kernel(); - if (nfsd_serv) - len = svc_sock_names(buf, nfsd_serv); - unlock_kernel(); - return len; + if (isdigit(buf[0])) { + char *mesg = buf; + int fd; + int err; + err = get_int(&mesg, &fd); + if (err) + return -EINVAL; + if (fd < 0) + return -EINVAL; + err = nfsd_create_serv(); + if (!err) { + int proto = 0; + err = svc_addsock(nfsd_serv, fd, buf, &proto); + /* Decrease the count, but don't shutdown the + * the service + */ + if (err >= 0) + lockd_up(proto); + nfsd_serv->sv_nrthreads--; + } + return err; + } + if (buf[0] == '-') { + char *toclose = kstrdup(buf+1, GFP_KERNEL); + int len = 0; + if (!toclose) + return -ENOMEM; + lock_kernel(); + if (nfsd_serv) + len = svc_sock_names(buf, nfsd_serv, toclose); + unlock_kernel(); + kfree(toclose); + return len; + } + return -EINVAL; } #ifdef CONFIG_NFSD_V4 |