lkml.org 
[lkml]   [2019]   [Mar]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.0 199/262] block, bfq: fix queue removal from weights tree
    Date
    From: Paolo Valente <paolo.valente@linaro.org>

    [ Upstream commit 9dee8b3b057e1da26f85f1842f2aaf3bb200fb94 ]

    bfq maintains an ordered list, through a red-black tree, of unique
    weights of active bfq_queues. This list is used to detect whether there
    are active queues with differentiated weights. The weight of a queue is
    removed from the list when both the following two conditions become
    true:

    (1) the bfq_queue is flagged as inactive
    (2) the has no in-flight request any longer;

    Unfortunately, in the rare cases where condition (2) becomes true before
    condition (1), the removal fails, because the function to remove the
    weight of the queue (bfq_weights_tree_remove) is rightly invoked in the
    path that deactivates the bfq_queue, but mistakenly invoked *before* the
    function that actually performs the deactivation (bfq_deactivate_bfqq).

    This commits moves the invocation of bfq_weights_tree_remove for
    condition (1) to after bfq_deactivate_bfqq. As a consequence of this
    move, it is necessary to add a further reference to the queue when the
    weight of a queue is added, because the queue might otherwise be freed
    before bfq_weights_tree_remove is invoked. This commit adds this
    reference and makes all related modifications.

    Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    block/bfq-iosched.c | 17 +++++++++++++----
    block/bfq-wf2q.c | 6 +++---
    2 files changed, 16 insertions(+), 7 deletions(-)

    diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
    index f010810c095f..e5ed28629271 100644
    --- a/block/bfq-iosched.c
    +++ b/block/bfq-iosched.c
    @@ -747,6 +747,7 @@ void bfq_weights_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq,

    inc_counter:
    bfqq->weight_counter->num_active++;
    + bfqq->ref++;
    }

    /*
    @@ -771,6 +772,7 @@ void __bfq_weights_tree_remove(struct bfq_data *bfqd,

    reset_entity_pointer:
    bfqq->weight_counter = NULL;
    + bfq_put_queue(bfqq);
    }

    /*
    @@ -782,9 +784,6 @@ void bfq_weights_tree_remove(struct bfq_data *bfqd,
    {
    struct bfq_entity *entity = bfqq->entity.parent;

    - __bfq_weights_tree_remove(bfqd, bfqq,
    - &bfqd->queue_weights_tree);
    -
    for_each_entity(entity) {
    struct bfq_sched_data *sd = entity->my_sched_data;

    @@ -818,6 +817,15 @@ void bfq_weights_tree_remove(struct bfq_data *bfqd,
    bfqd->num_groups_with_pending_reqs--;
    }
    }
    +
    + /*
    + * Next function is invoked last, because it causes bfqq to be
    + * freed if the following holds: bfqq is not in service and
    + * has no dispatched request. DO NOT use bfqq after the next
    + * function invocation.
    + */
    + __bfq_weights_tree_remove(bfqd, bfqq,
    + &bfqd->queue_weights_tree);
    }

    /*
    @@ -1011,7 +1019,8 @@ bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,

    static int bfqq_process_refs(struct bfq_queue *bfqq)
    {
    - return bfqq->ref - bfqq->allocated - bfqq->entity.on_st;
    + return bfqq->ref - bfqq->allocated - bfqq->entity.on_st -
    + (bfqq->weight_counter != NULL);
    }

    /* Empty burst list and add just bfqq (see comments on bfq_handle_burst) */
    diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
    index 72adbbe975d5..4aab1a8191f0 100644
    --- a/block/bfq-wf2q.c
    +++ b/block/bfq-wf2q.c
    @@ -1667,15 +1667,15 @@ void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq,

    bfqd->busy_queues--;

    - if (!bfqq->dispatched)
    - bfq_weights_tree_remove(bfqd, bfqq);
    -
    if (bfqq->wr_coeff > 1)
    bfqd->wr_busy_queues--;

    bfqg_stats_update_dequeue(bfqq_group(bfqq));

    bfq_deactivate_bfqq(bfqd, bfqq, true, expiration);
    +
    + if (!bfqq->dispatched)
    + bfq_weights_tree_remove(bfqd, bfqq);
    }

    /*
    --
    2.19.1
    \
     
     \ /
      Last update: 2019-03-27 20:18    [W:4.227 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site