| From a8c32a5c98943d370ea606a2e7dc04717eb92206 Mon Sep 17 00:00:00 2001 |
| From: Jens Axboe <axboe@kernel.dk> |
| Date: Tue, 6 Nov 2012 12:24:26 +0100 |
| Subject: dm: fix deadlock with request based dm and queue request_fn recursion |
| |
| From: Jens Axboe <axboe@kernel.dk> |
| |
| commit a8c32a5c98943d370ea606a2e7dc04717eb92206 upstream. |
| |
| Request based dm attempts to re-run the request queue off the |
| request completion path. If used with a driver that potentially does |
| end_io from its request_fn, we could deadlock trying to recurse |
| back into request dispatch. Fix this by punting the request queue |
| run to kblockd. |
| |
| Tested to fix a quickly reproducible deadlock in such a scenario. |
| |
| Acked-by: Alasdair G Kergon <agk@redhat.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/md/dm.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/md/dm.c |
| +++ b/drivers/md/dm.c |
| @@ -745,8 +745,14 @@ static void rq_completed(struct mapped_d |
| if (!md_in_flight(md)) |
| wake_up(&md->wait); |
| |
| + /* |
| + * Run this off this callpath, as drivers could invoke end_io while |
| + * inside their request_fn (and holding the queue lock). Calling |
| + * back into ->request_fn() could deadlock attempting to grab the |
| + * queue lock again. |
| + */ |
| if (run_queue) |
| - blk_run_queue(md->queue); |
| + blk_run_queue_async(md->queue); |
| |
| /* |
| * dm_put() must be at the end of this function. See the comment above |