aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/callback.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 51297b2d0532..18efeb5f005d 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -217,12 +217,50 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
217} 217}
218#endif /* CONFIG_NFS_V4_1 */ 218#endif /* CONFIG_NFS_V4_1 */
219 219
220static struct svc_serv *nfs_callback_create_svc(int minorversion)
221{
222 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
223 struct svc_serv *serv;
224
225 /*
226 * Check whether we're already up and running.
227 */
228 if (cb_info->task) {
229 /*
230 * Note: increase service usage, because later in case of error
231 * svc_destroy() will be called.
232 */
233 svc_get(cb_info->serv);
234 return cb_info->serv;
235 }
236
237 /*
238 * Sanity check: if there's no task,
239 * we should be the first user ...
240 */
241 if (cb_info->users)
242 printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
243 cb_info->users);
244
245 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
246 if (!serv) {
247 printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
248 return ERR_PTR(-ENOMEM);
249 }
250 /* As there is only one thread we need to over-ride the
251 * default maximum of 80 connections
252 */
253 serv->sv_maxconn = 1024;
254 dprintk("nfs_callback_create_svc: service created\n");
255 return serv;
256}
257
220/* 258/*
221 * Bring up the callback thread if it is not already up. 259 * Bring up the callback thread if it is not already up.
222 */ 260 */
223int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) 261int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
224{ 262{
225 struct svc_serv *serv = NULL; 263 struct svc_serv *serv;
226 struct svc_rqst *rqstp; 264 struct svc_rqst *rqstp;
227 int (*callback_svc)(void *vrqstp); 265 int (*callback_svc)(void *vrqstp);
228 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 266 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
@@ -232,19 +270,17 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
232 struct net *net = &init_net; 270 struct net *net = &init_net;
233 271
234 mutex_lock(&nfs_callback_mutex); 272 mutex_lock(&nfs_callback_mutex);
273
274 serv = nfs_callback_create_svc(minorversion);
275 if (IS_ERR(serv)) {
276 ret = PTR_ERR(serv);
277 goto err_create;
278 }
279
235 if (cb_info->users++ || cb_info->task != NULL) { 280 if (cb_info->users++ || cb_info->task != NULL) {
236 nfs_callback_bc_serv(minorversion, xprt, cb_info); 281 nfs_callback_bc_serv(minorversion, xprt, cb_info);
237 goto out; 282 goto out;
238 } 283 }
239 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
240 if (!serv) {
241 ret = -ENOMEM;
242 goto out_err;
243 }
244 /* As there is only one thread we need to over-ride the
245 * default maximum of 80 connections
246 */
247 serv->sv_maxconn = 1024;
248 284
249 ret = svc_bind(serv, net); 285 ret = svc_bind(serv, net);
250 if (ret < 0) { 286 if (ret < 0) {
@@ -285,16 +321,15 @@ out:
285 * on both success and failure so that the refcount is 1 when the 321 * on both success and failure so that the refcount is 1 when the
286 * thread exits. 322 * thread exits.
287 */ 323 */
288 if (serv) 324 svc_destroy(serv);
289 svc_destroy(serv); 325err_create:
290 mutex_unlock(&nfs_callback_mutex); 326 mutex_unlock(&nfs_callback_mutex);
291 return ret; 327 return ret;
292out_err: 328out_err:
293 dprintk("NFS: Couldn't create callback socket or server thread; " 329 dprintk("NFS: Couldn't create callback socket or server thread; "
294 "err = %d\n", ret); 330 "err = %d\n", ret);
295 cb_info->users--; 331 cb_info->users--;
296 if (serv) 332 svc_shutdown_net(serv, net);
297 svc_shutdown_net(serv, net);
298 goto out; 333 goto out;
299} 334}
300 335