[PATCH v3 00/11] Series short description
v3: Rebased on Bruce's tree, "for-3.6" branch v2: Rebased on Bruce's tree, "for-3.5" branch This patch set depeneds on "SUNRPC: separate per-net data creation from service creation" patch set sent earlier. The following series implements... --- Stanislav Kinsbursky (11): NFS: pass net to nfs_callback_down() NFS: callback service creation function introduced NFS: move per-net callback thread initialization to nfs_callback_up_net() NFS: callback up - transport backchannel cleanup NFS: callback service start function introduced NFS: callback up - users counting cleanup NFS: make nfs_callback_tcpport per network context NFS: make nfs_callback_tcpport6 per network context NFS; callback per-net usage counting introduced NFS: add debug messages to callback down function NFS: get net after idr allocation fs/nfs/callback.c | 288 ++++++++++++++++++++++++++++++++++------------------ fs/nfs/callback.h | 4 - fs/nfs/client.c | 5 + fs/nfs/netns.h | 3 + fs/nfs/nfs4state.c | 6 + 5 files changed, 202 insertions(+), 104 deletions(-)
[PATCH v3 01/11] NFS: pass net to nfs_callback_down()
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 4 ++-- fs/nfs/callback.h | 2 +- fs/nfs/client.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 23ff18f..2d3019d 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -321,7 +321,7 @@ out_err: /* * Kill the callback thread if it's no longer being used. */ -void nfs_callback_down(int minorversion) +void nfs_callback_down(int minorversion, struct net *net) { struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; @@ -329,7 +329,7 @@ void nfs_callback_down(int minorversion) cb_info->users--; if (cb_info->users == 0 && cb_info->task != NULL) { kthread_stop(cb_info->task); - svc_shutdown_net(cb_info->serv, &init_net); + svc_shutdown_net(cb_info->serv, net); svc_exit_thread(cb_info->rqst); cb_info->serv = NULL; cb_info->rqst = NULL; diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index a5527c9..6d900cf 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -194,7 +194,7 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy, struct cb_process_state *cps); #ifdef CONFIG_NFS_V4 extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt); -extern void nfs_callback_down(int minorversion); +extern void nfs_callback_down(int minorversion, struct net *net); extern int nfs4_validate_delegation_stateid(struct nfs_delegation *delegation, const nfs4_stateid *stateid); extern int nfs4_set_callback_sessionid(struct nfs_client *clp); diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 17ba6b9..28bc770 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -225,7 +225,7 @@ static void nfs4_shutdown_session(struct nfs_client *clp) static void nfs4_destroy_callback(struct nfs_client *clp) { if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) - nfs_callback_down(clp->cl_mvops->minor_version); + nfs_callback_down(clp->cl_mvops->minor_version, &init_net); } static void nfs4_shutdown_client(struct nfs_client *clp)
[PATCH v3 02/11] NFS: callback service creation function introduced
This function creates service if it's not exist, or increase usage counter of the existent, and returns pointer to it. Usage counter will be droppepd by svc_destroy() later in nfs_callback_up(). Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 55 +++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 45 insertions(+), 10 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 2d3019d..f8d0c21 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -241,12 +241,46 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, } #endif /* CONFIG_NFS_V4_1 */ +static struct svc_serv *nfs_callback_create_svc(int minorversion) +{ + struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; + struct svc_serv *serv; + + /* + * Check whether we're already up and running. + */ + if (cb_info->task) { + /* + * Note: increase service usage, because later in case of error + * svc_destroy() will be called. + */ + svc_get(cb_info->serv); + return cb_info->serv; + } + + /* + * Sanity check: if there's no task, + * we should be the first user ... + */ + if (cb_info->users) + printk(KERN_WARNING "nfs_callback_up: no kthread, %d users??\n", + cb_info->users); + + serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); + if (!serv) { + printk(KERN_ERR "lockd_up: create service failed\n"); + return ERR_PTR(-ENOMEM); + } + dprintk("nfs_callback_up: service created\n"); + return serv; +} + /* * Bring up the callback thread if it is not already up. */ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) { - struct svc_serv *serv = NULL; + struct svc_serv *serv; struct svc_rqst *rqstp; int (*callback_svc)(void *vrqstp); struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; @@ -256,15 +290,17 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) struct net *net = &init_net; mutex_lock(&nfs_callback_mutex); + + serv = nfs_callback_create_svc(minorversion); + if (IS_ERR(serv)) { + ret = PTR_ERR(serv); + goto err_create; + } + if (cb_info->users++ || cb_info->task != NULL) { nfs_callback_bc_serv(minorversion, xprt, cb_info); goto out; } - serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); - if (!serv) { - ret = -ENOMEM; - goto out_err; - } ret = svc_bind(serv, net); if (ret < 0) { @@ -305,16 +341,15 @@ out: * on both success and failure so that the refcount is 1 when the * thread exits. */ - if (serv) - svc_destroy(serv); + svc_destroy(serv); +err_create: mutex_unlock(&nfs_callback_mutex); return ret; out_err: dprintk("NFS: Couldn't create callback socket or server thread; " "err = %d\n", ret); cb_info->users--; - if (serv) - svc_shutdown_net(serv, net); + svc_shutdown_net(serv, net); goto out; }
[PATCH v3 03/11] NFS: move per-net callback thread initialization to nfs_callback_up_net()
This new function in now called before nfs_minorversion_callback_svc_setup()). Also few small changes: 1) current network namespace in nfs_callback_up() was replaced by transport net. 2) svc_shutdown_net() was moved prior to callback usage counter decrement (because in case of per-net data allocation faulure svc_shutdown_net() have to be skipped). Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 125 +++++++++++++++++++++++++++++++++-------------------- fs/nfs/client.c | 2 - 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index f8d0c21..b61ed61 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -63,6 +63,32 @@ static struct kernel_param_ops param_ops_portnr = { module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); +static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) +{ + int ret; + + ret = svc_create_xprt(serv, "tcp", net, PF_INET, + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + if (ret <= 0) + goto out_err; + nfs_callback_tcpport = ret; + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", + nfs_callback_tcpport, PF_INET, net); + + ret = svc_create_xprt(serv, "tcp", net, PF_INET6, + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); + if (ret > 0) { + nfs_callback_tcpport6 = ret; + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", + nfs_callback_tcpport6, PF_INET6, net); + } else if (ret != -EAFNOSUPPORT) + goto out_err; + return 0; + +out_err: + return (ret) ? ret : -ENOMEM; +} + /* * This is the NFSv4 callback kernel thread. */ @@ -104,36 +130,21 @@ nfs4_callback_svc(void *vrqstp) static struct svc_rqst * nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) { - int ret; - - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); - if (ret <= 0) - goto out_err; - nfs_callback_tcpport = ret; - dprintk("NFS: Callback listener port = %u (af %u)\n", - nfs_callback_tcpport, PF_INET); - - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); - if (ret > 0) { - nfs_callback_tcpport6 = ret; - dprintk("NFS: Callback listener port = %u (af %u)\n", - nfs_callback_tcpport6, PF_INET6); - } else if (ret == -EAFNOSUPPORT) - ret = 0; - else - goto out_err; - return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); - -out_err: - if (ret == 0) - ret = -ENOMEM; - return ERR_PTR(ret); } #if defined(CONFIG_NFS_V4_1) +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) +{ + /* + * Create an svc_sock for the back channel service that shares the + * fore channel connection. + * Returns the input port (0) and sets the svc_serv bc_xprt on success + */ + return svc_create_xprt(serv, "tcp-bc", net, PF_INET, 0, + SVC_SOCK_ANONYMOUS); +} + /* * The callback service for NFSv4.1 callbacks */ @@ -176,19 +187,6 @@ static struct svc_rqst * nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) { struct svc_rqst *rqstp; - int ret; - - /* - * Create an svc_sock for the back channel service that shares the - * fore channel connection. - * Returns the input port (0) and sets the svc_serv bc_xprt on success - */ - ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, - SVC_SOCK_ANONYMOUS); - if (ret < 0) { - rqstp = ERR_PTR(ret); - goto out; - } /* * Save the svc_serv in the transport so that it can @@ -204,7 +202,6 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) svc_xprt_put(serv->sv_bc_xprt); serv->sv_bc_xprt = NULL; } -out: dprintk("--> %s return %ld\n", __func__, IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); return rqstp; @@ -228,6 +225,11 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, xprt->bc_serv = cb_info->serv; } #else +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) +{ + return 0; +} + static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, struct svc_serv *serv, struct rpc_xprt *xprt, struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) @@ -241,6 +243,36 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, } #endif /* CONFIG_NFS_V4_1 */ +static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) +{ + int ret; + + dprintk("NFS: create per-net callback data; net=%p\n", net); + + ret = svc_bind(serv, net); + if (ret < 0) { + printk(KERN_WARNING "NFS: bind callback service failed\n"); + goto err_bind; + } + + if (minorversion) { + ret = nfs41_callback_up_net(serv, net); + if (ret < 0) + goto err_socks; + } + + if (ret == 0) + ret = nfs4_callback_up_net(serv, net); + if (ret < 0) + goto err_socks; + return 0; + +err_socks: + svc_rpcb_cleanup(serv, net); +err_bind: + return ret; +} + static struct svc_serv *nfs_callback_create_svc(int minorversion) { struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; @@ -287,7 +319,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) char svc_name[12]; int ret = 0; int minorversion_setup; - struct net *net = &init_net; + struct net *net = xprt->xprt_net; mutex_lock(&nfs_callback_mutex); @@ -302,11 +334,9 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) goto out; } - ret = svc_bind(serv, net); - if (ret < 0) { - printk(KERN_WARNING "NFS: bind callback service failed\n"); - goto out_err; - } + ret = nfs_callback_up_net(minorversion, serv, net); + if (ret < 0) + goto err_net; minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, serv, xprt, &rqstp, &callback_svc); @@ -346,10 +376,11 @@ err_create: mutex_unlock(&nfs_callback_mutex); return ret; out_err: + svc_shutdown_net(serv, net); +err_net: dprintk("NFS: Couldn't create callback socket or server thread; " "err = %d\n", ret); cb_info->users--; - svc_shutdown_net(serv, net); goto out; } diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 28bc770..d8c918b 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -225,7 +225,7 @@ static void nfs4_shutdown_session(struct nfs_client *clp) static void nfs4_destroy_callback(struct nfs_client *clp) { if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) - nfs_callback_down(clp->cl_mvops->minor_version, &init_net); + nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net); } static void nfs4_shutdown_client(struct nfs_client *clp)
[PATCH v3 04/11] NFS: callback up - transport backchannel cleanup
No need to assign transports backchannel server explicitly in nfs41_callback_up() - there is nfs_callback_bc_serv() function for this. By using it, nfs4_callback_up() and nfs41_callback_up() can be called without transport argument. Note: service have to be passed to nfs_callback_bc_serv() instead of callback, since callback link can be uninitialized. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 34 +++++++++++++++++----------------- 1 files changed, 17 insertions(+), 17 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index b61ed61..41150ef 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -128,7 +128,7 @@ nfs4_callback_svc(void *vrqstp) * Prepare to bring up the NFSv4 callback service */ static struct svc_rqst * -nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) +nfs4_callback_up(struct svc_serv *serv) { return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); } @@ -184,16 +184,10 @@ nfs41_callback_svc(void *vrqstp) * Bring up the NFSv4.1 callback service */ static struct svc_rqst * -nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) +nfs41_callback_up(struct svc_serv *serv) { struct svc_rqst *rqstp; - /* - * Save the svc_serv in the transport so that it can - * be referenced when the session backchannel is initialized - */ - xprt->bc_serv = serv; - INIT_LIST_HEAD(&serv->sv_cb_list); spin_lock_init(&serv->sv_cb_lock); init_waitqueue_head(&serv->sv_cb_waitq); @@ -208,21 +202,25 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) } static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, - struct svc_serv *serv, struct rpc_xprt *xprt, + struct svc_serv *serv, struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) { if (minorversion) { - *rqstpp = nfs41_callback_up(serv, xprt); + *rqstpp = nfs41_callback_up(serv); *callback_svc = nfs41_callback_svc; } return minorversion; } static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, - struct nfs_callback_data *cb_info) + struct svc_serv *serv) { if (minorversion) - xprt->bc_serv = cb_info->serv; + /* + * Save the svc_serv in the transport so that it can + * be referenced when the session backchannel is initialized + */ + xprt->bc_serv = serv; } #else static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) @@ -231,14 +229,14 @@ static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) } static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, - struct svc_serv *serv, struct rpc_xprt *xprt, + struct svc_serv *serv, struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) { return 0; } static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, - struct nfs_callback_data *cb_info) + struct svc_serv *serv) { } #endif /* CONFIG_NFS_V4_1 */ @@ -330,7 +328,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) } if (cb_info->users++ || cb_info->task != NULL) { - nfs_callback_bc_serv(minorversion, xprt, cb_info); + nfs_callback_bc_serv(minorversion, xprt, serv); goto out; } @@ -338,11 +336,13 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) if (ret < 0) goto err_net; + nfs_callback_bc_serv(minorversion, xprt, serv); + minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, - serv, xprt, &rqstp, &callback_svc); + serv, &rqstp, &callback_svc); if (!minorversion_setup) { /* v4.0 callback setup */ - rqstp = nfs4_callback_up(serv, xprt); + rqstp = nfs4_callback_up(serv); callback_svc = nfs4_callback_svc; }
[PATCH v3 05/11] NFS: callback service start function introduced
This is just a code move, which from my POW makes code looks better. I.e. now on start we have 3 different stages: 1) Service creation. 2) Service per-net data allocation. 3) Service start. Patch also renames goto label "out_err:" into "err_start:" to reflect new changes. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 77 +++++++++++++++++++++++++++++++---------------------- 1 files changed, 45 insertions(+), 32 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 41150ef..550d2a2 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -241,6 +241,46 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, } #endif /* CONFIG_NFS_V4_1 */ +static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, + struct svc_serv *serv) +{ + struct svc_rqst *rqstp; + int (*callback_svc)(void *vrqstp); + struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; + char svc_name[12]; + int ret; + int minorversion_setup; + + nfs_callback_bc_serv(minorversion, xprt, serv); + + minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, + serv, &rqstp, &callback_svc); + if (!minorversion_setup) { + /* v4.0 callback setup */ + rqstp = nfs4_callback_up(serv); + callback_svc = nfs4_callback_svc; + } + + if (IS_ERR(rqstp)) + return PTR_ERR(rqstp); + + svc_sock_update_bufs(serv); + + sprintf(svc_name, "nfsv4.%u-svc", minorversion); + cb_info->serv = serv; + cb_info->rqst = rqstp; + cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name); + if (IS_ERR(cb_info->task)) { + ret = PTR_ERR(cb_info->task); + svc_exit_thread(cb_info->rqst); + cb_info->rqst = NULL; + cb_info->task = NULL; + return PTR_ERR(cb_info->task); + } + dprintk("nfs_callback_up: service started\n"); + return 0; +} + static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) { int ret; @@ -311,12 +351,8 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion) int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) { struct svc_serv *serv; - struct svc_rqst *rqstp; - int (*callback_svc)(void *vrqstp); struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; - char svc_name[12]; int ret = 0; - int minorversion_setup; struct net *net = xprt->xprt_net; mutex_lock(&nfs_callback_mutex); @@ -336,34 +372,10 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) if (ret < 0) goto err_net; - nfs_callback_bc_serv(minorversion, xprt, serv); - - minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, - serv, &rqstp, &callback_svc); - if (!minorversion_setup) { - /* v4.0 callback setup */ - rqstp = nfs4_callback_up(serv); - callback_svc = nfs4_callback_svc; - } - - if (IS_ERR(rqstp)) { - ret = PTR_ERR(rqstp); - goto out_err; - } - - svc_sock_update_bufs(serv); + ret = nfs_callback_start_svc(minorversion, xprt, serv); + if (ret < 0) + goto err_start; - sprintf(svc_name, "nfsv4.%u-svc", minorversion); - cb_info->serv = serv; - cb_info->rqst = rqstp; - cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name); - if (IS_ERR(cb_info->task)) { - ret = PTR_ERR(cb_info->task); - svc_exit_thread(cb_info->rqst); - cb_info->rqst = NULL; - cb_info->task = NULL; - goto out_err; - } out: /* * svc_create creates the svc_serv with sv_nrthreads == 1, and then @@ -375,7 +387,8 @@ out: err_create: mutex_unlock(&nfs_callback_mutex); return ret; -out_err: + +err_start: svc_shutdown_net(serv, net); err_net: dprintk("NFS: Couldn't create callback socket or server thread; "
[PATCH v3 06/11] NFS: callback up - users counting cleanup
Usage coutner now increased only is the service was started sccessfully. Even if service is running already, then goto is not required anymore, because service creation and start will be skipped. With this patch code looks clearer. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 550d2a2..f2a7605 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -253,6 +253,9 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, nfs_callback_bc_serv(minorversion, xprt, serv); + if (cb_info->task) + return 0; + minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, serv, &rqstp, &callback_svc); if (!minorversion_setup) { @@ -308,6 +311,8 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct n err_socks: svc_rpcb_cleanup(serv, net); err_bind: + dprintk("NFS: Couldn't create callback socket: err = %d; " + "net = %p\n", ret, net); return ret; } @@ -352,7 +357,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) { struct svc_serv *serv; struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; - int ret = 0; + int ret; struct net *net = xprt->xprt_net; mutex_lock(&nfs_callback_mutex); @@ -363,11 +368,6 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) goto err_create; } - if (cb_info->users++ || cb_info->task != NULL) { - nfs_callback_bc_serv(minorversion, xprt, serv); - goto out; - } - ret = nfs_callback_up_net(minorversion, serv, net); if (ret < 0) goto err_net; @@ -376,13 +376,14 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) if (ret < 0) goto err_start; -out: + cb_info->users++; /* * svc_create creates the svc_serv with sv_nrthreads == 1, and then * svc_prepare_thread increments that. So we need to call svc_destroy * on both success and failure so that the refcount is 1 when the * thread exits. */ +err_net: svc_destroy(serv); err_create: mutex_unlock(&nfs_callback_mutex); @@ -390,11 +391,8 @@ err_create: err_start: svc_shutdown_net(serv, net); -err_net: - dprintk("NFS: Couldn't create callback socket or server thread; " - "err = %d\n", ret); - cb_info->users--; - goto out; + dprintk("NFS: Couldn't create server thread; err = %d\n", ret); + goto err_net; } /*
[PATCH v3 07/11] NFS: make nfs_callback_tcpport per network context
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 7 ++++--- fs/nfs/callback.h | 1 - fs/nfs/netns.h | 1 + fs/nfs/nfs4state.c | 4 +++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index f2a7605..80032fc 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -23,6 +23,7 @@ #include "nfs4_fs.h" #include "callback.h" #include "internal.h" +#include "netns.h" #define NFSDBG_FACILITY NFSDBG_CALLBACK @@ -38,7 +39,6 @@ static DEFINE_MUTEX(nfs_callback_mutex); static struct svc_program nfs4_callback_program; unsigned int nfs_callback_set_tcpport; -unsigned short nfs_callback_tcpport; unsigned short nfs_callback_tcpport6; #define NFS_CALLBACK_MAXPORTNR (65535U) @@ -66,14 +66,15 @@ module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) { int ret; + struct nfs_net *nn = net_generic(net, nfs_net_id); ret = svc_create_xprt(serv, "tcp", net, PF_INET, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret <= 0) goto out_err; - nfs_callback_tcpport = ret; + nn->nfs_callback_tcpport = ret; dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", - nfs_callback_tcpport, PF_INET, net); + nn->nfs_callback_tcpport, PF_INET, net); ret = svc_create_xprt(serv, "tcp", net, PF_INET6, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 6d900cf..8006959 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -208,7 +208,6 @@ extern int nfs4_set_callback_sessionid(struct nfs_client *clp); #define NFS41_BC_MAX_CALLBACKS 1 extern unsigned int nfs_callback_set_tcpport; -extern unsigned short nfs_callback_tcpport; extern unsigned short nfs_callback_tcpport6; #endif /* __LINUX_FS_NFS_CALLBACK_H */ diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 8a6394e..06a23fc 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h @@ -22,6 +22,7 @@ struct nfs_net { struct list_head nfs_volume_list; #ifdef CONFIG_NFS_V4 struct idr cb_ident_idr; /* Protected by nfs_client_lock */ + unsigned short nfs_callback_tcpport; #endif spinlock_t nfs_client_lock; struct timespec boot_time; diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f38300e..bc0ddf8 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -56,6 +56,7 @@ #include "delegation.h" #include "internal.h" #include "pnfs.h" +#include "netns.h" #define NFSDBG_FACILITY NFSDBG_STATE @@ -73,10 +74,11 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) }; unsigned short port; int status; + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state)) goto do_confirm; - port = nfs_callback_tcpport; + port = nn->nfs_callback_tcpport; if (clp->cl_addr.ss_family == AF_INET6) port = nfs_callback_tcpport6;
[PATCH v3 08/11] NFS: make nfs_callback_tcpport6 per network context
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 5 ++--- fs/nfs/callback.h | 1 - fs/nfs/netns.h | 1 + fs/nfs/nfs4state.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 80032fc..97bccb1 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -39,7 +39,6 @@ static DEFINE_MUTEX(nfs_callback_mutex); static struct svc_program nfs4_callback_program; unsigned int nfs_callback_set_tcpport; -unsigned short nfs_callback_tcpport6; #define NFS_CALLBACK_MAXPORTNR (65535U) static int param_set_portnr(const char *val, const struct kernel_param *kp) @@ -79,9 +78,9 @@ static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) ret = svc_create_xprt(serv, "tcp", net, PF_INET6, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret > 0) { - nfs_callback_tcpport6 = ret; + nn->nfs_callback_tcpport6 = ret; dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", - nfs_callback_tcpport6, PF_INET6, net); + nn->nfs_callback_tcpport6, PF_INET6, net); } else if (ret != -EAFNOSUPPORT) goto out_err; return 0; diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index 8006959..86b5671 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -208,6 +208,5 @@ extern int nfs4_set_callback_sessionid(struct nfs_client *clp); #define NFS41_BC_MAX_CALLBACKS 1 extern unsigned int nfs_callback_set_tcpport; -extern unsigned short nfs_callback_tcpport6; #endif /* __LINUX_FS_NFS_CALLBACK_H */ diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 06a23fc..097dae1 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h @@ -23,6 +23,7 @@ struct nfs_net { #ifdef CONFIG_NFS_V4 struct idr cb_ident_idr; /* Protected by nfs_client_lock */ unsigned short nfs_callback_tcpport; + unsigned short nfs_callback_tcpport6; #endif spinlock_t nfs_client_lock; struct timespec boot_time; diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index bc0ddf8..9313249 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -80,7 +80,7 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred) goto do_confirm; port = nn->nfs_callback_tcpport; if (clp->cl_addr.ss_family == AF_INET6) - port = nfs_callback_tcpport6; + port = nn->nfs_callback_tcpport6; status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid); if (status != 0)
[PATCH v3 09/11] NFS; callback per-net usage counting introduced
This patch also introduces refcount-aware nfs_callback_down_net() wrapper for svc_shutdown_net(). Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 19 +++++++++++++++++-- fs/nfs/netns.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 97bccb1..35ccd2a 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -284,10 +284,25 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, return 0; } +static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net) +{ + struct nfs_net *nn = net_generic(net, nfs_net_id); + + if (--nn->cb_users[minorversion]) + return; + + dprintk("NFS: destroy per-net callback data; net=%p\n", net); + svc_shutdown_net(serv, net); +} + static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) { + struct nfs_net *nn = net_generic(net, nfs_net_id); int ret; + if (nn->cb_users[minorversion]++) + return 0; + dprintk("NFS: create per-net callback data; net=%p\n", net); ret = svc_bind(serv, net); @@ -390,7 +405,7 @@ err_create: return ret; err_start: - svc_shutdown_net(serv, net); + nfs_callback_down_net(minorversion, serv, net); dprintk("NFS: Couldn't create server thread; err = %d\n", ret); goto err_net; } @@ -403,10 +418,10 @@ void nfs_callback_down(int minorversion, struct net *net) struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; mutex_lock(&nfs_callback_mutex); + nfs_callback_down_net(minorversion, cb_info->serv, net); cb_info->users--; if (cb_info->users == 0 && cb_info->task != NULL) { kthread_stop(cb_info->task); - svc_shutdown_net(cb_info->serv, net); svc_exit_thread(cb_info->rqst); cb_info->serv = NULL; cb_info->rqst = NULL; diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 097dae1..b015ab8 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h @@ -24,6 +24,7 @@ struct nfs_net { struct idr cb_ident_idr; /* Protected by nfs_client_lock */ unsigned short nfs_callback_tcpport; unsigned short nfs_callback_tcpport6; + int cb_users[NFS4_MAX_MINOR_VERSION + 1]; #endif spinlock_t nfs_client_lock; struct timespec boot_time;
[PATCH v3 10/11] NFS: add debug messages to callback down function
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/callback.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 35ccd2a..b4e76e9 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -422,7 +422,9 @@ void nfs_callback_down(int minorversion, struct net *net) cb_info->users--; if (cb_info->users == 0 && cb_info->task != NULL) { kthread_stop(cb_info->task); + dprintk("nfs_callback_down: service stopped\n"); svc_exit_thread(cb_info->rqst); + dprintk("nfs_callback_down: service destroyed\n"); cb_info->serv = NULL; cb_info->rqst = NULL; cb_info->task = NULL;
[PATCH v3 11/11] NFS: get net after idr allocation
Allocation can fail. So instead of put net in case of failure, get net after allocation. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> --- fs/nfs/client.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index d8c918b..d17aa10 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -175,7 +175,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ clp->cl_rpcclient = ERR_PTR(-EINVAL); clp->cl_proto = cl_init->proto; - clp->cl_net = get_net(cl_init->net); + clp->cl_net = cl_init->net; #ifdef CONFIG_NFS_V4 err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); @@ -189,6 +189,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ clp->cl_minorversion = cl_init->minorversion; clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; #endif + get_net(clp->cl_net); cred = rpc_lookup_machine_cred("*"); if (!IS_ERR(cred)) clp->cl_machine_cred = cred;
Re: [PATCH v3 03/11] NFS: move per-net callback thread initialization to nfs_callback_up_net()
On Tue, Jul 03, 2012 at 08:19:46PM +0400, Stanislav Kinsbursky wrote: > This new function in now called before nfs_minorversion_callback_svc_setup()). > > Also few small changes: > 1) current network namespace in nfs_callback_up() was replaced by transport net. > 2) svc_shutdown_net() was moved prior to callback usage counter decrement > (because in case of per-net data allocation faulure svc_shutdown_net() have to > be skipped). > > Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> > --- > fs/nfs/callback.c | 125 +++++++++++++++++++++++++++++++++-------------------- > fs/nfs/client.c | 2 - > 2 files changed, 79 insertions(+), 48 deletions(-) > > diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c > index f8d0c21..b61ed61 100644 > --- a/fs/nfs/callback.c > +++ b/fs/nfs/callback.c > @@ -63,6 +63,32 @@ static struct kernel_param_ops param_ops_portnr = { > > module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); > > +static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) > +{ > + int ret; > + > + ret = svc_create_xprt(serv, "tcp", net, PF_INET, > + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); > + if (ret <= 0) > + goto out_err; > + nfs_callback_tcpport = ret; > + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", > + nfs_callback_tcpport, PF_INET, net); > + > + ret = svc_create_xprt(serv, "tcp", net, PF_INET6, > + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); > + if (ret > 0) { > + nfs_callback_tcpport6 = ret; > + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", > + nfs_callback_tcpport6, PF_INET6, net); > + } else if (ret != -EAFNOSUPPORT) > + goto out_err; > + return 0; > + > +out_err: > + return (ret) ? ret : -ENOMEM; > +} > + > /* > * This is the NFSv4 callback kernel thread. > */ > @@ -104,36 +130,21 @@ nfs4_callback_svc(void *vrqstp) > static struct svc_rqst * > nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) > { > - int ret; > - > - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, > - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); > - if (ret <= 0) > - goto out_err; > - nfs_callback_tcpport = ret; > - dprintk("NFS: Callback listener port = %u (af %u)\n", > - nfs_callback_tcpport, PF_INET); > - > - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, > - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); > - if (ret > 0) { > - nfs_callback_tcpport6 = ret; > - dprintk("NFS: Callback listener port = %u (af %u)\n", > - nfs_callback_tcpport6, PF_INET6); > - } else if (ret == -EAFNOSUPPORT) > - ret = 0; > - else > - goto out_err; > - > return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); > - > -out_err: > - if (ret == 0) > - ret = -ENOMEM; > - return ERR_PTR(ret); > } > > #if defined(CONFIG_NFS_V4_1) > +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) > +{ > + /* > + * Create an svc_sock for the back channel service that shares the > + * fore channel connection. > + * Returns the input port (0) and sets the svc_serv bc_xprt on success > + */ > + return svc_create_xprt(serv, "tcp-bc", net, PF_INET, 0, > + SVC_SOCK_ANONYMOUS); > +} > + > /* > * The callback service for NFSv4.1 callbacks > */ > @@ -176,19 +187,6 @@ static struct svc_rqst * > nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) > { > struct svc_rqst *rqstp; > - int ret; > - > - /* > - * Create an svc_sock for the back channel service that shares the > - * fore channel connection. > - * Returns the input port (0) and sets the svc_serv bc_xprt on success > - */ > - ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, > - SVC_SOCK_ANONYMOUS); > - if (ret < 0) { > - rqstp = ERR_PTR(ret); > - goto out; > - } > > /* > * Save the svc_serv in the transport so that it can > @@ -204,7 +202,6 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) > svc_xprt_put(serv->sv_bc_xprt); > serv->sv_bc_xprt = NULL; > } > -out: > dprintk("--> %s return %ld\n", __func__, > IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); > return rqstp; > @@ -228,6 +225,11 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, > xprt->bc_serv = cb_info->serv; > } > #else > +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) > +{ > + return 0; > +} > + > static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, > struct svc_serv *serv, struct rpc_xprt *xprt, > struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) > @@ -241,6 +243,36 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, > } > #endif /* CONFIG_NFS_V4_1 */ > > +static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) > +{ > + int ret; > + > + dprintk("NFS: create per-net callback data; net=%p\n", net); > + > + ret = svc_bind(serv, net); > + if (ret < 0) { > + printk(KERN_WARNING "NFS: bind callback service failed\n"); > + goto err_bind; > + } > + > + if (minorversion) { > + ret = nfs41_callback_up_net(serv, net); > + if (ret < 0) > + goto err_socks; > + } > + > + if (ret == 0) > + ret = nfs4_callback_up_net(serv, net); So in the minorversion 1 case, and in the absence of errors, you set up both the 4.1 and 4.0 callback xprts? That doesn't look right. You should need only one or the other. --b. > + if (ret < 0) > + goto err_socks; > + return 0; > + > +err_socks: > + svc_rpcb_cleanup(serv, net); > +err_bind: > + return ret; > +} > + > static struct svc_serv *nfs_callback_create_svc(int minorversion) > { > struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; > @@ -287,7 +319,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) > char svc_name[12]; > int ret = 0; > int minorversion_setup; > - struct net *net = &init_net; > + struct net *net = xprt->xprt_net; > > mutex_lock(&nfs_callback_mutex); > > @@ -302,11 +334,9 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) > goto out; > } > > - ret = svc_bind(serv, net); > - if (ret < 0) { > - printk(KERN_WARNING "NFS: bind callback service failed\n"); > - goto out_err; > - } > + ret = nfs_callback_up_net(minorversion, serv, net); > + if (ret < 0) > + goto err_net; > > minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, > serv, xprt, &rqstp, &callback_svc); > @@ -346,10 +376,11 @@ err_create: > mutex_unlock(&nfs_callback_mutex); > return ret; > out_err: > + svc_shutdown_net(serv, net); > +err_net: > dprintk("NFS: Couldn't create callback socket or server thread; " > "err = %d\n", ret); > cb_info->users--; > - svc_shutdown_net(serv, net); > goto out; > } > > diff --git a/fs/nfs/client.c b/fs/nfs/client.c > index 28bc770..d8c918b 100644 > --- a/fs/nfs/client.c > +++ b/fs/nfs/client.c > @@ -225,7 +225,7 @@ static void nfs4_shutdown_session(struct nfs_client *clp) > static void nfs4_destroy_callback(struct nfs_client *clp) > { > if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) > - nfs_callback_down(clp->cl_mvops->minor_version, &init_net); > + nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net); > } > > static void nfs4_shutdown_client(struct nfs_client *clp) >
Re: [PATCH v3 00/11] Series short description
On Tue, Jul 03, 2012 at 08:19:23PM +0400, Stanislav Kinsbursky wrote: > v3: Rebased on Bruce's tree, "for-3.6" branch > > v2: Rebased on Bruce's tree, "for-3.5" branch Aside from the one question, this looks OK to me. I seem to recall this needed to go through my tree for some reason, but does Trond still want a chance to ACK/NACK it? --b. > > This patch set depeneds on "SUNRPC: separate per-net data creation from > service > creation" patch set sent earlier. > > The following series implements... > > --- > > Stanislav Kinsbursky (11): > NFS: pass net to nfs_callback_down() > NFS: callback service creation function introduced > NFS: move per-net callback thread initialization to nfs_callback_up_net() > NFS: callback up - transport backchannel cleanup > NFS: callback service start function introduced > NFS: callback up - users counting cleanup > NFS: make nfs_callback_tcpport per network context > NFS: make nfs_callback_tcpport6 per network context > NFS; callback per-net usage counting introduced > NFS: add debug messages to callback down function > NFS: get net after idr allocation > > > fs/nfs/callback.c | 288 ++++++++++++++++++++++++++++++++++------------------ > fs/nfs/callback.h | 4 - > fs/nfs/client.c | 5 + > fs/nfs/netns.h | 3 + > fs/nfs/nfs4state.c | 6 + > 5 files changed, 202 insertions(+), 104 deletions(-) >
25.07.2012 01:47, J. Bruce Fields пишет: > On Tue, Jul 03, 2012 at 08:19:46PM +0400, Stanislav Kinsbursky wrote: >> This new function in now called before nfs_minorversion_callback_svc_setup()). >> >> Also few small changes: >> 1) current network namespace in nfs_callback_up() was replaced by transport net. >> 2) svc_shutdown_net() was moved prior to callback usage counter decrement >> (because in case of per-net data allocation faulure svc_shutdown_net() have to >> be skipped). >> >> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> >> --- >> fs/nfs/callback.c | 125 +++++++++++++++++++++++++++++++++-------------------- >> fs/nfs/client.c | 2 - >> 2 files changed, 79 insertions(+), 48 deletions(-) >> >> diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c >> index f8d0c21..b61ed61 100644 >> --- a/fs/nfs/callback.c >> +++ b/fs/nfs/callback.c >> @@ -63,6 +63,32 @@ static struct kernel_param_ops param_ops_portnr = { >> >> module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); >> >> +static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) >> +{ >> + int ret; >> + >> + ret = svc_create_xprt(serv, "tcp", net, PF_INET, >> + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >> + if (ret <= 0) >> + goto out_err; >> + nfs_callback_tcpport = ret; >> + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", >> + nfs_callback_tcpport, PF_INET, net); >> + >> + ret = svc_create_xprt(serv, "tcp", net, PF_INET6, >> + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >> + if (ret > 0) { >> + nfs_callback_tcpport6 = ret; >> + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", >> + nfs_callback_tcpport6, PF_INET6, net); >> + } else if (ret != -EAFNOSUPPORT) >> + goto out_err; >> + return 0; >> + >> +out_err: >> + return (ret) ? ret : -ENOMEM; >> +} >> + >> /* >> * This is the NFSv4 callback kernel thread. >> */ >> @@ -104,36 +130,21 @@ nfs4_callback_svc(void *vrqstp) >> static struct svc_rqst * >> nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) >> { >> - int ret; >> - >> - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, >> - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >> - if (ret <= 0) >> - goto out_err; >> - nfs_callback_tcpport = ret; >> - dprintk("NFS: Callback listener port = %u (af %u)\n", >> - nfs_callback_tcpport, PF_INET); >> - >> - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, >> - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >> - if (ret > 0) { >> - nfs_callback_tcpport6 = ret; >> - dprintk("NFS: Callback listener port = %u (af %u)\n", >> - nfs_callback_tcpport6, PF_INET6); >> - } else if (ret == -EAFNOSUPPORT) >> - ret = 0; >> - else >> - goto out_err; >> - >> return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); >> - >> -out_err: >> - if (ret == 0) >> - ret = -ENOMEM; >> - return ERR_PTR(ret); >> } >> >> #if defined(CONFIG_NFS_V4_1) >> +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) >> +{ >> + /* >> + * Create an svc_sock for the back channel service that shares the >> + * fore channel connection. >> + * Returns the input port (0) and sets the svc_serv bc_xprt on success >> + */ >> + return svc_create_xprt(serv, "tcp-bc", net, PF_INET, 0, >> + SVC_SOCK_ANONYMOUS); >> +} >> + >> /* >> * The callback service for NFSv4.1 callbacks >> */ >> @@ -176,19 +187,6 @@ static struct svc_rqst * >> nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) >> { >> struct svc_rqst *rqstp; >> - int ret; >> - >> - /* >> - * Create an svc_sock for the back channel service that shares the >> - * fore channel connection. >> - * Returns the input port (0) and sets the svc_serv bc_xprt on success >> - */ >> - ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, >> - SVC_SOCK_ANONYMOUS); >> - if (ret < 0) { >> - rqstp = ERR_PTR(ret); >> - goto out; >> - } >> >> /* >> * Save the svc_serv in the transport so that it can >> @@ -204,7 +202,6 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) >> svc_xprt_put(serv->sv_bc_xprt); >> serv->sv_bc_xprt = NULL; >> } >> -out: >> dprintk("--> %s return %ld\n", __func__, >> IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); >> return rqstp; >> @@ -228,6 +225,11 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, >> xprt->bc_serv = cb_info->serv; >> } >> #else >> +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) >> +{ >> + return 0; >> +} >> + >> static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, >> struct svc_serv *serv, struct rpc_xprt *xprt, >> struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) >> @@ -241,6 +243,36 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, >> } >> #endif /* CONFIG_NFS_V4_1 */ >> >> +static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) >> +{ >> + int ret; >> + >> + dprintk("NFS: create per-net callback data; net=%p\n", net); >> + >> + ret = svc_bind(serv, net); >> + if (ret < 0) { >> + printk(KERN_WARNING "NFS: bind callback service failed\n"); >> + goto err_bind; >> + } >> + >> + if (minorversion) { >> + ret = nfs41_callback_up_net(serv, net); >> + if (ret < 0) >> + goto err_socks; >> + } >> + >> + if (ret == 0) >> + ret = nfs4_callback_up_net(serv, net); > > So in the minorversion 1 case, and in the absence of errors, you set up > both the 4.1 and 4.0 callback xprts? > > That doesn't look right. You should need only one or the other. > Thanks for the catch, Bruce. I'll fix it and resend. But currently I'm thinking, that for 3.6 kernel probably it's better to push this code through Trond's tree. -- Best regards, Stanislav Kinsbursky
25.07.2012 02:36, J. Bruce Fields пишет: > On Tue, Jul 03, 2012 at 08:19:23PM +0400, Stanislav Kinsbursky wrote: >> v3: Rebased on Bruce's tree, "for-3.6" branch >> >> v2: Rebased on Bruce's tree, "for-3.5" branch > > Aside from the one question, this looks OK to me. > > I seem to recall this needed to go through my tree for some reason, but > does Trond still want a chance to ACK/NACK it? > Agreed. Trond, could you, please, review this patch set? And maybe it's better to push this code through your tree to simplify further merging? > --b. > >> >> This patch set depeneds on "SUNRPC: separate per-net data creation from >> service >> creation" patch set sent earlier. >> >> The following series implements... >> >> --- >> >> Stanislav Kinsbursky (11): >> NFS: pass net to nfs_callback_down() >> NFS: callback service creation function introduced >> NFS: move per-net callback thread initialization to nfs_callback_up_net() >> NFS: callback up - transport backchannel cleanup >> NFS: callback service start function introduced >> NFS: callback up - users counting cleanup >> NFS: make nfs_callback_tcpport per network context >> NFS: make nfs_callback_tcpport6 per network context >> NFS; callback per-net usage counting introduced >> NFS: add debug messages to callback down function >> NFS: get net after idr allocation >> >> >> fs/nfs/callback.c | 288 ++++++++++++++++++++++++++++++++++------------------ >> fs/nfs/callback.h | 4 - >> fs/nfs/client.c | 5 + >> fs/nfs/netns.h | 3 + >> fs/nfs/nfs4state.c | 6 + >> 5 files changed, 202 insertions(+), 104 deletions(-) >> -- Best regards, Stanislav Kinsbursky
25.07.2012 14:18, Stanislav Kinsbursky пишет: > 25.07.2012 01:47, J. Bruce Fields пишет: >> On Tue, Jul 03, 2012 at 08:19:46PM +0400, Stanislav Kinsbursky wrote: >>> This new function in now called before nfs_minorversion_callback_svc_setup()). >>> >>> Also few small changes: >>> 1) current network namespace in nfs_callback_up() was replaced by transport net. >>> 2) svc_shutdown_net() was moved prior to callback usage counter decrement >>> (because in case of per-net data allocation faulure svc_shutdown_net() have to >>> be skipped). >>> >>> Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> >>> --- >>> fs/nfs/callback.c | 125 +++++++++++++++++++++++++++++++++-------------------- >>> fs/nfs/client.c | 2 - >>> 2 files changed, 79 insertions(+), 48 deletions(-) >>> >>> diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c >>> index f8d0c21..b61ed61 100644 >>> --- a/fs/nfs/callback.c >>> +++ b/fs/nfs/callback.c >>> @@ -63,6 +63,32 @@ static struct kernel_param_ops param_ops_portnr = { >>> >>> module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644); >>> >>> +static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net) >>> +{ >>> + int ret; >>> + >>> + ret = svc_create_xprt(serv, "tcp", net, PF_INET, >>> + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >>> + if (ret <= 0) >>> + goto out_err; >>> + nfs_callback_tcpport = ret; >>> + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", >>> + nfs_callback_tcpport, PF_INET, net); >>> + >>> + ret = svc_create_xprt(serv, "tcp", net, PF_INET6, >>> + nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >>> + if (ret > 0) { >>> + nfs_callback_tcpport6 = ret; >>> + dprintk("NFS: Callback listener port = %u (af %u, net %p)\n", >>> + nfs_callback_tcpport6, PF_INET6, net); >>> + } else if (ret != -EAFNOSUPPORT) >>> + goto out_err; >>> + return 0; >>> + >>> +out_err: >>> + return (ret) ? ret : -ENOMEM; >>> +} >>> + >>> /* >>> * This is the NFSv4 callback kernel thread. >>> */ >>> @@ -104,36 +130,21 @@ nfs4_callback_svc(void *vrqstp) >>> static struct svc_rqst * >>> nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) >>> { >>> - int ret; >>> - >>> - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, >>> - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >>> - if (ret <= 0) >>> - goto out_err; >>> - nfs_callback_tcpport = ret; >>> - dprintk("NFS: Callback listener port = %u (af %u)\n", >>> - nfs_callback_tcpport, PF_INET); >>> - >>> - ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, >>> - nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); >>> - if (ret > 0) { >>> - nfs_callback_tcpport6 = ret; >>> - dprintk("NFS: Callback listener port = %u (af %u)\n", >>> - nfs_callback_tcpport6, PF_INET6); >>> - } else if (ret == -EAFNOSUPPORT) >>> - ret = 0; >>> - else >>> - goto out_err; >>> - >>> return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); >>> - >>> -out_err: >>> - if (ret == 0) >>> - ret = -ENOMEM; >>> - return ERR_PTR(ret); >>> } >>> >>> #if defined(CONFIG_NFS_V4_1) >>> +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) >>> +{ >>> + /* >>> + * Create an svc_sock for the back channel service that shares the >>> + * fore channel connection. >>> + * Returns the input port (0) and sets the svc_serv bc_xprt on success >>> + */ >>> + return svc_create_xprt(serv, "tcp-bc", net, PF_INET, 0, >>> + SVC_SOCK_ANONYMOUS); >>> +} >>> + >>> /* >>> * The callback service for NFSv4.1 callbacks >>> */ >>> @@ -176,19 +187,6 @@ static struct svc_rqst * >>> nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) >>> { >>> struct svc_rqst *rqstp; >>> - int ret; >>> - >>> - /* >>> - * Create an svc_sock for the back channel service that shares the >>> - * fore channel connection. >>> - * Returns the input port (0) and sets the svc_serv bc_xprt on success >>> - */ >>> - ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, >>> - SVC_SOCK_ANONYMOUS); >>> - if (ret < 0) { >>> - rqstp = ERR_PTR(ret); >>> - goto out; >>> - } >>> >>> /* >>> * Save the svc_serv in the transport so that it can >>> @@ -204,7 +202,6 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) >>> svc_xprt_put(serv->sv_bc_xprt); >>> serv->sv_bc_xprt = NULL; >>> } >>> -out: >>> dprintk("--> %s return %ld\n", __func__, >>> IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); >>> return rqstp; >>> @@ -228,6 +225,11 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, >>> xprt->bc_serv = cb_info->serv; >>> } >>> #else >>> +static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) >>> +{ >>> + return 0; >>> +} >>> + >>> static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, >>> struct svc_serv *serv, struct rpc_xprt *xprt, >>> struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) >>> @@ -241,6 +243,36 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, >>> } >>> #endif /* CONFIG_NFS_V4_1 */ >>> >>> +static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) >>> +{ >>> + int ret; >>> + >>> + dprintk("NFS: create per-net callback data; net=%p\n", net); >>> + >>> + ret = svc_bind(serv, net); >>> + if (ret < 0) { >>> + printk(KERN_WARNING "NFS: bind callback service failed\n"); >>> + goto err_bind; >>> + } >>> + >>> + if (minorversion) { >>> + ret = nfs41_callback_up_net(serv, net); >>> + if (ret < 0) >>> + goto err_socks; >>> + } >>> + >>> + if (ret == 0) >>> + ret = nfs4_callback_up_net(serv, net); >> >> So in the minorversion 1 case, and in the absence of errors, you set up >> both the 4.1 and 4.0 callback xprts? >> >> That doesn't look right. You should need only one or the other. >> > > Thanks for the catch, Bruce. > I'll fix it and resend. > But currently I'm thinking, that for 3.6 kernel probably it's better to push > this code through Trond's tree. > No, Bruce. It works fine. nfs41_callback_up_net() will return either negative value of port number. I.e. nfs4_callback_up_net() won't be called. But this looks confusing. I'll rewrite this part. -- Best regards, Stanislav Kinsbursky
25.07.2012 02:36, J. Bruce Fields пишет: > On Tue, Jul 03, 2012 at 08:19:23PM +0400, Stanislav Kinsbursky wrote: >> v3: Rebased on Bruce's tree, "for-3.6" branch >> >> v2: Rebased on Bruce's tree, "for-3.5" branch > > Aside from the one question, this looks OK to me. > > I seem to recall this needed to go through my tree for some reason, but > does Trond still want a chance to ACK/NACK it? > > --b. > Bruce, I'll send this patch set once more to Trond. Thanks for your time. -- Best regards, Stanislav Kinsbursky