Commit 2268c0fe authored by Dennis Zhou's avatar Dennis Zhou Committed by Jens Axboe

blkcg: introduce common blkg association logic

There are 3 ways blkg association can happen: association with the
current css, with the page css (swap), or from the wbc css (writeback).

This patch handles how association is done for the first case where we
are associating bsaed on the current css. If there is already a blkg
associated, the css will be reused and association will be redone as the
request_queue may have changed.
Signed-off-by: default avatarDennis Zhou <dennis@kernel.org>
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent beea9da0
...@@ -2009,7 +2009,21 @@ int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css) ...@@ -2009,7 +2009,21 @@ int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css)
EXPORT_SYMBOL_GPL(bio_associate_blkcg); EXPORT_SYMBOL_GPL(bio_associate_blkcg);
/** /**
* bio_associate_blkg - associate a bio with the a blkg * bio_disassociate_blkg - puts back the blkg reference if associated
* @bio: target bio
*
* Helper to disassociate the blkg from @bio if a blkg is associated.
*/
void bio_disassociate_blkg(struct bio *bio)
{
if (bio->bi_blkg) {
blkg_put(bio->bi_blkg);
bio->bi_blkg = NULL;
}
}
/**
* __bio_associate_blkg - associate a bio with the a blkg
* @bio: target bio * @bio: target bio
* @blkg: the blkg to associate * @blkg: the blkg to associate
* *
...@@ -2022,12 +2036,42 @@ EXPORT_SYMBOL_GPL(bio_associate_blkcg); ...@@ -2022,12 +2036,42 @@ EXPORT_SYMBOL_GPL(bio_associate_blkcg);
* A reference will be taken on the @blkg and will be released when @bio is * A reference will be taken on the @blkg and will be released when @bio is
* freed. * freed.
*/ */
int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg) static void __bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg)
{ {
if (unlikely(bio->bi_blkg)) bio_disassociate_blkg(bio);
return -EBUSY;
bio->bi_blkg = blkg_try_get_closest(blkg); bio->bi_blkg = blkg_try_get_closest(blkg);
return 0; }
/**
* bio_associate_blkg - associate a bio with a blkg
* @bio: target bio
*
* Associate @bio with the blkg found from the bio's css and request_queue.
* If one is not found, bio_lookup_blkg() creates the blkg. If a blkg is
* already associated, the css is reused and association redone as the
* request_queue may have changed.
*/
void bio_associate_blkg(struct bio *bio)
{
struct request_queue *q = bio->bi_disk->queue;
struct blkcg *blkcg;
struct blkcg_gq *blkg;
rcu_read_lock();
bio_associate_blkcg(bio, NULL);
blkcg = bio_blkcg(bio);
if (!blkcg->css.parent) {
__bio_associate_blkg(bio, q->root_blkg);
} else {
blkg = blkg_lookup_create(blkcg, q);
__bio_associate_blkg(bio, blkg);
}
rcu_read_unlock();
} }
/** /**
...@@ -2040,10 +2084,7 @@ void bio_disassociate_task(struct bio *bio) ...@@ -2040,10 +2084,7 @@ void bio_disassociate_task(struct bio *bio)
css_put(bio->bi_css); css_put(bio->bi_css);
bio->bi_css = NULL; bio->bi_css = NULL;
} }
if (bio->bi_blkg) { bio_disassociate_blkg(bio);
blkg_put(bio->bi_blkg);
bio->bi_blkg = NULL;
}
} }
/** /**
...@@ -2055,6 +2096,9 @@ void bio_clone_blkcg_association(struct bio *dst, struct bio *src) ...@@ -2055,6 +2096,9 @@ void bio_clone_blkcg_association(struct bio *dst, struct bio *src)
{ {
if (src->bi_css) if (src->bi_css)
WARN_ON(bio_associate_blkcg(dst, src->bi_css)); WARN_ON(bio_associate_blkcg(dst, src->bi_css));
if (src->bi_blkg)
__bio_associate_blkg(dst, src->bi_blkg);
} }
EXPORT_SYMBOL_GPL(bio_clone_blkcg_association); EXPORT_SYMBOL_GPL(bio_clone_blkcg_association);
#endif /* CONFIG_BLK_CGROUP */ #endif /* CONFIG_BLK_CGROUP */
......
...@@ -472,21 +472,15 @@ static void check_scale_change(struct iolatency_grp *iolat) ...@@ -472,21 +472,15 @@ static void check_scale_change(struct iolatency_grp *iolat)
static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio) static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio)
{ {
struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos); struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos);
struct blkcg *blkcg;
struct blkcg_gq *blkg; struct blkcg_gq *blkg;
struct request_queue *q = rqos->q;
bool issue_as_root = bio_issue_as_root_blkg(bio); bool issue_as_root = bio_issue_as_root_blkg(bio);
if (!blk_iolatency_enabled(blkiolat)) if (!blk_iolatency_enabled(blkiolat))
return; return;
rcu_read_lock(); bio_associate_blkg(bio);
bio_associate_blkcg(bio, NULL); blkg = bio->bi_blkg;
blkcg = bio_blkcg(bio);
blkg = blkg_lookup_create(blkcg, q);
bio_issue_init(&bio->bi_issue, bio_sectors(bio)); bio_issue_init(&bio->bi_issue, bio_sectors(bio));
bio_associate_blkg(bio, blkg);
rcu_read_unlock();
while (blkg && blkg->parent) { while (blkg && blkg->parent) {
struct iolatency_grp *iolat = blkg_to_lat(blkg); struct iolatency_grp *iolat = blkg_to_lat(blkg);
......
...@@ -2115,10 +2115,10 @@ static inline void throtl_update_latency_buckets(struct throtl_data *td) ...@@ -2115,10 +2115,10 @@ static inline void throtl_update_latency_buckets(struct throtl_data *td)
} }
#endif #endif
static void blk_throtl_assoc_bio(struct throtl_grp *tg, struct bio *bio) static void blk_throtl_assoc_bio(struct bio *bio)
{ {
#ifdef CONFIG_BLK_DEV_THROTTLING_LOW #ifdef CONFIG_BLK_DEV_THROTTLING_LOW
bio_associate_blkg(bio, tg_to_blkg(tg)); bio_associate_blkg(bio);
bio_issue_init(&bio->bi_issue, bio_sectors(bio)); bio_issue_init(&bio->bi_issue, bio_sectors(bio));
#endif #endif
} }
...@@ -2143,7 +2143,7 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, ...@@ -2143,7 +2143,7 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg,
throtl_update_latency_buckets(td); throtl_update_latency_buckets(td);
blk_throtl_assoc_bio(tg, bio); blk_throtl_assoc_bio(bio);
blk_throtl_update_idletime(tg); blk_throtl_update_idletime(tg);
sq = &tg->service_queue; sq = &tg->service_queue;
......
...@@ -511,12 +511,15 @@ static inline int bio_associate_blkcg_from_page(struct bio *bio, ...@@ -511,12 +511,15 @@ static inline int bio_associate_blkcg_from_page(struct bio *bio,
#ifdef CONFIG_BLK_CGROUP #ifdef CONFIG_BLK_CGROUP
int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css); int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css);
int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg); void bio_disassociate_blkg(struct bio *bio);
void bio_associate_blkg(struct bio *bio);
void bio_disassociate_task(struct bio *bio); void bio_disassociate_task(struct bio *bio);
void bio_clone_blkcg_association(struct bio *dst, struct bio *src); void bio_clone_blkcg_association(struct bio *dst, struct bio *src);
#else /* CONFIG_BLK_CGROUP */ #else /* CONFIG_BLK_CGROUP */
static inline int bio_associate_blkcg(struct bio *bio, static inline int bio_associate_blkcg(struct bio *bio,
struct cgroup_subsys_state *blkcg_css) { return 0; } struct cgroup_subsys_state *blkcg_css) { return 0; }
static inline void bio_disassociate_blkg(struct bio *bio) { }
static inline void bio_associate_blkg(struct bio *bio) { }
static inline void bio_disassociate_task(struct bio *bio) { } static inline void bio_disassociate_task(struct bio *bio) { }
static inline void bio_clone_blkcg_association(struct bio *dst, static inline void bio_clone_blkcg_association(struct bio *dst,
struct bio *src) { } struct bio *src) { }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment