diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-25 00:46:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-25 00:46:43 -0400 |
commit | f34157878d3b17641ad2366988600c23c89d98b2 (patch) | |
tree | 694070f19ebc813ef8fc24e2aeb1f4db62153ab3 | |
parent | ae59df0349baf44c988b32a3b4dc21363d87df15 (diff) | |
parent | 528fd3547bad0bdd31c8f987e5bd00c83df8af39 (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.c | 36 |
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 | ||
1448 | static 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 | ||
1475 | static void xprt_destroy_kref(struct kref *kref) | 1489 | static void xprt_destroy_kref(struct kref *kref) |