summaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-10-19 12:13:10 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-10-19 12:17:56 -0400
commit528fd3547bad0bdd31c8f987e5bd00c83df8af39 (patch)
treeb3c63debe9be5b6cf44b386066e453b6094d8a8a /net/sunrpc
parent4c625a974fb81724e60966b677e47fcba782c950 (diff)
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: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/xprt.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1a39ad14c42f..898485e3ece4 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -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)