NVDIMM Device and Persistent Memory development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Yu Kuai" <yukuai@kernel.org>
Cc: hannes@cmpxchg.org, mkoutny@suse.com, linux-raid@vger.kernel.org,
	yukuai@fygo.io, nvdimm@lists.linux.dev, tj@kernel.org
Subject: Re: [RFC PATCH v1 2/3] blk-cgroup: store blkcg in bio instead of blkg
Date: Tue, 04 Aug 2026 07:09:30 +0000	[thread overview]
Message-ID: <20260804070931.487701F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260804065313.2092022-3-yukuai@kernel.org>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] Dropping a bio's pinned `blkg` reference fails if the cgroup is offlined while IO is in flight, leaking the originally pinned `blkg` and causing a reference underflow on the root `blkg`.
- [High] `bio_blkg()` returns NULL when blkg creation fails and it falls back to an ancestor, leading to an immediate kernel panic in blk-throttle.
- [Medium] Standard IO statistics (io.stat) are silently dropped because the block cgroup association no longer creates missing blkgs by default.
--

--- Patch [2]: [RFC PATCH v1 2/3] blk-cgroup: store blkcg in bio instead of blkg ---
commit be98a58b9b6c0f35f61427866bf52e9085c5a028
Author: Yu Kuai <yukuai@fygo.io>
Subject: blk-cgroup: store blkcg in bio instead of blkg

A bio currently stores a queue-local blkg reference. This forces bio
association and remap paths to look up or create a blkg even when the bio
will never enter a blkcg policy. Store the blkcg css association in the
bio instead, and derive the blkg from the bio's blkcg and current bdev
when a policy needs it.

> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
> index 52e7faaff0e5b..68a1d93e6584e 100644
> --- a/block/blk-cgroup.c
> +++ b/block/blk-cgroup.c
[ ... ]
> +static struct blkcg_gq *bio_pinned_blkg(struct bio *bio)
> +{
> +	struct request_queue *q = bdev_get_queue(bio->bi_bdev);
> +	struct blkcg_gq *blkg;
> +
> +	rcu_read_lock();
> +	blkg = blkg_lookup(bio_blkcg(bio), q);
> +	rcu_read_unlock();
> +
> +	if (WARN_ON_ONCE(!blkg))
> +		return q->root_blkg;
> +	return blkg;
> +}

[Severity: Critical]
How does this handle a cgroup being offlined while IO is in flight?
If an unprivileged user issues async IO and then immediately removes the
cgroup via rmdir, blkg_destroy() will remove the blkg from the radix tree.
When the bio completes, blkg_lookup() here will fail to find the child blkg
and fall back to returning q->root_blkg.

[ ... ]
> +void bio_put_blkg_ref(struct bio *bio)
> +{
> +	if (bio_flagged(bio, BIO_BLKG_REF)) {
> +		struct blkcg_gq *blkg = bio_pinned_blkg(bio);
> +
> +		blkg_put(blkg);
> +		bio_clear_flag(bio, BIO_BLKG_REF);
> +	}
> +}

[Severity: Critical]
Because bio_pinned_blkg() falls back to q->root_blkg when the child blkg is
no longer in the radix tree, blkg_put() here will drop the reference on the
root blkg instead of the actually pinned child blkg. Will this leak the
child blkg and eventually cause a use-after-free panic on the root blkg
due to the reference underflow?

[ ... ]
> +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;
> +
> +	if (!blkcg || !bio->bi_bdev)
> +		return NULL;
> +
> +	if (bio_flagged(bio, BIO_BLKG_REF))
> +		return bio_pinned_blkg(bio);
> +
> +	disk = bio->bi_bdev->bd_disk;
> +	q = disk->queue;
>  
>  	spin_lock_irq(&q->queue_lock);
> -	blkg = blkg_lookup_create(blkcg, bio->bi_bdev->bd_disk);
> -	if (blkg)
> -		blkg = blkg_lookup_tryget(blkg);
> +	blkg = blkg_lookup_create(blkcg, disk);
> +	if (blkg && blkg->blkcg == blkcg && blkg_tryget(blkg))
> +		bio_set_flag(bio, BIO_BLKG_REF);
> +	else
> +		blkg = NULL;
>  	spin_unlock_irq(&q->queue_lock);
>  
>  	return blkg;
>  }

[Severity: High]
Is it intentional to return NULL when blkg_lookup_create() falls back
to an ancestor? If blkg creation fails due to ENOMEM, it correctly
returns the closest alive ancestor. But this strict blkg->blkcg == blkcg
check fails, explicitly returning NULL. Since blk-throttle unconditionally
dereferences the returned blkg (for example in __blk_throtl_bio() via
blkg_to_tg(blkg)->td), won't this cause a kernel panic under memory pressure
instead of gracefully falling back?

[ ... ]
>  void blk_cgroup_bio_start(struct bio *bio)
>  {
> -	struct blkcg_gq *blkg = bio_blkg(bio);
>  	struct blkcg *blkcg = bio_blkcg(bio);
> +	struct blkcg_gq *blkg;
>  	int rwd = blk_cgroup_io_type(bio), cpu;
>  	struct blkg_iostat_set *bis;
>  	unsigned long flags;
>  
>  	if (!cgroup_subsys_on_dfl(io_cgrp_subsys))
>  		return;
> +	if (!blkcg)
> +		return;
>  
>  	/* Root-level stats are sourced from system-wide IO stats */
>  	if (!cgroup_parent(blkcg->css.cgroup))
>  		return;
>  
> +	blkg = bio_blkg_lookup(bio);
> +	if (!blkg)
> +		return;

[Severity: Medium]
Can this silently drop standard IO statistics (io.stat)? Before this
patch, bio_associate_blkg() proactively created the blkg. Now, missing
blkgs are not created by default. If no other active IO policy like
throttle or BFQ processes the bio and explicitly calls bio_blkg() to
create the hierarchy, bio_blkg_lookup() returns NULL and
blk_cgroup_bio_start() aborts. Does this completely lose cgroup IO accounting
on disks without active block IO policies?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260804065313.2092022-1-yukuai@kernel.org?part=2

  reply	other threads:[~2026-08-04  7:09 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-04  6:53 [RFC PATCH v1 0/3] blk-cgroup: store blkcg in bio before blkcg_mutex conversion Yu Kuai
2026-08-04  6:53 ` [RFC PATCH v1 1/3] blk-cgroup: add helpers for bio cgroup state Yu Kuai
2026-08-04  7:08   ` sashiko-bot
2026-08-04 10:52   ` Jan Kara
2026-08-04 13:25     ` Christoph Hellwig
2026-08-04 15:07       ` yu kuai
2026-08-04  6:53 ` [RFC PATCH v1 2/3] blk-cgroup: store blkcg in bio instead of blkg Yu Kuai
2026-08-04  7:09   ` sashiko-bot [this message]
2026-08-04  9:19   ` Tao Cui
2026-08-04 13:32     ` Christoph Hellwig
2026-08-04 15:30       ` yu kuai
2026-08-04 15:47         ` Christoph Hellwig
2026-08-05  0:58         ` Tao Cui
2026-08-06  9:22   ` Michal Koutný
2026-08-04  6:53 ` [RFC PATCH v1 3/3] blk-cgroup: move async bio punt state to blkcg Yu Kuai
2026-08-04  7:10   ` sashiko-bot

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=20260804070931.487701F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=mkoutny@suse.com \
    --cc=nvdimm@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tj@kernel.org \
    --cc=yukuai@fygo.io \
    --cc=yukuai@kernel.org \
    /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