Skip to content

Commit beea9da

Browse files
dennisszhouaxboe
authored andcommitted
blkcg: convert blkg_lookup_create() to find closest blkg
There are several scenarios where blkg_lookup_create() can fail such as the blkcg dying, request_queue is dying, or simply being OOM. Most handle this by simply falling back to the q->root_blkg and calling it a day. This patch implements the notion of closest blkg. During blkg_lookup_create(), if it fails to create, return the closest blkg found or the q->root_blkg. blkg_try_get_closest() is introduced and used during association so a bio is always attached to a blkg. Signed-off-by: Dennis Zhou <dennis@kernel.org> Acked-by: Tejun Heo <tj@kernel.org> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent b978962 commit beea9da

File tree

5 files changed

+44
-38
lines changed

5 files changed

+44
-38
lines changed

block/bio.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,21 +2009,24 @@ int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css)
20092009
EXPORT_SYMBOL_GPL(bio_associate_blkcg);
20102010

20112011
/**
2012-
* bio_associate_blkg - associate a bio with the specified blkg
2012+
* bio_associate_blkg - associate a bio with the a blkg
20132013
* @bio: target bio
20142014
* @blkg: the blkg to associate
20152015
*
2016-
* Associate @bio with the blkg specified by @blkg. This is the queue specific
2017-
* blkcg information associated with the @bio, a reference will be taken on the
2018-
* @blkg and will be freed when the bio is freed.
2016+
* This tries to associate @bio with the specified @blkg. Association failure
2017+
* is handled by walking up the blkg tree. Therefore, the blkg associated can
2018+
* be anything between @blkg and the root_blkg. This situation only happens
2019+
* when a cgroup is dying and then the remaining bios will spill to the closest
2020+
* alive blkg.
2021+
*
2022+
* A reference will be taken on the @blkg and will be released when @bio is
2023+
* freed.
20192024
*/
20202025
int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg)
20212026
{
20222027
if (unlikely(bio->bi_blkg))
20232028
return -EBUSY;
2024-
if (!blkg_try_get(blkg))
2025-
return -ENODEV;
2026-
bio->bi_blkg = blkg;
2029+
bio->bi_blkg = blkg_try_get_closest(blkg);
20272030
return 0;
20282031
}
20292032

block/blk-cgroup.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,8 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
258258
* that all non-root blkg's have access to the parent blkg. This function
259259
* should be called under RCU read lock and @q->queue_lock.
260260
*
261-
* Returns pointer to the looked up or created blkg on success, ERR_PTR()
262-
* value on error. If @q is dead, returns ERR_PTR(-EINVAL). If @q is not
263-
* dead and bypassing, returns ERR_PTR(-EBUSY).
261+
* Returns the blkg or the closest blkg if blkg_create() fails as it walks
262+
* down from root.
264263
*/
265264
struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg,
266265
struct request_queue *q)
@@ -276,19 +275,29 @@ struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg,
276275

277276
/*
278277
* Create blkgs walking down from blkcg_root to @blkcg, so that all
279-
* non-root blkgs have access to their parents.
278+
* non-root blkgs have access to their parents. Returns the closest
279+
* blkg to the intended blkg should blkg_create() fail.
280280
*/
281281
while (true) {
282282
struct blkcg *pos = blkcg;
283283
struct blkcg *parent = blkcg_parent(blkcg);
284-
285-
while (parent && !__blkg_lookup(parent, q, false)) {
284+
struct blkcg_gq *ret_blkg = q->root_blkg;
285+
286+
while (parent) {
287+
blkg = __blkg_lookup(parent, q, false);
288+
if (blkg) {
289+
/* remember closest blkg */
290+
ret_blkg = blkg;
291+
break;
292+
}
286293
pos = parent;
287294
parent = blkcg_parent(parent);
288295
}
289296

290297
blkg = blkg_create(pos, q, NULL);
291-
if (pos == blkcg || IS_ERR(blkg))
298+
if (IS_ERR(blkg))
299+
return ret_blkg;
300+
if (pos == blkcg)
292301
return blkg;
293302
}
294303
}

block/blk-iolatency.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -483,21 +483,11 @@ static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio)
483483
rcu_read_lock();
484484
bio_associate_blkcg(bio, NULL);
485485
blkcg = bio_blkcg(bio);
486-
blkg = blkg_lookup(blkcg, q);
487-
if (unlikely(!blkg)) {
488-
spin_lock_irq(&q->queue_lock);
489-
blkg = __blkg_lookup_create(blkcg, q);
490-
if (IS_ERR(blkg))
491-
blkg = NULL;
492-
spin_unlock_irq(&q->queue_lock);
493-
}
494-
if (!blkg)
495-
goto out;
496-
486+
blkg = blkg_lookup_create(blkcg, q);
497487
bio_issue_init(&bio->bi_issue, bio_sectors(bio));
498488
bio_associate_blkg(bio, blkg);
499-
out:
500489
rcu_read_unlock();
490+
501491
while (blkg && blkg->parent) {
502492
struct iolatency_grp *iolat = blkg_to_lat(blkg);
503493
if (!iolat) {

block/blk-throttle.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,9 +2118,7 @@ static inline void throtl_update_latency_buckets(struct throtl_data *td)
21182118
static void blk_throtl_assoc_bio(struct throtl_grp *tg, struct bio *bio)
21192119
{
21202120
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW
2121-
/* fallback to root_blkg if we fail to get a blkg ref */
2122-
if (bio->bi_css && (bio_associate_blkg(bio, tg_to_blkg(tg)) == -ENODEV))
2123-
bio_associate_blkg(bio, bio->bi_disk->queue->root_blkg);
2121+
bio_associate_blkg(bio, tg_to_blkg(tg));
21242122
bio_issue_init(&bio->bi_issue, bio_sectors(bio));
21252123
#endif
21262124
}

include/linux/blk-cgroup.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,20 @@ static inline struct blkcg_gq *blkg_try_get(struct blkcg_gq *blkg)
545545
return NULL;
546546
}
547547

548+
/**
549+
* blkg_try_get_closest - try and get a blkg ref on the closet blkg
550+
* @blkg: blkg to get
551+
*
552+
* This walks up the blkg tree to find the closest non-dying blkg and returns
553+
* the blkg that it did association with as it may not be the passed in blkg.
554+
*/
555+
static inline struct blkcg_gq *blkg_try_get_closest(struct blkcg_gq *blkg)
556+
{
557+
while (!atomic_inc_not_zero(&blkg->refcnt))
558+
blkg = blkg->parent;
559+
560+
return blkg;
561+
}
548562

549563
void __blkg_release_rcu(struct rcu_head *rcu);
550564

@@ -797,15 +811,7 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q,
797811
/* associate blkcg if bio hasn't attached one */
798812
bio_associate_blkcg(bio, NULL);
799813
blkcg = bio_blkcg(bio);
800-
801-
blkg = blkg_lookup(blkcg, q);
802-
if (unlikely(!blkg)) {
803-
spin_lock_irq(&q->queue_lock);
804-
blkg = __blkg_lookup_create(blkcg, q);
805-
if (IS_ERR(blkg))
806-
blkg = NULL;
807-
spin_unlock_irq(&q->queue_lock);
808-
}
814+
blkg = blkg_lookup_create(blkcg, q);
809815

810816
throtl = blk_throtl_bio(q, blkg, bio);
811817

0 commit comments

Comments
 (0)