Skip to content

Commit 3f758e8

Browse files
Algodev-githubaxboe
authored andcommitted
block, bfq: move update of waker and woken list to queue freeing
Since commit 13a857a ("block, bfq: detect wakers and unconditionally inject their I/O"), every bfq_queue has a pointer to a waker bfq_queue and a list of the bfq_queues it may wake. In this respect, when a bfq_queue, say Q, remains with no I/O source attached to it, Q cannot be woken by any other bfq_queue, and cannot wake any other bfq_queue. Then Q must be removed from the woken list of its possible waker bfq_queue, and all bfq_queues in the woken list of Q must stop having a waker bfq_queue. Q remains with no I/O source in two cases: when the last process associated with Q exits or when such a process gets associated with a different bfq_queue. Unfortunately, commit 13a857a ("block, bfq: detect wakers and unconditionally inject their I/O") performed the above updates only in the first case. This commit fixes this bug by moving these updates to when Q gets freed. This is a simple and safe way to handle all cases, as both the above events, process exit and re-association, lead to Q being freed soon, and because dangling references would come out only after Q gets freed (if no update were performed). Fixes: 13a857a ("block, bfq: detect wakers and unconditionally inject their I/O") Reported-by: Douglas Anderson <[email protected]> Tested-by: Douglas Anderson <[email protected]> Signed-off-by: Paolo Valente <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 08d383a commit 3f758e8

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

block/bfq-iosched.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4765,6 +4765,8 @@ static struct request *bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
47654765
*/
47664766
void bfq_put_queue(struct bfq_queue *bfqq)
47674767
{
4768+
struct bfq_queue *item;
4769+
struct hlist_node *n;
47684770
#ifdef CONFIG_BFQ_GROUP_IOSCHED
47694771
struct bfq_group *bfqg = bfqq_group(bfqq);
47704772
#endif
@@ -4809,6 +4811,33 @@ void bfq_put_queue(struct bfq_queue *bfqq)
48094811
bfqq->bfqd->burst_size--;
48104812
}
48114813

4814+
/*
4815+
* bfqq does not exist any longer, so it cannot be woken by
4816+
* any other queue, and cannot wake any other queue. Then bfqq
4817+
* must be removed from the woken list of its possible waker
4818+
* queue, and all queues in the woken list of bfqq must stop
4819+
* having a waker queue. Strictly speaking, these updates
4820+
* should be performed when bfqq remains with no I/O source
4821+
* attached to it, which happens before bfqq gets freed. In
4822+
* particular, this happens when the last process associated
4823+
* with bfqq exits or gets associated with a different
4824+
* queue. However, both events lead to bfqq being freed soon,
4825+
* and dangling references would come out only after bfqq gets
4826+
* freed. So these updates are done here, as a simple and safe
4827+
* way to handle all cases.
4828+
*/
4829+
/* remove bfqq from woken list */
4830+
if (!hlist_unhashed(&bfqq->woken_list_node))
4831+
hlist_del_init(&bfqq->woken_list_node);
4832+
4833+
/* reset waker for all queues in woken list */
4834+
hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
4835+
woken_list_node) {
4836+
item->waker_bfqq = NULL;
4837+
bfq_clear_bfqq_has_waker(item);
4838+
hlist_del_init(&item->woken_list_node);
4839+
}
4840+
48124841
if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
48134842
bfqq->bfqd->last_completed_rq_bfqq = NULL;
48144843

@@ -4839,9 +4868,6 @@ static void bfq_put_cooperator(struct bfq_queue *bfqq)
48394868

48404869
static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
48414870
{
4842-
struct bfq_queue *item;
4843-
struct hlist_node *n;
4844-
48454871
if (bfqq == bfqd->in_service_queue) {
48464872
__bfq_bfqq_expire(bfqd, bfqq, BFQQE_BUDGET_TIMEOUT);
48474873
bfq_schedule_dispatch(bfqd);
@@ -4851,18 +4877,6 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
48514877

48524878
bfq_put_cooperator(bfqq);
48534879

4854-
/* remove bfqq from woken list */
4855-
if (!hlist_unhashed(&bfqq->woken_list_node))
4856-
hlist_del_init(&bfqq->woken_list_node);
4857-
4858-
/* reset waker for all queues in woken list */
4859-
hlist_for_each_entry_safe(item, n, &bfqq->woken_list,
4860-
woken_list_node) {
4861-
item->waker_bfqq = NULL;
4862-
bfq_clear_bfqq_has_waker(item);
4863-
hlist_del_init(&item->woken_list_node);
4864-
}
4865-
48664880
bfq_put_queue(bfqq); /* release process reference */
48674881
}
48684882

0 commit comments

Comments
 (0)