The patch titled knfsd: allow sockets to be passed to nfsd via 'portlist' has been added to the -mm tree. Its filename is knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: knfsd: allow sockets to be passed to nfsd via 'portlist' From: NeilBrown <neilb@xxxxxxx> 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@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- fs/nfsd/nfsctl.c | 59 ++++++++++++++++++++++++++----- fs/nfsd/nfssvc.c | 4 -- include/linux/nfsd/nfsd.h | 1 include/linux/sunrpc/svcsock.h | 6 ++- net/sunrpc/svcsock.c | 49 +++++++++++++++++++++++-- 5 files changed, 102 insertions(+), 17 deletions(-) diff -puN fs/nfsd/nfsctl.c~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist fs/nfsd/nfsctl.c --- a/fs/nfsd/nfsctl.c~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist +++ a/fs/nfsd/nfsctl.c @@ -23,9 +23,11 @@ #include <linux/pagemap.h> #include <linux/init.h> #include <linux/string.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> @@ -425,16 +427,55 @@ static ssize_t write_versions(struct fil 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 diff -puN fs/nfsd/nfssvc.c~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist fs/nfsd/nfssvc.c --- a/fs/nfsd/nfssvc.c~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist +++ a/fs/nfsd/nfssvc.c @@ -195,7 +195,7 @@ void nfsd_reset_versions(void) } } -static int nfsd_create_serv(void) +int nfsd_create_serv(void) { int err = 0; lock_kernel(); @@ -210,8 +210,6 @@ static int nfsd_create_serv(void) nfsd_last_thread); if (nfsd_serv == NULL) err = -ENOMEM; - else - nfsd_serv->sv_nrthreads++; unlock_kernel(); do_gettimeofday(&nfssvc_boot); /* record boot time */ return err; diff -puN include/linux/nfsd/nfsd.h~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist include/linux/nfsd/nfsd.h --- a/include/linux/nfsd/nfsd.h~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist +++ a/include/linux/nfsd/nfsd.h @@ -143,6 +143,7 @@ int nfsd_set_posix_acl(struct svc_fh *, enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; int nfsd_vers(int vers, enum vers_op change); void nfsd_reset_versions(void); +int nfsd_create_serv(void); /* diff -puN include/linux/sunrpc/svcsock.h~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist include/linux/sunrpc/svcsock.h --- a/include/linux/sunrpc/svcsock.h~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist +++ a/include/linux/sunrpc/svcsock.h @@ -61,6 +61,10 @@ int svc_recv(struct svc_serv *, struct int svc_send(struct svc_rqst *); void svc_drop(struct svc_rqst *); void svc_sock_update_bufs(struct svc_serv *serv); -int svc_sock_names(char *buf, struct svc_serv *serv); +int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose); +int svc_addsock(struct svc_serv *serv, + int fd, + char *name_return, + int *proto); #endif /* SUNRPC_SVCSOCK_H */ diff -puN net/sunrpc/svcsock.c~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist net/sunrpc/svcsock.c --- a/net/sunrpc/svcsock.c~knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist +++ a/net/sunrpc/svcsock.c @@ -31,6 +31,7 @@ #include <linux/slab.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <linux/file.h> #include <net/sock.h> #include <net/checksum.h> #include <net/ip.h> @@ -451,9 +452,9 @@ static int one_sock_name(char *buf, stru } int -svc_sock_names(char *buf, struct svc_serv *serv) +svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) { - struct svc_sock *svsk; + struct svc_sock *svsk, *closesk = NULL; int len = 0; if (!serv) @@ -461,9 +462,14 @@ svc_sock_names(char *buf, struct svc_ser spin_lock(&serv->sv_lock); list_for_each_entry(svsk, &serv->sv_permsocks, sk_list) { int onelen = one_sock_name(buf+len, svsk); - len += onelen; + if (toclose && strcmp(toclose, buf+len) == 0) + closesk = svsk; + else + len += onelen; } spin_unlock(&serv->sv_lock); + if (closesk) + svc_delete_socket(closesk); return len; } EXPORT_SYMBOL(svc_sock_names); @@ -1417,6 +1423,38 @@ svc_setup_socket(struct svc_serv *serv, return svsk; } +int svc_addsock(struct svc_serv *serv, + int fd, + char *name_return, + int *proto) +{ + int err = 0; + struct socket *so = sockfd_lookup(fd, &err); + struct svc_sock *svsk = NULL; + + if (!so) + return err; + if (so->sk->sk_family != AF_INET) + err = -EAFNOSUPPORT; + else if (so->sk->sk_protocol != IPPROTO_TCP && + so->sk->sk_protocol != IPPROTO_UDP) + err = -EPROTONOSUPPORT; + else if (so->state > SS_UNCONNECTED) + err = -EISCONN; + else { + svsk = svc_setup_socket(serv, so, &err, 1); + if (svsk) + err = 0; + } + if (err) { + sockfd_put(so); + return err; + } + if (proto) *proto = so->sk->sk_protocol; + return one_sock_name(name_return, svsk); +} +EXPORT_SYMBOL_GPL(svc_addsock); + /* * Create socket for RPC service. */ @@ -1494,7 +1532,10 @@ svc_delete_socket(struct svc_sock *svsk) if (!svsk->sk_inuse) { spin_unlock_bh(&serv->sv_lock); - sock_release(svsk->sk_sock); + if (svsk->sk_sock->file) + sockfd_put(svsk->sk_sock); + else + sock_release(svsk->sk_sock); kfree(svsk); } else { spin_unlock_bh(&serv->sv_lock); _ Patches currently in -mm which might be from neilb@xxxxxxx are ext3-avoid-triggering-ext3_error-on-bad-nfs-file-handle.patch ext3-avoid-triggering-ext3_error-on-bad-nfs-file-handle-fix.patch git-klibc.patch ext3-reject-filehandles-referring-to-special-files.patch ext2-reject-file-handles-with-bad-inode-numbers-early.patch knfsd-knfsd-add-some-missing-newlines-in-printks.patch knfsd-knfsd-remove-an-unused-variable-from-e_show.patch knfsd-knfsd-remove-an-unused-variable-from-auth_unix_lookup.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes-tidy.patch knfsd-be-more-selective-in-which-sockets-lockd-listens-on.patch knfsd-remove-nfsd_versbits-as-intermediate-storage-for-desired-versions.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers-tweaks.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports-tidy.patch knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist.patch md-dm-reduce-stack-usage-with-stacked-block-devices.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html