nfsd_last_thread expects that any socket on sv_permsocks will hold a lockd reference. Make sure that __write_ports_addxprt takes a lockd reference for each socket it creates and have __write_ports_delxprt release references when it closes a socket. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/nfsd/nfsctl.c | 59 ++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 42 insertions(+), 17 deletions(-) diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 9e8645a..365aee0 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -989,6 +989,21 @@ static ssize_t __write_ports_delfd(char *buf) return len; } +static int +nfsd_shutdown_xprt(const char *transport, const unsigned short family, + const int port) +{ + struct svc_xprt *xprt; + + xprt = svc_find_xprt(nfsd_serv, transport, family, port); + if (xprt == NULL) + return -ENOTCONN; + + svc_close_xprt(xprt); + svc_xprt_put(xprt); + return 0; +} + /* * A transport listener is added by writing it's transport name and * a port number. @@ -996,7 +1011,6 @@ static ssize_t __write_ports_delfd(char *buf) static ssize_t __write_ports_addxprt(char *buf) { char transport[16]; - struct svc_xprt *xprt; int port, err; if (sscanf(buf, "%15s %4u", transport, &port) != 2) @@ -1014,20 +1028,29 @@ static ssize_t __write_ports_addxprt(char *buf) if (err < 0) goto out_err; + err = lockd_up(); + if (err != 0) { + nfsd_shutdown_xprt(transport, PF_INET, port); + goto out_err; + } + err = svc_create_xprt(nfsd_serv, transport, PF_INET6, port, SVC_SOCK_ANONYMOUS); - if (err < 0 && err != -EAFNOSUPPORT) - goto out_close; + if (err < 0 && err != -EAFNOSUPPORT) { + nfsd_shutdown_xprt(transport, PF_INET, port); + goto out_err; + } + + err = lockd_up(); + if (err != 0) { + nfsd_shutdown_xprt(transport, PF_INET6, port); + nfsd_shutdown_xprt(transport, PF_INET, port); + goto out_err; + } /* Decrease the count, but don't shut down the service */ nfsd_serv->sv_nrthreads--; return 0; -out_close: - xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port); - if (xprt != NULL) { - svc_close_xprt(xprt); - svc_xprt_put(xprt); - } out_err: svc_destroy(nfsd_serv); return err; @@ -1039,9 +1062,8 @@ out_err: */ static ssize_t __write_ports_delxprt(char *buf) { - struct svc_xprt *xprt; char transport[16]; - int port; + int port, err; if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2) return -EINVAL; @@ -1049,13 +1071,16 @@ static ssize_t __write_ports_delxprt(char *buf) if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL) return -EINVAL; - xprt = svc_find_xprt(nfsd_serv, transport, AF_UNSPEC, port); - if (xprt == NULL) - return -ENOTCONN; + /* PF_INET6 sockets are considered optional */ + err = nfsd_shutdown_xprt(transport, PF_INET6, port); + if (err == 0) + lockd_down(); - svc_close_xprt(xprt); - svc_xprt_put(xprt); - return 0; + err = nfsd_shutdown_xprt(transport, PF_INET, port); + if (err == 0) + lockd_down(); + + return err; } static ssize_t __write_ports(struct file *file, char *buf, size_t size) -- 1.5.5.6 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html