aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-08-20 10:00:16 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-01 18:25:24 -0400
commitc946556b8749beb357e2d2860e7dac757972dd3d (patch)
tree63a7a403984febfcaab31a13726b68be1f627486 /fs/nfs
parentdd018428dce087b72d9e6a0b32e93cb8088b3aaa (diff)
NFS: move per-net callback thread initialization to nfs_callback_up_net()
v4: 1) Callback transport creation routine selection by version simlified. 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> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/callback.c133
-rw-r--r--fs/nfs/nfs4client.c2
2 files changed, 87 insertions, 48 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 18efeb5f005d..a53b4e53d5dd 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -39,6 +39,32 @@ static struct svc_program nfs4_callback_program;
39 39
40unsigned short nfs_callback_tcpport6; 40unsigned short nfs_callback_tcpport6;
41 41
42static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
43{
44 int ret;
45
46 ret = svc_create_xprt(serv, "tcp", net, PF_INET,
47 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
48 if (ret <= 0)
49 goto out_err;
50 nfs_callback_tcpport = ret;
51 dprintk("NFS: Callback listener port = %u (af %u, net %p)\n",
52 nfs_callback_tcpport, PF_INET, net);
53
54 ret = svc_create_xprt(serv, "tcp", net, PF_INET6,
55 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
56 if (ret > 0) {
57 nfs_callback_tcpport6 = ret;
58 dprintk("NFS: Callback listener port = %u (af %u, net %p)\n",
59 nfs_callback_tcpport6, PF_INET6, net);
60 } else if (ret != -EAFNOSUPPORT)
61 goto out_err;
62 return 0;
63
64out_err:
65 return (ret) ? ret : -ENOMEM;
66}
67
42/* 68/*
43 * This is the NFSv4 callback kernel thread. 69 * This is the NFSv4 callback kernel thread.
44 */ 70 */
@@ -80,36 +106,21 @@ nfs4_callback_svc(void *vrqstp)
80static struct svc_rqst * 106static struct svc_rqst *
81nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 107nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
82{ 108{
83 int ret;
84
85 ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
86 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
87 if (ret <= 0)
88 goto out_err;
89 nfs_callback_tcpport = ret;
90 dprintk("NFS: Callback listener port = %u (af %u)\n",
91 nfs_callback_tcpport, PF_INET);
92
93 ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
94 nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
95 if (ret > 0) {
96 nfs_callback_tcpport6 = ret;
97 dprintk("NFS: Callback listener port = %u (af %u)\n",
98 nfs_callback_tcpport6, PF_INET6);
99 } else if (ret == -EAFNOSUPPORT)
100 ret = 0;
101 else
102 goto out_err;
103
104 return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE); 109 return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
105
106out_err:
107 if (ret == 0)
108 ret = -ENOMEM;
109 return ERR_PTR(ret);
110} 110}
111 111
112#if defined(CONFIG_NFS_V4_1) 112#if defined(CONFIG_NFS_V4_1)
113static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net)
114{
115 /*
116 * Create an svc_sock for the back channel service that shares the
117 * fore channel connection.
118 * Returns the input port (0) and sets the svc_serv bc_xprt on success
119 */
120 return svc_create_xprt(serv, "tcp-bc", net, PF_INET, 0,
121 SVC_SOCK_ANONYMOUS);
122}
123
113/* 124/*
114 * The callback service for NFSv4.1 callbacks 125 * The callback service for NFSv4.1 callbacks
115 */ 126 */
@@ -152,19 +163,6 @@ static struct svc_rqst *
152nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) 163nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
153{ 164{
154 struct svc_rqst *rqstp; 165 struct svc_rqst *rqstp;
155 int ret;
156
157 /*
158 * Create an svc_sock for the back channel service that shares the
159 * fore channel connection.
160 * Returns the input port (0) and sets the svc_serv bc_xprt on success
161 */
162 ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0,
163 SVC_SOCK_ANONYMOUS);
164 if (ret < 0) {
165 rqstp = ERR_PTR(ret);
166 goto out;
167 }
168 166
169 /* 167 /*
170 * Save the svc_serv in the transport so that it can 168 * Save the svc_serv in the transport so that it can
@@ -180,7 +178,6 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
180 svc_xprt_put(serv->sv_bc_xprt); 178 svc_xprt_put(serv->sv_bc_xprt);
181 serv->sv_bc_xprt = NULL; 179 serv->sv_bc_xprt = NULL;
182 } 180 }
183out:
184 dprintk("--> %s return %ld\n", __func__, 181 dprintk("--> %s return %ld\n", __func__,
185 IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0); 182 IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0);
186 return rqstp; 183 return rqstp;
@@ -204,6 +201,11 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
204 xprt->bc_serv = cb_info->serv; 201 xprt->bc_serv = cb_info->serv;
205} 202}
206#else 203#else
204static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net)
205{
206 return 0;
207}
208
207static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, 209static inline int nfs_minorversion_callback_svc_setup(u32 minorversion,
208 struct svc_serv *serv, struct rpc_xprt *xprt, 210 struct svc_serv *serv, struct rpc_xprt *xprt,
209 struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp)) 211 struct svc_rqst **rqstpp, int (**callback_svc)(void *vrqstp))
@@ -217,6 +219,44 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
217} 219}
218#endif /* CONFIG_NFS_V4_1 */ 220#endif /* CONFIG_NFS_V4_1 */
219 221
222static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net)
223{
224 int ret;
225
226 dprintk("NFS: create per-net callback data; net=%p\n", net);
227
228 ret = svc_bind(serv, net);
229 if (ret < 0) {
230 printk(KERN_WARNING "NFS: bind callback service failed\n");
231 goto err_bind;
232 }
233
234 switch (minorversion) {
235 case 0:
236 ret = nfs4_callback_up_net(serv, net);
237 break;
238 case 1:
239 ret = nfs41_callback_up_net(serv, net);
240 break;
241 default:
242 printk(KERN_ERR "NFS: unknown callback version: %d\n",
243 minorversion);
244 ret = -EINVAL;
245 break;
246 }
247
248 if (ret < 0) {
249 printk(KERN_ERR "NFS: callback service start failed\n");
250 goto err_socks;
251 }
252 return 0;
253
254err_socks:
255 svc_rpcb_cleanup(serv, net);
256err_bind:
257 return ret;
258}
259
220static struct svc_serv *nfs_callback_create_svc(int minorversion) 260static struct svc_serv *nfs_callback_create_svc(int minorversion)
221{ 261{
222 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 262 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
@@ -267,7 +307,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
267 char svc_name[12]; 307 char svc_name[12];
268 int ret = 0; 308 int ret = 0;
269 int minorversion_setup; 309 int minorversion_setup;
270 struct net *net = &init_net; 310 struct net *net = xprt->xprt_net;
271 311
272 mutex_lock(&nfs_callback_mutex); 312 mutex_lock(&nfs_callback_mutex);
273 313
@@ -282,11 +322,9 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
282 goto out; 322 goto out;
283 } 323 }
284 324
285 ret = svc_bind(serv, net); 325 ret = nfs_callback_up_net(minorversion, serv, net);
286 if (ret < 0) { 326 if (ret < 0)
287 printk(KERN_WARNING "NFS: bind callback service failed\n"); 327 goto err_net;
288 goto out_err;
289 }
290 328
291 minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, 329 minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion,
292 serv, xprt, &rqstp, &callback_svc); 330 serv, xprt, &rqstp, &callback_svc);
@@ -326,10 +364,11 @@ err_create:
326 mutex_unlock(&nfs_callback_mutex); 364 mutex_unlock(&nfs_callback_mutex);
327 return ret; 365 return ret;
328out_err: 366out_err:
367 svc_shutdown_net(serv, net);
368err_net:
329 dprintk("NFS: Couldn't create callback socket or server thread; " 369 dprintk("NFS: Couldn't create callback socket or server thread; "
330 "err = %d\n", ret); 370 "err = %d\n", ret);
331 cb_info->users--; 371 cb_info->users--;
332 svc_shutdown_net(serv, net);
333 goto out; 372 goto out;
334} 373}
335 374
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 088a7d2e2ecb..612f5ebaabac 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -84,7 +84,7 @@ error:
84static void nfs4_destroy_callback(struct nfs_client *clp) 84static void nfs4_destroy_callback(struct nfs_client *clp)
85{ 85{
86 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) 86 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
87 nfs_callback_down(clp->cl_mvops->minor_version, &init_net); 87 nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net);
88} 88}
89 89
90static void nfs4_shutdown_client(struct nfs_client *clp) 90static void nfs4_shutdown_client(struct nfs_client *clp)