Linux block layer
 help / color / mirror / Atom feed
From: Yu Kuai <yukuai@kernel.org>
To: Jens Axboe <axboe@kernel.dk>, Tejun Heo <tj@kernel.org>,
	Josef Bacik <josef@toxicpanda.com>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	Clark Williams <clrkwllms@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>
Cc: Yu Kuai <yukuai@fygo.io>, Christoph Hellwig <hch@lst.de>,
	Nilay Shroff <nilay@linux.ibm.com>, Tao Cui <cui.tao@linux.dev>,
	Hannes Reinecke <hare@suse.de>,
	linux-block@vger.kernel.org, cgroups@vger.kernel.org,
	linux-rt-devel@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [RFC PATCH v3 6/6] blk-cgroup: make policy blkg creation nowait-safe
Date: Sun, 23 Aug 2026 23:29:25 +0800	[thread overview]
Message-ID: <20260823152926.1043863-7-yukuai@kernel.org> (raw)
In-Reply-To: <20260823152926.1043863-1-yukuai@kernel.org>

From: Yu Kuai <yukuai@fygo.io>

bio_blkg() is called by blkcg policy paths when they need a queue-local
blkg. Keep that allocation lazy instead of preparing every REQ_NOWAIT bio
from submit_bio_noacct().

If a policy first needs a blkg for a REQ_NOWAIT bio, use mutex_trylock()
and GFP_ATOMIC so the lookup never sleeps. If the mutex cannot be acquired,
look up and pin the closest existing blkg in the hierarchy under RCU. The
creation helper provides the same fallback if atomic allocation fails, so
valid policy I/O always gets a blkg without blocking.

Signed-off-by: Yu Kuai <yukuai@fygo.io>
---
 block/blk-cgroup.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 31afb433ab18..9895d6661070 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -28,10 +28,11 @@
 #include <linux/atomic.h>
 #include <linux/ctype.h>
 #include <linux/resume_user_mode.h>
 #include <linux/psi.h>
 #include <linux/part_stat.h>
+#include <linux/preempt.h>
 #include "blk.h"
 #include "blk-cgroup.h"
 #include "blk-ioprio.h"
 #include "blk-throttle.h"
 
@@ -469,10 +470,24 @@ static struct blkcg_gq *blkg_lookup_tryget(struct blkcg_gq *blkg)
 	while (!blkg_tryget(blkg))
 		blkg = blkg->parent;
 	return blkg;
 }
 
+static struct blkcg_gq *blkg_lookup_closest(struct blkcg *blkcg,
+					    struct request_queue *q)
+{
+	struct blkcg_gq *blkg;
+
+	rcu_read_lock();
+	while (!(blkg = blkg_lookup(blkcg, q)))
+		blkcg = blkcg_parent(blkcg);
+	blkg = blkg_lookup_tryget(blkg);
+	rcu_read_unlock();
+
+	return blkg;
+}
+
 /**
  * blkg_lookup_create - lookup blkg, try to create one if not there
  * @blkcg: blkcg of interest
  * @disk: gendisk of interest
  * @gfp_mask: allocation mask to use
@@ -2066,11 +2081,10 @@ struct blkcg_gq *bio_blkg(struct bio *bio)
 {
 	struct blkcg *blkcg = bio_blkcg(bio);
 	struct gendisk *disk;
 	struct request_queue *q;
 	struct blkcg_gq *blkg;
-	int ret;
 
 	if (!blkcg || !bio->bi_bdev)
 		return NULL;
 
 	if (bio_flagged(bio, BIO_BLKG_REF))
@@ -2087,10 +2101,29 @@ struct blkcg_gq *bio_blkg(struct bio *bio)
 	if (blkg) {
 		bio_set_blkg_ref(bio, blkg);
 		return blkg;
 	}
 
+	if (bio->bi_opf & REQ_NOWAIT) {
+		/*
+		 * Nowait callers must not sleep on the mutex nor allocate with
+		 * sleeping GFPs.  Trylock the mutex and create the missing blkg
+		 * atomically.  If the mutex cannot be acquired, skip allocation
+		 * and pin the closest existing blkg instead.  blkg_lookup_create()
+		 * provides the same fallback if allocation fails.
+		 */
+		if (!preemptible() || !mutex_trylock(&q->blkcg_mutex)) {
+			blkg = blkg_lookup_closest(blkcg, q);
+		} else {
+			blkg_lookup_create(blkcg, disk, GFP_ATOMIC, &blkg);
+			blkg = blkg_lookup_tryget(blkg);
+			mutex_unlock(&q->blkcg_mutex);
+		}
+		bio_set_blkg_ref(bio, blkg);
+		return blkg;
+	}
+
 	mutex_lock(&q->blkcg_mutex);
 	blkg_lookup_create(blkcg, disk, GFP_NOIO, &blkg);
 	blkg = blkg_lookup_tryget(blkg);
 	mutex_unlock(&q->blkcg_mutex);
 
-- 
2.51.0


      parent reply	other threads:[~2026-08-23 15:30 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-23 15:29 [RFC PATCH v3 0/6] blk-cgroup: protect blkgs with blkcg_mutex Yu Kuai
2026-08-23 15:29 ` [RFC PATCH v3 1/6] blk-cgroup: call pd_free_fn() outside spinlocks Yu Kuai
2026-08-23 15:29 ` [RFC PATCH v3 2/6] blk-throttle: protect throttle state with td lock Yu Kuai
2026-08-23 15:29 ` [RFC PATCH v3 3/6] blk-cgroup: protect blkgs with blkcg_mutex Yu Kuai
2026-08-23 15:29 ` [RFC PATCH v3 4/6] blk-cgroup: allocate blkgs in blkg_create Yu Kuai
2026-08-25  1:35   ` Tao Cui
2026-08-25  2:33     ` yu kuai
2026-08-23 15:29 ` [RFC PATCH v3 5/6] blk-cgroup: share blkg creation between lookup and config prep Yu Kuai
2026-08-23 15:29 ` Yu Kuai [this message]

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=20260823152926.1043863-7-yukuai@kernel.org \
    --to=yukuai@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=bigeasy@linutronix.de \
    --cc=cgroups@vger.kernel.org \
    --cc=clrkwllms@kernel.org \
    --cc=cui.tao@linux.dev \
    --cc=hare@suse.de \
    --cc=hch@lst.de \
    --cc=josef@toxicpanda.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-devel@lists.linux.dev \
    --cc=nilay@linux.ibm.com \
    --cc=rostedt@goodmis.org \
    --cc=tj@kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox