| From ba2df233243e06166ea30c4eee1b1167b9e373f2 Mon Sep 17 00:00:00 2001 |
| From: Paolo Valente <paolo.valente@linaro.org> |
| Date: Mon, 3 Feb 2020 11:40:59 +0100 |
| Subject: [PATCH] block, bfq: get a ref to a group when adding it to a service |
| tree |
| |
| commit db37a34c563bf4692b36990ae89005c031385e52 upstream. |
| |
| BFQ schedules generic entities, which may represent either bfq_queues |
| or groups of bfq_queues. When an entity is inserted into a service |
| tree, a reference must be taken, to make sure that the entity does not |
| disappear while still referred in the tree. Unfortunately, such a |
| reference is mistakenly taken only if the entity represents a |
| bfq_queue. This commit takes a reference also in case the entity |
| represents a group. |
| |
| Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> |
| Tested-by: Chris Evich <cevich@redhat.com> |
| Signed-off-by: Paolo Valente <paolo.valente@linaro.org> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c |
| index ce7377917b8c..b1c435208a47 100644 |
| --- a/block/bfq-cgroup.c |
| +++ b/block/bfq-cgroup.c |
| @@ -256,7 +256,7 @@ static void bfqg_put(struct bfq_group *bfqg) |
| kfree(bfqg); |
| } |
| |
| -static void bfqg_and_blkg_get(struct bfq_group *bfqg) |
| +void bfqg_and_blkg_get(struct bfq_group *bfqg) |
| { |
| /* see comments in bfq_bic_update_cgroup for why refcounting bfqg */ |
| bfqg_get(bfqg); |
| diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h |
| index c2faa77824f8..eb3ac95fdbf9 100644 |
| --- a/block/bfq-iosched.h |
| +++ b/block/bfq-iosched.h |
| @@ -947,6 +947,7 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, |
| struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg); |
| struct bfq_group *bfqq_group(struct bfq_queue *bfqq); |
| struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node); |
| +void bfqg_and_blkg_get(struct bfq_group *bfqg); |
| void bfqg_and_blkg_put(struct bfq_group *bfqg); |
| |
| #ifdef CONFIG_BFQ_GROUP_IOSCHED |
| diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c |
| index c9ba225081ce..3be22faa4c01 100644 |
| --- a/block/bfq-wf2q.c |
| +++ b/block/bfq-wf2q.c |
| @@ -536,7 +536,9 @@ static void bfq_get_entity(struct bfq_entity *entity) |
| bfqq->ref++; |
| bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", |
| bfqq, bfqq->ref); |
| - } |
| + } else |
| + bfqg_and_blkg_get(container_of(entity, struct bfq_group, |
| + entity)); |
| } |
| |
| /** |
| @@ -650,8 +652,14 @@ static void bfq_forget_entity(struct bfq_service_tree *st, |
| |
| entity->on_st = false; |
| st->wsum -= entity->weight; |
| - if (bfqq && !is_in_service) |
| + if (is_in_service) |
| + return; |
| + |
| + if (bfqq) |
| bfq_put_queue(bfqq); |
| + else |
| + bfqg_and_blkg_put(container_of(entity, struct bfq_group, |
| + entity)); |
| } |
| |
| /** |
| -- |
| 2.7.4 |
| |