linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix
@ 2020-03-21  9:45 Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 1/4] block, bfq: move forward the getting of an extra ref in bfq_bfqq_move Paolo Valente
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Paolo Valente @ 2020-03-21  9:45 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, linux-kernel, bfq-iosched, oleksandr, rasibley,
	vkabatov, xzhou, jstancek, Paolo Valente

Hi,
this is a series of four fixes. The first patch fixes the issue
reported in [1], while the following patches fix a few extra issues
found while testing the first fix.

Thanks,
Paolo

[1] https://www.spinics.net/lists/linux-block/msg50629.html

Paolo Valente (4):
  block, bfq: move forward the getting of an extra ref in bfq_bfqq_move
  block, bfq: turn put_queue into release_process_ref in
    __bfq_bic_change_cgroup
  block, bfq: make reparent_leaf_entity actually work only on leaf
    entities
  block, bfq: invoke flush_idle_tree after reparent_active_queues in
    pd_offline

 block/bfq-cgroup.c  | 87 +++++++++++++++++++++++++++------------------
 block/bfq-iosched.c |  2 --
 block/bfq-iosched.h |  1 +
 3 files changed, 53 insertions(+), 37 deletions(-)

--
2.20.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH BUGFIX 1/4] block, bfq: move forward the getting of an extra ref in bfq_bfqq_move
  2020-03-21  9:45 [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Paolo Valente
@ 2020-03-21  9:45 ` Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 2/4] block, bfq: turn put_queue into release_process_ref in __bfq_bic_change_cgroup Paolo Valente
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Paolo Valente @ 2020-03-21  9:45 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, linux-kernel, bfq-iosched, oleksandr, rasibley,
	vkabatov, xzhou, jstancek, Paolo Valente, cki-project

Commit ecedd3d7e199 ("block, bfq: get extra ref to prevent a queue
from being freed during a group move") gets an extra reference to a
bfq_queue before possibly deactivating it (temporarily), in
bfq_bfqq_move(). This prevents the bfq_queue from disappearing before
being reactivated in its new group.

Yet, the bfq_queue may also be expired (i.e., its service may be
stopped) before the bfq_queue is deactivated. And also an expiration
may lead to a premature freeing. This commit fixes this issue by
simply moving forward the getting of the extra reference already
introduced by commit ecedd3d7e199 ("block, bfq: get extra ref to
prevent a queue from being freed during a group move").

Reported-by: cki-project@redhat.com
Tested-by: cki-project@redhat.com
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
---
 block/bfq-cgroup.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index f0ff6654af28..9d963ed518d1 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -642,6 +642,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 {
 	struct bfq_entity *entity = &bfqq->entity;
 
+	/*
+	 * Get extra reference to prevent bfqq from being freed in
+	 * next possible expire or deactivate.
+	 */
+	bfqq->ref++;
+
 	/* If bfqq is empty, then bfq_bfqq_expire also invokes
 	 * bfq_del_bfqq_busy, thereby removing bfqq and its entity
 	 * from data structures related to current group. Otherwise we
@@ -652,12 +658,6 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 		bfq_bfqq_expire(bfqd, bfqd->in_service_queue,
 				false, BFQQE_PREEMPTED);
 
-	/*
-	 * get extra reference to prevent bfqq from being freed in
-	 * next possible deactivate
-	 */
-	bfqq->ref++;
-
 	if (bfq_bfqq_busy(bfqq))
 		bfq_deactivate_bfqq(bfqd, bfqq, false, false);
 	else if (entity->on_st_or_in_serv)
@@ -677,7 +677,7 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 
 	if (!bfqd->in_service_queue && !bfqd->rq_in_driver)
 		bfq_schedule_dispatch(bfqd);
-	/* release extra ref taken above */
+	/* release extra ref taken above, bfqq may happen to be freed now */
 	bfq_put_queue(bfqq);
 }
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BUGFIX 2/4] block, bfq: turn put_queue into release_process_ref in __bfq_bic_change_cgroup
  2020-03-21  9:45 [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 1/4] block, bfq: move forward the getting of an extra ref in bfq_bfqq_move Paolo Valente
@ 2020-03-21  9:45 ` Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 3/4] block, bfq: make reparent_leaf_entity actually work only on leaf entities Paolo Valente
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Paolo Valente @ 2020-03-21  9:45 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, linux-kernel, bfq-iosched, oleksandr, rasibley,
	vkabatov, xzhou, jstancek, Paolo Valente, cki-project

A bfq_put_queue() may be invoked in __bfq_bic_change_cgroup(). The
goal of this put is to release a process reference to a bfq_queue. But
process-reference releases may trigger also some extra operation, and,
to this goal, are handled through bfq_release_process_ref(). So, turn
the invocation of bfq_put_queue() into an invocation of
bfq_release_process_ref().

Tested-by: cki-project@redhat.com
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
---
 block/bfq-cgroup.c  | 5 +----
 block/bfq-iosched.c | 2 --
 block/bfq-iosched.h | 1 +
 3 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index 9d963ed518d1..72c6151ace96 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -714,10 +714,7 @@ static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
 
 		if (entity->sched_data != &bfqg->sched_data) {
 			bic_set_bfqq(bic, NULL, 0);
-			bfq_log_bfqq(bfqd, async_bfqq,
-				     "bic_change_group: %p %d",
-				     async_bfqq, async_bfqq->ref);
-			bfq_put_queue(async_bfqq);
+			bfq_release_process_ref(bfqd, async_bfqq);
 		}
 	}
 
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 8c436abfaf14..d9c1899cf05b 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -2716,8 +2716,6 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
 	}
 }
 
-
-static
 void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 {
 	/*
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
index d1233af9c684..cd224aaf9f52 100644
--- a/block/bfq-iosched.h
+++ b/block/bfq-iosched.h
@@ -955,6 +955,7 @@ 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_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);
 void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BUGFIX 3/4] block, bfq: make reparent_leaf_entity actually work only on leaf entities
  2020-03-21  9:45 [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 1/4] block, bfq: move forward the getting of an extra ref in bfq_bfqq_move Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 2/4] block, bfq: turn put_queue into release_process_ref in __bfq_bic_change_cgroup Paolo Valente
@ 2020-03-21  9:45 ` Paolo Valente
  2020-03-21  9:45 ` [PATCH BUGFIX 4/4] block, bfq: invoke flush_idle_tree after reparent_active_queues in pd_offline Paolo Valente
  2020-03-21 20:31 ` [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Jens Axboe
  4 siblings, 0 replies; 6+ messages in thread
From: Paolo Valente @ 2020-03-21  9:45 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, linux-kernel, bfq-iosched, oleksandr, rasibley,
	vkabatov, xzhou, jstancek, Paolo Valente, cki-project

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>
---
 block/bfq-cgroup.c | 48 ++++++++++++++++++++++++++++++----------------
 1 file changed, 31 insertions(+), 17 deletions(-)

diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index 72c6151ace96..efb89db7ba24 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -815,39 +815,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;
-
-	if (!RB_EMPTY_ROOT(&st->active))
-		entity = bfq_entity_of(rb_first(active));
+	struct bfq_entity *entity;
 
-	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);
 }
 
 /**
@@ -898,7 +912,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);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BUGFIX 4/4] block, bfq: invoke flush_idle_tree after reparent_active_queues in pd_offline
  2020-03-21  9:45 [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Paolo Valente
                   ` (2 preceding siblings ...)
  2020-03-21  9:45 ` [PATCH BUGFIX 3/4] block, bfq: make reparent_leaf_entity actually work only on leaf entities Paolo Valente
@ 2020-03-21  9:45 ` Paolo Valente
  2020-03-21 20:31 ` [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Jens Axboe
  4 siblings, 0 replies; 6+ messages in thread
From: Paolo Valente @ 2020-03-21  9:45 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, linux-kernel, bfq-iosched, oleksandr, rasibley,
	vkabatov, xzhou, jstancek, Paolo Valente, cki-project

In bfq_pd_offline(), the function bfq_flush_idle_tree() is invoked to
flush the rb tree that contains all idle entities belonging to the pd
(cgroup) being destroyed. In particular, bfq_flush_idle_tree() is
invoked before bfq_reparent_active_queues(). Yet the latter may happen
to add some entities to the idle tree. It happens if, in some of the
calls to bfq_bfqq_move() performed by bfq_reparent_active_queues(),
the queue to move is empty and gets expired.

This commit simply reverses the invocation order between
bfq_flush_idle_tree() and bfq_reparent_active_queues().

Tested-by: cki-project@redhat.com
Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
---
 block/bfq-cgroup.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index efb89db7ba24..68882b9b8f11 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -893,13 +893,6 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
 	for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) {
 		st = bfqg->sched_data.service_tree + i;
 
-		/*
-		 * The idle tree may still contain bfq_queues belonging
-		 * to exited task because they never migrated to a different
-		 * cgroup from the one being destroyed now.
-		 */
-		bfq_flush_idle_tree(st);
-
 		/*
 		 * It may happen that some queues are still active
 		 * (busy) upon group destruction (if the corresponding
@@ -913,6 +906,19 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
 		 * scheduler has taken no reference.
 		 */
 		bfq_reparent_active_queues(bfqd, bfqg, st, i);
+
+		/*
+		 * The idle tree may still contain bfq_queues
+		 * belonging to exited task because they never
+		 * migrated to a different cgroup from the one being
+		 * destroyed now. In addition, even
+		 * bfq_reparent_active_queues() may happen to add some
+		 * entities to the idle tree. It happens if, in some
+		 * of the calls to bfq_bfqq_move() performed by
+		 * bfq_reparent_active_queues(), the queue to move is
+		 * empty and gets expired.
+		 */
+		bfq_flush_idle_tree(st);
 	}
 
 	__bfq_deactivate_entity(entity, false);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix
  2020-03-21  9:45 [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Paolo Valente
                   ` (3 preceding siblings ...)
  2020-03-21  9:45 ` [PATCH BUGFIX 4/4] block, bfq: invoke flush_idle_tree after reparent_active_queues in pd_offline Paolo Valente
@ 2020-03-21 20:31 ` Jens Axboe
  4 siblings, 0 replies; 6+ messages in thread
From: Jens Axboe @ 2020-03-21 20:31 UTC (permalink / raw)
  To: Paolo Valente
  Cc: linux-block, linux-kernel, bfq-iosched, oleksandr, rasibley,
	vkabatov, xzhou, jstancek

On 3/21/20 3:45 AM, Paolo Valente wrote:
> Hi,
> this is a series of four fixes. The first patch fixes the issue
> reported in [1], while the following patches fix a few extra issues
> found while testing the first fix.

Applied for 5.7, thanks.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-03-21 20:31 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-21  9:45 [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Paolo Valente
2020-03-21  9:45 ` [PATCH BUGFIX 1/4] block, bfq: move forward the getting of an extra ref in bfq_bfqq_move Paolo Valente
2020-03-21  9:45 ` [PATCH BUGFIX 2/4] block, bfq: turn put_queue into release_process_ref in __bfq_bic_change_cgroup Paolo Valente
2020-03-21  9:45 ` [PATCH BUGFIX 3/4] block, bfq: make reparent_leaf_entity actually work only on leaf entities Paolo Valente
2020-03-21  9:45 ` [PATCH BUGFIX 4/4] block, bfq: invoke flush_idle_tree after reparent_active_queues in pd_offline Paolo Valente
2020-03-21 20:31 ` [PATCH BUGFIX 0/4] block, bfq: series of cgroups-related fix Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).