mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 08:26:59 +00:00
SUNRPC: Close a race with transport setup and module put
After we've looked up the transport module, we need to ensure it can't go away until we've finished running the transport setup code. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
d5aa6b22e2
commit
9bccd26461
1 changed files with 33 additions and 11 deletions
|
@ -157,6 +157,32 @@ xprt_class_release(const struct xprt_class *t)
|
|||
module_put(t->owner);
|
||||
}
|
||||
|
||||
static const struct xprt_class *
|
||||
xprt_class_find_by_ident_locked(int ident)
|
||||
{
|
||||
const struct xprt_class *t;
|
||||
|
||||
list_for_each_entry(t, &xprt_list, list) {
|
||||
if (t->ident != ident)
|
||||
continue;
|
||||
if (!try_module_get(t->owner))
|
||||
continue;
|
||||
return t;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct xprt_class *
|
||||
xprt_class_find_by_ident(int ident)
|
||||
{
|
||||
const struct xprt_class *t;
|
||||
|
||||
spin_lock(&xprt_list_lock);
|
||||
t = xprt_class_find_by_ident_locked(ident);
|
||||
spin_unlock(&xprt_list_lock);
|
||||
return t;
|
||||
}
|
||||
|
||||
static const struct xprt_class *
|
||||
xprt_class_find_by_netid_locked(const char *netid)
|
||||
{
|
||||
|
@ -1929,21 +1955,17 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net)
|
|||
struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
|
||||
{
|
||||
struct rpc_xprt *xprt;
|
||||
struct xprt_class *t;
|
||||
const struct xprt_class *t;
|
||||
|
||||
spin_lock(&xprt_list_lock);
|
||||
list_for_each_entry(t, &xprt_list, list) {
|
||||
if (t->ident == args->ident) {
|
||||
spin_unlock(&xprt_list_lock);
|
||||
goto found;
|
||||
}
|
||||
t = xprt_class_find_by_ident(args->ident);
|
||||
if (!t) {
|
||||
dprintk("RPC: transport (%d) not supported\n", args->ident);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
spin_unlock(&xprt_list_lock);
|
||||
dprintk("RPC: transport (%d) not supported\n", args->ident);
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
found:
|
||||
xprt = t->setup(args);
|
||||
xprt_class_release(t);
|
||||
|
||||
if (IS_ERR(xprt))
|
||||
goto out;
|
||||
if (args->flags & XPRT_CREATE_NO_IDLE_TIMEOUT)
|
||||
|
|
Loading…
Reference in a new issue