Commit f3415787 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-4.14-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:

 - Fix a list corruption in xprt_release()

 - Fix a workqueue lockdep warning due to unsafe use of
   cancel_work_sync()

* tag 'nfs-for-4.14-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  SUNRPC: Destroy transport from the system workqueue
  SUNRPC: fix a list corruption issue in xprt_release()
parents ae59df03 528fd354
...@@ -1333,7 +1333,7 @@ void xprt_release(struct rpc_task *task) ...@@ -1333,7 +1333,7 @@ void xprt_release(struct rpc_task *task)
rpc_count_iostats(task, task->tk_client->cl_metrics); rpc_count_iostats(task, task->tk_client->cl_metrics);
spin_lock(&xprt->recv_lock); spin_lock(&xprt->recv_lock);
if (!list_empty(&req->rq_list)) { if (!list_empty(&req->rq_list)) {
list_del(&req->rq_list); list_del_init(&req->rq_list);
xprt_wait_on_pinned_rqst(req); xprt_wait_on_pinned_rqst(req);
} }
spin_unlock(&xprt->recv_lock); spin_unlock(&xprt->recv_lock);
...@@ -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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment