Jan Kara 996a1f
From cb5e5543e67afb6ee9670075531107884021da3f Mon Sep 17 00:00:00 2001
Jan Kara 996a1f
From: Jan Kara <jack@suse.cz>
Jan Kara 996a1f
Date: Fri, 4 Mar 2022 18:57:35 +0100
Jan Kara 996a1f
Subject: [PATCH 8/9] bfq: Get rid of __bio_blkcg() usage
Jan Kara 996a1f
References: bsc#1197926
Jan Kara 996a1f
Patch-mainline: submitted, in linux-block tree
Jan Kara 996a1f
Jan Kara 996a1f
BFQ usage of __bio_blkcg() is a relict from the past. Furthermore if bio
Jan Kara 996a1f
would not be associated with any blkcg, the usage of __bio_blkcg() in
Jan Kara 996a1f
BFQ is prone to races with the task being migrated between cgroups as
Jan Kara 996a1f
__bio_blkcg() calls at different places could return different blkcgs.
Jan Kara 996a1f
Jan Kara 996a1f
Convert BFQ to the new situation where bio->bi_blkg is initialized in
Jan Kara 996a1f
bio_set_dev() and thus practically always valid. This allows us to save
Jan Kara 996a1f
blkcg_gq lookup and noticeably simplify the code.
Jan Kara 996a1f
Jan Kara 996a1f
Cc: stable@vger.kernel.org
Jan Kara 996a1f
Fixes: 0fe061b9f03c ("blkcg: fix ref count issue with bio_blkcg() using task_css")
Jan Kara 996a1f
Tested-by: "yukuai (C)" <yukuai3@huawei.com>
Jan Kara 996a1f
Signed-off-by: Jan Kara <jack@suse.cz>
Jan Kara 996a1f
Jan Kara 996a1f
---
Jan Kara 996a1f
 block/bfq-cgroup.c  |   63 ++++++++++++++++++----------------------------------
Jan Kara 996a1f
 block/bfq-iosched.c |   10 --------
Jan Kara 996a1f
 block/bfq-iosched.h |    3 --
Jan Kara 996a1f
 3 files changed, 25 insertions(+), 51 deletions(-)
Jan Kara 996a1f
Jan Kara 996a1f
--- a/block/bfq-cgroup.c
Jan Kara 996a1f
+++ b/block/bfq-cgroup.c
Jan Kara 996a1f
@@ -582,27 +582,11 @@ static void bfq_group_set_parent(struct
Jan Kara 996a1f
 	entity->sched_data = &parent->sched_data;
Jan Kara 996a1f
 }
Jan Kara 996a1f
 
Jan Kara 996a1f
-static struct bfq_group *bfq_lookup_bfqg(struct bfq_data *bfqd,
Jan Kara 996a1f
-					 struct blkcg *blkcg)
Jan Kara 996a1f
+static void bfq_link_bfqg(struct bfq_data *bfqd, struct bfq_group *bfqg)
Jan Kara 996a1f
 {
Jan Kara 996a1f
-	struct blkcg_gq *blkg;
Jan Kara 996a1f
-
Jan Kara 996a1f
-	blkg = blkg_lookup(blkcg, bfqd->queue);
Jan Kara 996a1f
-	if (likely(blkg))
Jan Kara 996a1f
-		return blkg_to_bfqg(blkg);
Jan Kara 996a1f
-	return NULL;
Jan Kara 996a1f
-}
Jan Kara 996a1f
-
Jan Kara 996a1f
-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd,
Jan Kara 996a1f
-				     struct blkcg *blkcg)
Jan Kara 996a1f
-{
Jan Kara 996a1f
-	struct bfq_group *bfqg, *parent;
Jan Kara 996a1f
+	struct bfq_group *parent;
Jan Kara 996a1f
 	struct bfq_entity *entity;
Jan Kara 996a1f
 
Jan Kara 996a1f
-	bfqg = bfq_lookup_bfqg(bfqd, blkcg);
Jan Kara 996a1f
-	if (unlikely(!bfqg))
Jan Kara 996a1f
-		return NULL;
Jan Kara 996a1f
-
Jan Kara 996a1f
 	/*
Jan Kara 996a1f
 	 * Update chain of bfq_groups as we might be handling a leaf group
Jan Kara 996a1f
 	 * which, along with some of its relatives, has not been hooked yet
Jan Kara 996a1f
@@ -619,8 +603,15 @@ struct bfq_group *bfq_find_set_group(str
Jan Kara 996a1f
 			bfq_group_set_parent(curr_bfqg, parent);
Jan Kara 996a1f
 		}
Jan Kara 996a1f
 	}
Jan Kara 996a1f
+}
Jan Kara 996a1f
 
Jan Kara 996a1f
-	return bfqg;
Jan Kara 996a1f
+struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
Jan Kara 996a1f
+{
Jan Kara 996a1f
+	struct blkcg_gq *blkg = bio->bi_blkg;
Jan Kara 996a1f
+
Jan Kara 996a1f
+	if (!blkg)
Jan Kara 996a1f
+		return bfqd->root_group;
Jan Kara 996a1f
+	return blkg_to_bfqg(blkg);
Jan Kara 996a1f
 }
Jan Kara 996a1f
 
Jan Kara 996a1f
 /**
Jan Kara 996a1f
@@ -690,25 +681,15 @@ void bfq_bfqq_move(struct bfq_data *bfqd
Jan Kara 996a1f
  * Move bic to blkcg, assuming that bfqd->lock is held; which makes
Jan Kara 996a1f
  * sure that the reference to cgroup is valid across the call (see
Jan Kara 996a1f
  * comments in bfq_bic_update_cgroup on this issue)
Jan Kara 996a1f
- *
Jan Kara 996a1f
- * NOTE: an alternative approach might have been to store the current
Jan Kara 996a1f
- * cgroup in bfqq and getting a reference to it, reducing the lookup
Jan Kara 996a1f
- * time here, at the price of slightly more complex code.
Jan Kara 996a1f
  */
Jan Kara 996a1f
-static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
Jan Kara 996a1f
-						struct bfq_io_cq *bic,
Jan Kara 996a1f
-						struct blkcg *blkcg)
Jan Kara 996a1f
+static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
Jan Kara 996a1f
+				     struct bfq_io_cq *bic,
Jan Kara 996a1f
+				     struct bfq_group *bfqg)
Jan Kara 996a1f
 {
Jan Kara 996a1f
 	struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0);
Jan Kara 996a1f
 	struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1);
Jan Kara 996a1f
-	struct bfq_group *bfqg;
Jan Kara 996a1f
 	struct bfq_entity *entity;
Jan Kara 996a1f
 
Jan Kara 996a1f
-	bfqg = bfq_find_set_group(bfqd, blkcg);
Jan Kara 996a1f
-
Jan Kara 996a1f
-	if (unlikely(!bfqg))
Jan Kara 996a1f
-		bfqg = bfqd->root_group;
Jan Kara 996a1f
-
Jan Kara 996a1f
 	if (async_bfqq) {
Jan Kara 996a1f
 		entity = &async_bfqq->entity;
Jan Kara 996a1f
 
Jan Kara 996a1f
@@ -760,20 +741,24 @@ static struct bfq_group *__bfq_bic_chang
Jan Kara 996a1f
 void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
Jan Kara 996a1f
 {
Jan Kara 996a1f
 	struct bfq_data *bfqd = bic_to_bfqd(bic);
Jan Kara 996a1f
-	struct bfq_group *bfqg = NULL;
Jan Kara 996a1f
+	struct bfq_group *bfqg = bfq_bio_bfqg(bfqd, bio);
Jan Kara 996a1f
 	uint64_t serial_nr;
Jan Kara 996a1f
 
Jan Kara 996a1f
-	rcu_read_lock();
Jan Kara 996a1f
-	serial_nr = __bio_blkcg(bio)->css.serial_nr;
Jan Kara 996a1f
+	serial_nr = bfqg_to_blkg(bfqg)->blkcg->css.serial_nr;
Jan Kara 996a1f
 
Jan Kara 996a1f
 	/*
Jan Kara 996a1f
 	 * Check whether blkcg has changed.  The condition may trigger
Jan Kara 996a1f
 	 * spuriously on a newly created cic but there's no harm.
Jan Kara 996a1f
 	 */
Jan Kara 996a1f
 	if (unlikely(!bfqd) || likely(bic->blkcg_serial_nr == serial_nr))
Jan Kara 996a1f
-		goto out;
Jan Kara 996a1f
+		return;
Jan Kara 996a1f
 
Jan Kara 996a1f
-	bfqg = __bfq_bic_change_cgroup(bfqd, bic, __bio_blkcg(bio));
Jan Kara 996a1f
+	/*
Jan Kara 996a1f
+	 * New cgroup for this process. Make sure it is linked to bfq internal
Jan Kara 996a1f
+	 * cgroup hierarchy.
Jan Kara 996a1f
+	 */
Jan Kara 996a1f
+	bfq_link_bfqg(bfqd, bfqg);
Jan Kara 996a1f
+	__bfq_bic_change_cgroup(bfqd, bic, bfqg);
Jan Kara 996a1f
 	/*
Jan Kara 996a1f
 	 * Update blkg_path for bfq_log_* functions. We cache this
Jan Kara 996a1f
 	 * path, and update it here, for the following
Jan Kara 996a1f
@@ -826,8 +811,6 @@ void bfq_bic_update_cgroup(struct bfq_io
Jan Kara 996a1f
 	 */
Jan Kara 996a1f
 	blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path));
Jan Kara 996a1f
 	bic->blkcg_serial_nr = serial_nr;
Jan Kara 996a1f
-out:
Jan Kara 996a1f
-	rcu_read_unlock();
Jan Kara 996a1f
 }
Jan Kara 996a1f
 
Jan Kara 996a1f
 /**
Jan Kara 996a1f
@@ -1445,7 +1428,7 @@ void bfq_end_wr_async(struct bfq_data *b
Jan Kara 996a1f
 	bfq_end_wr_async_queues(bfqd, bfqd->root_group);
Jan Kara 996a1f
 }
Jan Kara 996a1f
 
Jan Kara 996a1f
-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, struct blkcg *blkcg)
Jan Kara 996a1f
+struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
Jan Kara 996a1f
 {
Jan Kara 996a1f
 	return bfqd->root_group;
Jan Kara 996a1f
 }
Jan Kara 996a1f
--- a/block/bfq-iosched.c
Jan Kara 996a1f
+++ b/block/bfq-iosched.c
Jan Kara 996a1f
@@ -5267,14 +5267,7 @@ static struct bfq_queue *bfq_get_queue(s
Jan Kara 996a1f
 	struct bfq_queue *bfqq;
Jan Kara 996a1f
 	struct bfq_group *bfqg;
Jan Kara 996a1f
 
Jan Kara 996a1f
-	rcu_read_lock();
Jan Kara 996a1f
-
Jan Kara 996a1f
-	bfqg = bfq_find_set_group(bfqd, __bio_blkcg(bio));
Jan Kara 996a1f
-	if (!bfqg) {
Jan Kara 996a1f
-		bfqq = &bfqd->oom_bfqq;
Jan Kara 996a1f
-		goto out;
Jan Kara 996a1f
-	}
Jan Kara 996a1f
-
Jan Kara 996a1f
+	bfqg = bfq_bio_bfqg(bfqd, bio);
Jan Kara 996a1f
 	if (!is_sync) {
Jan Kara 996a1f
 		async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class,
Jan Kara 996a1f
 						  ioprio);
Jan Kara 996a1f
@@ -5318,7 +5311,6 @@ static struct bfq_queue *bfq_get_queue(s
Jan Kara 996a1f
 out:
Jan Kara 996a1f
 	bfqq->ref++; /* get a process reference to this queue */
Jan Kara 996a1f
 	bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, bfqq->ref);
Jan Kara 996a1f
-	rcu_read_unlock();
Jan Kara 996a1f
 	return bfqq;
Jan Kara 996a1f
 }
Jan Kara 996a1f
 
Jan Kara 996a1f
--- a/block/bfq-iosched.h
Jan Kara 996a1f
+++ b/block/bfq-iosched.h
Jan Kara 996a1f
@@ -985,8 +985,7 @@ void bfq_bfqq_move(struct bfq_data *bfqd
Jan Kara 996a1f
 void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg);
Jan Kara 996a1f
 void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio);
Jan Kara 996a1f
 void bfq_end_wr_async(struct bfq_data *bfqd);
Jan Kara 996a1f
-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd,
Jan Kara 996a1f
-				     struct blkcg *blkcg);
Jan Kara 996a1f
+struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio);
Jan Kara 996a1f
 struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg);
Jan Kara 996a1f
 struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
Jan Kara 996a1f
 struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node);