All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.