lkml.org 
[lkml]   [2022]   [Jun]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 219/411] bfq: Split shared queues on move between cgroups
    Date
    From: Jan Kara <jack@suse.cz>

    commit 3bc5e683c67d94bd839a1da2e796c15847b51b69 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: stable@vger.kernel.org
    Fixes: e21b7a0b9887 ("block, bfq: add full hierarchical scheduling and cgroups support")
    Tested-by: "yukuai (C)" <yukuai3@huawei.com>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Reviewed-by: Christoph Hellwig <hch@lst.de>
    Link: https://lore.kernel.org/r/20220401102752.8599-3-jack@suse.cz
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    block/bfq-cgroup.c | 36 +++++++++++++++++++++++++++++++++---
    block/bfq-iosched.c | 2 +-
    block/bfq-iosched.h | 1 +
    3 files changed, 35 insertions(+), 4 deletions(-)

    --- a/block/bfq-cgroup.c
    +++ b/block/bfq-cgroup.c
    @@ -708,9 +708,39 @@ static struct bfq_group *__bfq_bic_chang
    }

    if (sync_bfqq) {
    - entity = &sync_bfqq->entity;
    - if (entity->sched_data != &bfqg->sched_data)
    - bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
    + if (!sync_bfqq->new_bfqq && !bfq_bfqq_coop(sync_bfqq)) {
    + /* We are the only user of this bfqq, just move it */
    + if (sync_bfqq->entity.sched_data != &bfqg->sched_data)
    + bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
    + } else {
    + struct bfq_queue *bfqq;
    +
    + /*
    + * The queue was merged to a different queue. Check
    + * that the merge chain still belongs to the same
    + * cgroup.
    + */
    + for (bfqq = sync_bfqq; bfqq; bfqq = bfqq->new_bfqq)
    + if (bfqq->entity.sched_data !=
    + &bfqg->sched_data)
    + break;
    + if (bfqq) {
    + /*
    + * Some queue changed cgroup so the merge is
    + * not valid anymore. We cannot easily just
    + * cancel the merge (by clearing new_bfqq) as
    + * there may be other processes using this
    + * queue and holding refs to all queues below
    + * sync_bfqq->new_bfqq. Similarly if the merge
    + * already happened, we need to detach from
    + * bfqq now so that we cannot merge bio to a
    + * request from the old cgroup.
    + */
    + bfq_put_cooperator(sync_bfqq);
    + bfq_release_process_ref(bfqd, sync_bfqq);
    + bic_set_bfqq(bic, NULL, 1);
    + }
    + }
    }

    return bfqg;
    --- a/block/bfq-iosched.c
    +++ b/block/bfq-iosched.c
    @@ -4914,7 +4914,7 @@ void bfq_put_queue(struct bfq_queue *bfq
    bfqg_and_blkg_put(bfqg);
    }

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

    --- a/block/bfq-iosched.h
    +++ b/block/bfq-iosched.h
    @@ -949,6 +949,7 @@ void bfq_weights_tree_remove(struct bfq_
    void bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
    bool compensate, enum bfqq_expiration reason);
    void bfq_put_queue(struct bfq_queue *bfqq);
    +void bfq_put_cooperator(struct bfq_queue *bfqq);
    void bfq_end_wr_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
    void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq);
    void bfq_schedule_dispatch(struct bfq_data *bfqd);

    \
     
     \ /
      Last update: 2022-06-13 13:28    [W:5.272 / U:0.704 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site