Re: [RFC PATCH v2 7/8] bfq: avoid blkg lookup from locked cgroup update

"yu kuai" <[email protected]> Wed, 29 Jul 2026 15:56:16 +0800
Newsgroups org.kernel.vger.cgroups,org.kernel.vger.linux-block
Message-ID <[email protected]>
Hi,

在 2026/7/29 15:33, Tao Cui 写道:
>
> 在 2026/7/24 20:30, Yu Kuai 写道:
>> From: Yu Kuai <[email protected]>
>>
>> bfq_bio_bfqg() is called while bfqd->lock is held from the merge and
>> request insertion paths.  It walks bio->bi_blkg and its parent chain to
>> find the closest online BFQ group, and re-associates the bio by looking
>> the chosen blkg up again through bio_associate_blkg_from_css().
>>
>> Now that blkg creation runs under q->blkcg_mutex from the sleepable submit
>> path, bio_associate_blkg_from_css() can sleep on a lookup miss, which BFQ
>> must not do while holding bfqd->lock.  The blkg BFQ wants is already in
>> hand from the ancestry walk, so update bio->bi_blkg by swapping references
>> to that existing blkg directly instead of looking it up again by css.
>>
> Just checking the new bfq helper that swaps a bio's blkg: it does the
> blkg_put() without the NULL guard the old helper had.  Is there any path
> where BFQ could see a bio that hasn't been associated yet (bi_blkg == NULL)?
> The fallback branch calls it unconditionally, so if such a path exists it
> would crash.  My reading is the bio is always associated before it reaches
> BFQ, so it can't happen -- but wanted to ask in case I'm missing a path.

You're not missing. Bio must associate a blkg before submitting, you can see
lots of places will deference bio's blkg directly.

>
> Thanks,
> Tao
>
>> Signed-off-by: Yu Kuai <[email protected]>
>> ---
>>   block/bfq-cgroup.c | 16 +++++++++++++---
>>   1 file changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
>> index 42614aa78cd4..8a3ff9510386 100644
>> --- a/block/bfq-cgroup.c
>> +++ b/block/bfq-cgroup.c
>> @@ -604,6 +604,16 @@ static void bfq_link_bfqg(struct bfq_data *bfqd, struct bfq_group *bfqg)
>>   	}
>>   }
>>   
>> +static void bfq_bio_update_blkg(struct bio *bio, struct blkcg_gq *blkg)
>> +{
>> +	if (bio->bi_blkg == blkg)
>> +		return;
>> +
>> +	blkg_get(blkg);
>> +	blkg_put(bio->bi_blkg);
>> +	bio->bi_blkg = blkg;
>> +}
>> +
>>   struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
>>   {
>>   	struct blkcg_gq *blkg = bio->bi_blkg;
>> @@ -616,13 +626,13 @@ struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
>>   		}
>>   		bfqg = blkg_to_bfqg(blkg);
>>   		if (bfqg->pd.online) {
>> -			bio_associate_blkg_from_css(bio, &blkg->blkcg->css);
>> +			bfq_bio_update_blkg(bio, blkg);
>>   			return bfqg;
>>   		}
>>   		blkg = blkg->parent;
>>   	}
>> -	bio_associate_blkg_from_css(bio,
>> -				&bfqg_to_blkg(bfqd->root_group)->blkcg->css);
>> +	blkg = bfqg_to_blkg(bfqd->root_group);
>> +	bfq_bio_update_blkg(bio, blkg);
>>   	return bfqd->root_group;
>>   }
>>   

-- 
Thanks,
Kuai