Skip to content

Commit 4dfc12f

Browse files
jankaragregkh
authored andcommitted
bfq: Split shared queues on move between cgroups
commit 3bc5e68 upstream. When bfqq is shared by multiple processes it can happen that one of the processes gets moved to a different cgroup (or just starts submitting IO for different cgroup). In case that happens we need to split the merged bfqq as otherwise we will have IO for multiple cgroups in one bfqq and we will just account IO time to wrong entities etc. Similarly if the bfqq is scheduled to merge with another bfqq but the merge didn't happen yet, cancel the merge as it need not be valid anymore. CC: [email protected] Fixes: e21b7a0 ("block, bfq: add full hierarchical scheduling and cgroups support") Tested-by: "yukuai (C)" <[email protected]> Signed-off-by: Jan Kara <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c072cab commit 4dfc12f

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

block/bfq-cgroup.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,39 @@ static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
725725
}
726726

727727
if (sync_bfqq) {
728-
entity = &sync_bfqq->entity;
729-
if (entity->sched_data != &bfqg->sched_data)
730-
bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
728+
if (!sync_bfqq->new_bfqq && !bfq_bfqq_coop(sync_bfqq)) {
729+
/* We are the only user of this bfqq, just move it */
730+
if (sync_bfqq->entity.sched_data != &bfqg->sched_data)
731+
bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
732+
} else {
733+
struct bfq_queue *bfqq;
734+
735+
/*
736+
* The queue was merged to a different queue. Check
737+
* that the merge chain still belongs to the same
738+
* cgroup.
739+
*/
740+
for (bfqq = sync_bfqq; bfqq; bfqq = bfqq->new_bfqq)
741+
if (bfqq->entity.sched_data !=
742+
&bfqg->sched_data)
743+
break;
744+
if (bfqq) {
745+
/*
746+
* Some queue changed cgroup so the merge is
747+
* not valid anymore. We cannot easily just
748+
* cancel the merge (by clearing new_bfqq) as
749+
* there may be other processes using this
750+
* queue and holding refs to all queues below
751+
* sync_bfqq->new_bfqq. Similarly if the merge
752+
* already happened, we need to detach from
753+
* bfqq now so that we cannot merge bio to a
754+
* request from the old cgroup.
755+
*/
756+
bfq_put_cooperator(sync_bfqq);
757+
bfq_release_process_ref(bfqd, sync_bfqq);
758+
bic_set_bfqq(bic, NULL, 1);
759+
}
760+
}
731761
}
732762

733763
return bfqg;

block/bfq-iosched.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4917,7 +4917,7 @@ void bfq_put_queue(struct bfq_queue *bfqq)
49174917
bfqg_and_blkg_put(bfqg);
49184918
}
49194919

4920-
static void bfq_put_cooperator(struct bfq_queue *bfqq)
4920+
void bfq_put_cooperator(struct bfq_queue *bfqq)
49214921
{
49224922
struct bfq_queue *__bfqq, *next;
49234923

block/bfq-iosched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,7 @@ void bfq_weights_tree_remove(struct bfq_data *bfqd,
954954
void bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
955955
bool compensate, enum bfqq_expiration reason);
956956
void bfq_put_queue(struct bfq_queue *bfqq);
957+
void bfq_put_cooperator(struct bfq_queue *bfqq);
957958
void bfq_end_wr_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
958959
void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq);
959960
void bfq_schedule_dispatch(struct bfq_data *bfqd);

0 commit comments

Comments
 (0)