From: Zhaoyang Huang <zhaoyang.huang@xxxxxxxxxx> The 'over-sized' bio under blk throttle control will be delayed to launch which breaks original IO timing and have the immediate BW be not within the bps limit. Introduce a helper function to calculate block device's budgt which provide the allowed bytes for current bio. Signed-off-by: Zhaoyang Huang <zhaoyang.huang@xxxxxxxxxx> --- block/blk-throttle.c | 44 ++++++++++++++++++++++++++++++++++++++ include/linux/blk-cgroup.h | 10 +++++++++ 2 files changed, 54 insertions(+) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index f4850a6f860b..41c75258183d 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -10,6 +10,7 @@ #include <linux/blkdev.h> #include <linux/bio.h> #include <linux/blktrace_api.h> +#include <linux/cgroup.h> #include "blk.h" #include "blk-cgroup-rwstat.h" #include "blk-stat.h" @@ -2365,6 +2366,49 @@ void blk_throtl_bio_endio(struct bio *bio) } #endif +unsigned long blk_throttle_budgt(struct block_device *bdev) +{ + struct request_queue *q = bdev_get_queue(bdev); + struct blkcg *blkcg; + struct blkcg_gq *blkg; + struct throtl_grp *tg; + long long bytes_allowed = 0; + unsigned long jiffy_elapsed, jiffy_elapsed_rnd; + u64 bps_limit; + + if (!q) + return U64_MAX; + + rcu_read_lock(); + spin_lock_irq(&q->queue_lock); + blkcg = css_to_blkcg(task_css(current, io_cgrp_id)); + if (!blkcg) + goto out; + + blkg = blkg_lookup(blkcg, q); + if (!blkg || !blkg_tryget(blkg)) + goto out; + + tg = blkg_to_tg(blkg); + bps_limit = tg_bps_limit(tg, READ); + if (bps_limit == U64_MAX) + goto out; + + jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[READ]; + if (!jiffy_elapsed) + jiffy_elapsed_rnd = tg->td->throtl_slice; + + jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, tg->td->throtl_slice); + bytes_allowed = calculate_bytes_allowed(bps_limit, jiffy_elapsed_rnd) + + tg->carryover_bytes[READ]; + blkg_put(blkg); +out: + spin_unlock_irq(&q->queue_lock); + rcu_read_unlock(); + return bytes_allowed; +} + + int blk_throtl_init(struct gendisk *disk) { struct request_queue *q = disk->queue; diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index dd5841a42c33..ba79fa464e0a 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -15,10 +15,12 @@ */ #include <linux/types.h> +#include <linux/limits.h> struct bio; struct cgroup_subsys_state; struct gendisk; +struct block_device; #define FC_APPID_LEN 129 @@ -45,6 +47,14 @@ static inline struct cgroup_subsys_state *bio_blkcg_css(struct bio *bio) } #endif /* CONFIG_BLK_CGROUP */ +#ifdef CONFIG_BLK_DEV_THROTTLING +unsigned long blk_throttle_budgt(struct block_device *bdev); +#else +static inline unsigned long blk_throttle_budgt(struct block_device *bdev) +{ + return U64_MAX; +} +#endif int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len); char *blkcg_get_fc_appid(struct bio *bio); -- 2.25.1