diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-08-20 10:00:16 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-01 18:25:24 -0400 |
commit | c946556b8749beb357e2d2860e7dac757972dd3d (patch) | |
tree | 63a7a403984febfcaab31a13726b68be1f627486 /fs/nfs | |
parent | dd018428dce087b72d9e6a0b32e93cb8088b3aaa (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.c | 133 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 2 |
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 | ||
40 | unsigned short nfs_callback_tcpport6; | 40 | unsigned short nfs_callback_tcpport6; |
41 | 41 | ||
42 | static 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 | |||
64 | out_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) | |||
80 | static struct svc_rqst * | 106 | static struct svc_rqst * |
81 | nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) | 107 | nfs4_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 | |||
106 | out_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) |
113 | static 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 * | |||
152 | nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) | 163 | nfs41_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 | } |
183 | out: | ||
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 |
204 | static int nfs41_callback_up_net(struct svc_serv *serv, struct net *net) | ||
205 | { | ||
206 | return 0; | ||
207 | } | ||
208 | |||
207 | static inline int nfs_minorversion_callback_svc_setup(u32 minorversion, | 209 | static 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 | ||
222 | static 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 | |||
254 | err_socks: | ||
255 | svc_rpcb_cleanup(serv, net); | ||
256 | err_bind: | ||
257 | return ret; | ||
258 | } | ||
259 | |||
220 | static struct svc_serv *nfs_callback_create_svc(int minorversion) | 260 | static 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; |
328 | out_err: | 366 | out_err: |
367 | svc_shutdown_net(serv, net); | ||
368 | err_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: | |||
84 | static void nfs4_destroy_callback(struct nfs_client *clp) | 84 | static 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 | ||
90 | static void nfs4_shutdown_client(struct nfs_client *clp) | 90 | static void nfs4_shutdown_client(struct nfs_client *clp) |