提交 528fd354 编写于 作者: T Trond Myklebust

SUNRPC: Destroy transport from the system workqueue

The transport may need to flush transport connect and receive tasks
that are running on rpciod. In order to do so safely, we need to
ensure that the caller of cancel_work_sync() etc is not itself
running on rpciod.
Do so by running the destroy task from the system workqueue.
Signed-off-by: NTrond Myklebust <trond.myklebust@primarydata.com>
上级 4c625a97
...@@ -1445,6 +1445,23 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args) ...@@ -1445,6 +1445,23 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
return xprt; return xprt;
} }
static void xprt_destroy_cb(struct work_struct *work)
{
struct rpc_xprt *xprt =
container_of(work, struct rpc_xprt, task_cleanup);
rpc_xprt_debugfs_unregister(xprt);
rpc_destroy_wait_queue(&xprt->binding);
rpc_destroy_wait_queue(&xprt->pending);
rpc_destroy_wait_queue(&xprt->sending);
rpc_destroy_wait_queue(&xprt->backlog);
kfree(xprt->servername);
/*
* Tear down transport state and free the rpc_xprt
*/
xprt->ops->destroy(xprt);
}
/** /**
* xprt_destroy - destroy an RPC transport, killing off all requests. * xprt_destroy - destroy an RPC transport, killing off all requests.
* @xprt: transport to destroy * @xprt: transport to destroy
...@@ -1454,22 +1471,19 @@ static void xprt_destroy(struct rpc_xprt *xprt) ...@@ -1454,22 +1471,19 @@ static void xprt_destroy(struct rpc_xprt *xprt)
{ {
dprintk("RPC: destroying transport %p\n", xprt); dprintk("RPC: destroying transport %p\n", xprt);
/* Exclude transport connect/disconnect handlers */ /*
* Exclude transport connect/disconnect handlers and autoclose
*/
wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE); wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
del_timer_sync(&xprt->timer); del_timer_sync(&xprt->timer);
rpc_xprt_debugfs_unregister(xprt);
rpc_destroy_wait_queue(&xprt->binding);
rpc_destroy_wait_queue(&xprt->pending);
rpc_destroy_wait_queue(&xprt->sending);
rpc_destroy_wait_queue(&xprt->backlog);
cancel_work_sync(&xprt->task_cleanup);
kfree(xprt->servername);
/* /*
* Tear down transport state and free the rpc_xprt * Destroy sockets etc from the system workqueue so they can
* safely flush receive work running on rpciod.
*/ */
xprt->ops->destroy(xprt); INIT_WORK(&xprt->task_cleanup, xprt_destroy_cb);
schedule_work(&xprt->task_cleanup);
} }
static void xprt_destroy_kref(struct kref *kref) static void xprt_destroy_kref(struct kref *kref)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册