Commit 109b81296c63228578d4760794d8dd46e02eddfb
Committed by
Jens Axboe
1 parent
4263a2f1da
Exists in
master
and in
7 other branches
block: splice plug list to local context
If the request_fn ends up blocking, we could be re-entering the plug flush. Since the list is protected by explicitly not allowing schedule events, this isn't a terribly good idea. Additionally, it can cause us to recurse. As request_fn called by __blk_run_queue is allowed to 'schedule()' (after dropping the queue lock of course), it is possible to get a recursive call: schedule -> blk_flush_plug -> __blk_finish_plug -> flush_plug_list -> __blk_run_queue -> request_fn -> schedule We must make sure that the second schedule does not call into blk_flush_plug again. So instead of leaving the list of requests on blk_plug->list, move them to a separate list leaving blk_plug->list empty. Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Showing 1 changed file with 9 additions and 5 deletions Side-by-side Diff
block/blk-core.c
... | ... | @@ -2673,19 +2673,24 @@ |
2673 | 2673 | struct request_queue *q; |
2674 | 2674 | unsigned long flags; |
2675 | 2675 | struct request *rq; |
2676 | + LIST_HEAD(list); | |
2676 | 2677 | |
2677 | 2678 | BUG_ON(plug->magic != PLUG_MAGIC); |
2678 | 2679 | |
2679 | 2680 | if (list_empty(&plug->list)) |
2680 | 2681 | return; |
2681 | 2682 | |
2682 | - if (plug->should_sort) | |
2683 | - list_sort(NULL, &plug->list, plug_rq_cmp); | |
2683 | + list_splice_init(&plug->list, &list); | |
2684 | 2684 | |
2685 | + if (plug->should_sort) { | |
2686 | + list_sort(NULL, &list, plug_rq_cmp); | |
2687 | + plug->should_sort = 0; | |
2688 | + } | |
2689 | + | |
2685 | 2690 | q = NULL; |
2686 | 2691 | local_irq_save(flags); |
2687 | - while (!list_empty(&plug->list)) { | |
2688 | - rq = list_entry_rq(plug->list.next); | |
2692 | + while (!list_empty(&list)) { | |
2693 | + rq = list_entry_rq(list.next); | |
2689 | 2694 | list_del_init(&rq->queuelist); |
2690 | 2695 | BUG_ON(!(rq->cmd_flags & REQ_ON_PLUG)); |
2691 | 2696 | BUG_ON(!rq->q); |
... | ... | @@ -2713,7 +2718,6 @@ |
2713 | 2718 | spin_unlock(q->queue_lock); |
2714 | 2719 | } |
2715 | 2720 | |
2716 | - BUG_ON(!list_empty(&plug->list)); | |
2717 | 2721 | local_irq_restore(flags); |
2718 | 2722 | } |
2719 | 2723 |