diff options
Diffstat (limited to 'net/sunrpc/svc_xprt.c')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index eb650af50c4..271467c5138 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -105,6 +105,7 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt, INIT_LIST_HEAD(&xprt->xpt_deferred); mutex_init(&xprt->xpt_mutex); spin_lock_init(&xprt->xpt_lock); + set_bit(XPT_BUSY, &xprt->xpt_flags); } EXPORT_SYMBOL_GPL(svc_xprt_init); @@ -112,7 +113,6 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, int flags) { struct svc_xprt_class *xcl; - int ret = -ENOENT; struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, @@ -121,27 +121,34 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, dprintk("svc: creating transport %s[%d]\n", xprt_name, port); spin_lock(&svc_xprt_class_lock); list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { - if (strcmp(xprt_name, xcl->xcl_name) == 0) { - spin_unlock(&svc_xprt_class_lock); - if (try_module_get(xcl->xcl_owner)) { - struct svc_xprt *newxprt; - newxprt = xcl->xcl_ops->xpo_create - (serv, - (struct sockaddr *)&sin, sizeof(sin), - flags); - if (IS_ERR(newxprt)) { - module_put(xcl->xcl_owner); - ret = PTR_ERR(newxprt); - } else - ret = svc_xprt_local_port(newxprt); - } - goto out; + struct svc_xprt *newxprt; + + if (strcmp(xprt_name, xcl->xcl_name)) + continue; + + if (!try_module_get(xcl->xcl_owner)) + goto err; + + spin_unlock(&svc_xprt_class_lock); + newxprt = xcl->xcl_ops-> + xpo_create(serv, (struct sockaddr *)&sin, sizeof(sin), + flags); + if (IS_ERR(newxprt)) { + module_put(xcl->xcl_owner); + return PTR_ERR(newxprt); } + + clear_bit(XPT_TEMP, &newxprt->xpt_flags); + spin_lock_bh(&serv->sv_lock); + list_add(&newxprt->xpt_list, &serv->sv_permsocks); + spin_unlock_bh(&serv->sv_lock); + clear_bit(XPT_BUSY, &newxprt->xpt_flags); + return svc_xprt_local_port(newxprt); } + err: spin_unlock(&svc_xprt_class_lock); dprintk("svc: transport %s not found\n", xprt_name); - out: - return ret; + return -ENOENT; } EXPORT_SYMBOL_GPL(svc_create_xprt); |