From: Yu Kuai <yukuai@kernel.org>
To: "Jens Axboe" <axboe@kernel.dk>, "Tejun Heo" <tj@kernel.org>,
"Josef Bacik" <josef@toxicpanda.com>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Michal Koutný" <mkoutny@suse.com>
Cc: Yu Kuai <yukuai@fygo.io>, Christoph Hellwig <hch@lst.de>,
Tao Cui <cui.tao@linux.dev>, Jan Kara <jack@suse.cz>,
Ming Lei <ming.lei@redhat.com>, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>, Coly Li <colyli@fygo.io>,
Kent Overstreet <kent.overstreet@linux.dev>,
Alasdair Kergon <agk@redhat.com>,
Mike Snitzer <snitzer@kernel.org>,
Mikulas Patocka <mpatocka@redhat.com>,
Benjamin Marzinski <bmarzins@redhat.com>,
Song Liu <song@kernel.org>, Li Nan <magiclinan@didiglobal.com>,
Xiao Ni <xiao@kernel.org>,
Pankaj Gupta <pankaj.gupta.linux@gmail.com>,
Dan Williams <djbw@kernel.org>,
Vishal Verma <vishal.l.verma@intel.com>,
Dave Jiang <dave.jiang@intel.com>,
Alison Schofield <alison.schofield@intel.com>,
Ira Weiny <iweiny@kernel.org>,
Andreas Gruenbacher <agruenba@redhat.com>,
Matthew Wilcox <willy@infradead.org>,
Andrew Morton <akpm@linux-foundation.org>,
Chris Li <chrisl@kernel.org>, Kairui Song <kasong@tencent.com>,
Kemeng Shi <shikemeng@huaweicloud.com>,
Nhat Pham <nphamcs@gmail.com>, Baoquan He <baoquan.he@linux.dev>,
Barry Song <baohua@kernel.org>,
Youngjun Park <youngjun.park@lge.com>,
cgroups@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-block@vger.kernel.org,
linux-bcache@vger.kernel.org, dm-devel@lists.linux.dev,
linux-raid@vger.kernel.org, nvdimm@lists.linux.dev,
virtualization@lists.linux.dev, gfs2@lists.linux.dev,
linux-fsdevel@vger.kernel.org, linux-mm@kvack.org
Subject: [RFC PATCH v3 3/3] blk-cgroup: move async bio punt state to blkcg
Date: Tue, 18 Aug 2026 15:06:41 +0800 [thread overview]
Message-ID: <20260818070641.756747-4-yukuai@kernel.org> (raw)
In-Reply-To: <20260818070641.756747-1-yukuai@kernel.org>
From: Yu Kuai <yukuai@fygo.io>
blkcg_punt_bio_submit() currently queues punted bios on blkg->async_bios,
so it has to call bio_blkg() to find or create a queue-local blkg. Bios
now carry and pin the blkcg css, so punted bio lifetime no longer needs to
be anchored by a blkg.
Keeping the punt state in blkg can instantiate a blkg even when no blkcg
policy is enabled, just to bounce submission from a shared kthread. Move
async_bio_lock, async_bios and async_bio_work to struct blkcg, and queue
punted bios on bio_blkcg() for non-root cgroups. Root or unassociated bios
are submitted directly.
This preserves the priority-inversion avoidance while preventing
blkcg_punt_bio_submit() from creating blkgs that are not needed by any
policy.
Signed-off-by: Yu Kuai <yukuai@fygo.io>
---
block/blk-cgroup.c | 44 +++++++++++++++++++++-----------------------
block/blk-cgroup.h | 14 ++++++--------
2 files changed, 27 insertions(+), 31 deletions(-)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index c3bbcb3e7e58..2c758c26bce6 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -178,14 +178,10 @@ static void blkg_free(struct blkcg_gq *blkg)
static void __blkg_release(struct rcu_head *rcu)
{
struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head);
-#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
- WARN_ON(!bio_list_empty(&blkg->async_bios));
-#endif
-
blkg_free(blkg);
}
/*
* A group is RCU protected, but having an rcu lock does not mean that one
@@ -224,23 +220,22 @@ static void blkg_release(struct percpu_ref *ref)
}
#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
static struct workqueue_struct *blkcg_punt_bio_wq;
-static void blkg_async_bio_workfn(struct work_struct *work)
+static void blkcg_async_bio_workfn(struct work_struct *work)
{
- struct blkcg_gq *blkg = container_of(work, struct blkcg_gq,
- async_bio_work);
+ struct blkcg *blkcg = container_of(work, struct blkcg, async_bio_work);
struct bio_list bios = BIO_EMPTY_LIST;
struct bio *bio;
struct blk_plug plug;
bool need_plug = false;
- /* as long as there are pending bios, @blkg can't go away */
- spin_lock(&blkg->async_bio_lock);
- bio_list_merge_init(&bios, &blkg->async_bios);
- spin_unlock(&blkg->async_bio_lock);
+ /* as long as there are pending bios, @blkcg can't go away */
+ spin_lock(&blkcg->async_bio_lock);
+ bio_list_merge_init(&bios, &blkcg->async_bios);
+ spin_unlock(&blkcg->async_bio_lock);
/* start plug only when bio_list contains at least 2 bios */
if (bios.head && bios.head->bi_next) {
need_plug = true;
blk_start_plug(&plug);
@@ -257,19 +252,19 @@ static void blkg_async_bio_workfn(struct work_struct *work)
* cgroup. Use this helper instead of submit_bio to punt the actual issuing to
* a dedicated per-blkcg work item to avoid such priority inversions.
*/
void blkcg_punt_bio_submit(struct bio *bio)
{
- struct blkcg_gq *blkg = bio_blkg(bio);
+ struct blkcg *blkcg = bio_blkcg(bio);
- if (blkg && blkg->parent) {
- spin_lock(&blkg->async_bio_lock);
- bio_list_add(&blkg->async_bios, bio);
- spin_unlock(&blkg->async_bio_lock);
- queue_work(blkcg_punt_bio_wq, &blkg->async_bio_work);
+ if (blkcg && cgroup_parent(blkcg->css.cgroup)) {
+ spin_lock(&blkcg->async_bio_lock);
+ bio_list_add(&blkcg->async_bios, bio);
+ spin_unlock(&blkcg->async_bio_lock);
+ queue_work(blkcg_punt_bio_wq, &blkcg->async_bio_work);
} else {
- /* Never bounce if there is no non-root blkg to queue on. */
+ /* Never bounce if there is no non-root blkcg to queue on. */
submit_bio(bio);
}
}
EXPORT_SYMBOL_GPL(blkcg_punt_bio_submit);
@@ -348,15 +343,10 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
blkg->q = disk->queue;
INIT_LIST_HEAD(&blkg->q_node);
blkg->blkcg = blkcg;
blkg->blkcg_id = blkcg->css.id;
blkg->iostat.blkg = blkg;
-#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
- spin_lock_init(&blkg->async_bio_lock);
- bio_list_init(&blkg->async_bios);
- INIT_WORK(&blkg->async_bio_work, blkg_async_bio_workfn);
-#endif
u64_stats_init(&blkg->iostat.sync);
for_each_possible_cpu(cpu) {
u64_stats_init(&per_cpu_ptr(blkg->iostat_cpu, cpu)->sync);
per_cpu_ptr(blkg->iostat_cpu, cpu)->blkg = blkg;
@@ -1388,10 +1378,13 @@ static void blkcg_css_free(struct cgroup_subsys_state *css)
if (blkcg->cpd[i])
blkcg_policy[i]->cpd_free_fn(blkcg->cpd[i]);
mutex_unlock(&blkcg_pol_mutex);
+#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
+ WARN_ON(!bio_list_empty(&blkcg->async_bios));
+#endif
free_percpu(blkcg->lhead);
kfree(blkcg);
}
static struct cgroup_subsys_state *
@@ -1436,10 +1429,15 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
}
spin_lock_init(&blkcg->lock);
refcount_set(&blkcg->online_pin, 1);
INIT_HLIST_HEAD(&blkcg->blkg_list);
+#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
+ spin_lock_init(&blkcg->async_bio_lock);
+ bio_list_init(&blkcg->async_bios);
+ INIT_WORK(&blkcg->async_bio_work, blkcg_async_bio_workfn);
+#endif
#ifdef CONFIG_CGROUP_WRITEBACK
INIT_LIST_HEAD(&blkcg->cgwb_list);
#endif
list_add_tail(&blkcg->all_blkcgs_node, &all_blkcgs);
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 936428b6127e..eb76cc38b41b 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -75,18 +75,11 @@ struct blkcg_gq {
struct blkg_iostat_set __percpu *iostat_cpu;
struct blkg_iostat_set iostat;
struct blkg_policy_data *pd[BLKCG_MAX_POLS];
-#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
- spinlock_t async_bio_lock;
- struct bio_list async_bios;
-#endif
- union {
- struct work_struct async_bio_work;
- struct work_struct free_work;
- };
+ struct work_struct free_work;
atomic_t use_delay;
atomic64_t delay_nsec;
atomic64_t delay_start;
u64 last_delay;
@@ -111,10 +104,15 @@ struct blkcg {
/*
* List of updated percpu blkg_iostat_set's since the last flush.
*/
struct llist_head __percpu *lhead;
+#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
+ spinlock_t async_bio_lock; /* protects async_bios */
+ struct bio_list async_bios;
+ struct work_struct async_bio_work;
+#endif
#ifdef CONFIG_BLK_CGROUP_FC_APPID
char fc_app_id[FC_APPID_LEN];
#endif
#ifdef CONFIG_CGROUP_WRITEBACK
struct list_head cgwb_list;
--
2.51.0
next prev parent reply other threads:[~2026-08-18 7:08 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 7:06 [RFC PATCH v3 0/3] blk-cgroup: store blkcg in bio before blkcg_mutex conversion Yu Kuai
2026-08-18 7:06 ` [RFC PATCH v3 1/3] blk-cgroup: use a request_queue rhashtable for blkg lookup Yu Kuai
2026-08-19 9:14 ` Christoph Hellwig
2026-08-18 7:06 ` [RFC PATCH v3 2/3] blk-cgroup: store blkcg in bio instead of blkg Yu Kuai
2026-08-19 9:14 ` Christoph Hellwig
2026-08-18 7:06 ` Yu Kuai [this message]
2026-08-19 9:15 ` [RFC PATCH v3 3/3] blk-cgroup: move async bio punt state to blkcg Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818070641.756747-4-yukuai@kernel.org \
--to=yukuai@kernel.org \
--cc=agk@redhat.com \
--cc=agruenba@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=alison.schofield@intel.com \
--cc=axboe@kernel.dk \
--cc=baohua@kernel.org \
--cc=baoquan.he@linux.dev \
--cc=bmarzins@redhat.com \
--cc=cgroups@vger.kernel.org \
--cc=chrisl@kernel.org \
--cc=colyli@fygo.io \
--cc=corbet@lwn.net \
--cc=cui.tao@linux.dev \
--cc=dave.jiang@intel.com \
--cc=djbw@kernel.org \
--cc=dm-devel@lists.linux.dev \
--cc=gfs2@lists.linux.dev \
--cc=hannes@cmpxchg.org \
--cc=hch@lst.de \
--cc=iweiny@kernel.org \
--cc=jack@suse.cz \
--cc=josef@toxicpanda.com \
--cc=kasong@tencent.com \
--cc=kent.overstreet@linux.dev \
--cc=linux-bcache@vger.kernel.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-raid@vger.kernel.org \
--cc=magiclinan@didiglobal.com \
--cc=ming.lei@redhat.com \
--cc=mkoutny@suse.com \
--cc=mpatocka@redhat.com \
--cc=nphamcs@gmail.com \
--cc=nvdimm@lists.linux.dev \
--cc=pankaj.gupta.linux@gmail.com \
--cc=shikemeng@huaweicloud.com \
--cc=skhan@linuxfoundation.org \
--cc=snitzer@kernel.org \
--cc=song@kernel.org \
--cc=tj@kernel.org \
--cc=virtualization@lists.linux.dev \
--cc=vishal.l.verma@intel.com \
--cc=willy@infradead.org \
--cc=xiao@kernel.org \
--cc=youngjun.park@lge.com \
--cc=yukuai@fygo.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.