aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-10-25 00:46:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-10-25 00:46:43 -0400
commitf34157878d3b17641ad2366988600c23c89d98b2 (patch)
tree694070f19ebc813ef8fc24e2aeb1f4db62153ab3
parentae59df0349baf44c988b32a3b4dc21363d87df15 (diff)
parent528fd3547bad0bdd31c8f987e5bd00c83df8af39 (diff)
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()
-rw-r--r--net/sunrpc/xprt.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index e741ec2b4d8e..898485e3ece4 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1333,7 +1333,7 @@ void xprt_release(struct rpc_task *task)
1333 rpc_count_iostats(task, task->tk_client->cl_metrics); 1333 rpc_count_iostats(task, task->tk_client->cl_metrics);
1334 spin_lock(&xprt->recv_lock); 1334 spin_lock(&xprt->recv_lock);
1335 if (!list_empty(&req->rq_list)) { 1335 if (!list_empty(&req->rq_list)) {
1336 list_del(&req->rq_list); 1336 list_del_init(&req->rq_list);
1337 xprt_wait_on_pinned_rqst(req); 1337 xprt_wait_on_pinned_rqst(req);
1338 } 1338 }
1339 spin_unlock(&xprt->recv_lock); 1339 spin_unlock(&xprt->recv_lock);
@@ -1445,6 +1445,23 @@ out:
1445 return xprt; 1445 return xprt;
1446} 1446}
1447 1447
1448static void xprt_destroy_cb(struct work_struct *work)
1449{
1450 struct rpc_xprt *xprt =
1451 container_of(work, struct rpc_xprt, task_cleanup);
1452
1453 rpc_xprt_debugfs_unregister(xprt);
1454 rpc_destroy_wait_queue(&xprt->binding);
1455 rpc_destroy_wait_queue(&xprt->pending);
1456 rpc_destroy_wait_queue(&xprt->sending);
1457 rpc_destroy_wait_queue(&xprt->backlog);
1458 kfree(xprt->servername);
1459 /*
1460 * Tear down transport state and free the rpc_xprt
1461 */
1462 xprt->ops->destroy(xprt);
1463}
1464
1448/** 1465/**
1449 * xprt_destroy - destroy an RPC transport, killing off all requests. 1466 * xprt_destroy - destroy an RPC transport, killing off all requests.
1450 * @xprt: transport to destroy 1467 * @xprt: transport to destroy
@@ -1454,22 +1471,19 @@ static void xprt_destroy(struct rpc_xprt *xprt)
1454{ 1471{
1455 dprintk("RPC: destroying transport %p\n", xprt); 1472 dprintk("RPC: destroying transport %p\n", xprt);
1456 1473
1457 /* Exclude transport connect/disconnect handlers */ 1474 /*
1475 * Exclude transport connect/disconnect handlers and autoclose
1476 */
1458 wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE); 1477 wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
1459 1478
1460 del_timer_sync(&xprt->timer); 1479 del_timer_sync(&xprt->timer);
1461 1480
1462 rpc_xprt_debugfs_unregister(xprt);
1463 rpc_destroy_wait_queue(&xprt->binding);
1464 rpc_destroy_wait_queue(&xprt->pending);
1465 rpc_destroy_wait_queue(&xprt->sending);
1466 rpc_destroy_wait_queue(&xprt->backlog);
1467 cancel_work_sync(&xprt->task_cleanup);
1468 kfree(xprt->servername);
1469 /* 1481 /*
1470 * Tear down transport state and free the rpc_xprt 1482 * Destroy sockets etc from the system workqueue so they can
1483 * safely flush receive work running on rpciod.
1471 */ 1484 */
1472 xprt->ops->destroy(xprt); 1485 INIT_WORK(&xprt->task_cleanup, xprt_destroy_cb);
1486 schedule_work(&xprt->task_cleanup);
1473} 1487}
1474 1488
1475static void xprt_destroy_kref(struct kref *kref) 1489static void xprt_destroy_kref(struct kref *kref)