From: Tao Cui Standalone flushes issued by blkdev_issue_flush() are represented as dataless REQ_OP_WRITE | REQ_PREFLUSH bios, which calc_vtime_cost_builtin() prices at zero. The flush component of flush-heavy workloads such as database commits, journal flushes, and metadata sync is thus neither charged nor throttled: a cgroup at 1% weight can issue ~510k flushes per 12s, monopolizing the device while iocost reports zero usage. Price them as pageless random writes (LCOEF_WRANDIO), which provides an approximation of the device time consumed by a flush. For profiles where WRANDIO clamps to zero (ssd_dfl / ssd_fast), use a one-page floor (LCOEF_WPAGE). After this patch, the same 1%-weight cgroup is limited to 24 flushes per 12s; on ext4, write+fsync workloads are correctly accounted through the journal layer (~2.2us per flush on the ssd_fast profile). Fixes: 7caa47151ab2 ("blkcg: implement blk-iocost") Signed-off-by: Tao Cui --- block/blk-iocost.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 2745bffcd5ee..abc512532ed9 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2533,8 +2533,8 @@ static void calc_vtime_cost_builtin(struct bio *bio, struct ioc_gq *iocg, u64 seek_pages = 0; u64 cost = 0; - /* Can't calculate cost for empty bio */ - if (!bio->bi_iter.bi_size) + /* Dataless WRITE|REQ_PREFLUSH (standalone flush) is priced below */ + if (!bio->bi_iter.bi_size && !(bio->bi_opf & REQ_PREFLUSH)) goto out; switch (bio_op(bio)) { @@ -2544,6 +2544,15 @@ static void calc_vtime_cost_builtin(struct bio *bio, struct ioc_gq *iocg, coef_page = ioc->params.lcoefs[LCOEF_RPAGE]; break; case REQ_OP_WRITE: + if (!bio->bi_iter.bi_size) { + /* + * dataless WRITE|REQ_PREFLUSH: standalone flush; + * at least one page so fast profiles still charge + */ + cost = max(ioc->params.lcoefs[LCOEF_WRANDIO], + ioc->params.lcoefs[LCOEF_WPAGE]); + goto out; + } coef_seqio = ioc->params.lcoefs[LCOEF_WSEQIO]; coef_randio = ioc->params.lcoefs[LCOEF_WRANDIO]; coef_page = ioc->params.lcoefs[LCOEF_WPAGE]; -- 2.43.0