block, bfq: make reparent_leaf_entity actually work only on leaf entities
commit 576682fa52cbd95deb3773449566274f206acc58 upstream. bfq_reparent_leaf_entity() reparents the input leaf entity (a leaf entity represents just a bfq_queue in an entity tree). Yet, the input entity is guaranteed to always be a leaf entity only in two-level entity trees. In this respect, because of the error fixed by commit 14afc5936197 ("block, bfq: fix overwrite of bfq_group pointer in bfq_find_set_group()"), all (wrongly collapsed) entity trees happened to actually have only two levels. After the latter commit, this does not hold any longer. This commit fixes this problem by modifying bfq_reparent_leaf_entity(), so that it searches an active leaf entity down the path that stems from the input entity. Such a leaf entity is guaranteed to exist when bfq_reparent_leaf_entity() is invoked. Tested-by: cki-project@redhat.com Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
ad749ca022
commit
839b7cd1d8
@ -798,39 +798,53 @@ static void bfq_flush_idle_tree(struct bfq_service_tree *st)
|
||||
/**
|
||||
* bfq_reparent_leaf_entity - move leaf entity to the root_group.
|
||||
* @bfqd: the device data structure with the root group.
|
||||
* @entity: the entity to move.
|
||||
* @entity: the entity to move, if entity is a leaf; or the parent entity
|
||||
* of an active leaf entity to move, if entity is not a leaf.
|
||||
*/
|
||||
static void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
|
||||
struct bfq_entity *entity)
|
||||
struct bfq_entity *entity,
|
||||
int ioprio_class)
|
||||
{
|
||||
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
|
||||
struct bfq_queue *bfqq;
|
||||
struct bfq_entity *child_entity = entity;
|
||||
|
||||
while (child_entity->my_sched_data) { /* leaf not reached yet */
|
||||
struct bfq_sched_data *child_sd = child_entity->my_sched_data;
|
||||
struct bfq_service_tree *child_st = child_sd->service_tree +
|
||||
ioprio_class;
|
||||
struct rb_root *child_active = &child_st->active;
|
||||
|
||||
child_entity = bfq_entity_of(rb_first(child_active));
|
||||
|
||||
if (!child_entity)
|
||||
child_entity = child_sd->in_service_entity;
|
||||
}
|
||||
|
||||
bfqq = bfq_entity_to_bfqq(child_entity);
|
||||
bfq_bfqq_move(bfqd, bfqq, bfqd->root_group);
|
||||
}
|
||||
|
||||
/**
|
||||
* bfq_reparent_active_entities - move to the root group all active
|
||||
* entities.
|
||||
* bfq_reparent_active_queues - move to the root group all active queues.
|
||||
* @bfqd: the device data structure with the root group.
|
||||
* @bfqg: the group to move from.
|
||||
* @st: the service tree with the entities.
|
||||
* @st: the service tree to start the search from.
|
||||
*/
|
||||
static void bfq_reparent_active_entities(struct bfq_data *bfqd,
|
||||
struct bfq_group *bfqg,
|
||||
struct bfq_service_tree *st)
|
||||
static void bfq_reparent_active_queues(struct bfq_data *bfqd,
|
||||
struct bfq_group *bfqg,
|
||||
struct bfq_service_tree *st,
|
||||
int ioprio_class)
|
||||
{
|
||||
struct rb_root *active = &st->active;
|
||||
struct bfq_entity *entity = NULL;
|
||||
struct bfq_entity *entity;
|
||||
|
||||
if (!RB_EMPTY_ROOT(&st->active))
|
||||
entity = bfq_entity_of(rb_first(active));
|
||||
|
||||
for (; entity ; entity = bfq_entity_of(rb_first(active)))
|
||||
bfq_reparent_leaf_entity(bfqd, entity);
|
||||
while ((entity = bfq_entity_of(rb_first(active))))
|
||||
bfq_reparent_leaf_entity(bfqd, entity, ioprio_class);
|
||||
|
||||
if (bfqg->sched_data.in_service_entity)
|
||||
bfq_reparent_leaf_entity(bfqd,
|
||||
bfqg->sched_data.in_service_entity);
|
||||
bfqg->sched_data.in_service_entity,
|
||||
ioprio_class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -881,7 +895,7 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
|
||||
* There is no need to put the sync queues, as the
|
||||
* scheduler has taken no reference.
|
||||
*/
|
||||
bfq_reparent_active_entities(bfqd, bfqg, st);
|
||||
bfq_reparent_active_queues(bfqd, bfqg, st, i);
|
||||
}
|
||||
|
||||
__bfq_deactivate_entity(entity, false);
|
||||
|
Loading…
Reference in New Issue
Block a user