* Re: [PATCH block-5.17] block: don't merge across cgroup boundaries if iocost or iolatency is active [not found] ` <107965ce-a29a-b5f4-ef87-63b753380891@kernel.dk> @ 2022-03-14 20:41 ` Tejun Heo 0 siblings, 0 replies; 4+ messages in thread From: Tejun Heo @ 2022-03-14 20:41 UTC (permalink / raw) To: Jens Axboe; +Cc: linux-block, kernel-team, linux-kernel, Josef Bacik On Mon, Mar 14, 2022 at 02:12:34PM -0600, Jens Axboe wrote: > > * Add WARN_ON_ONCE() on blkg mismatch in ioc_rqos_merge() so that we can > > easily notice similar failures in the future. > > > > * Make sure iocost enable/disable transitions only happen when iocost is > > actually enabled / disabled. > > Is there really no better way to do this than add a lot of expensive > checks to the fast path? > > Even just inverting the checks so that > > if (req->bio->bi_blkg != bio->bi_blkg) > ... > > is checked first would seem a lot saner. > > In any case, since this isn't a new regression, I'd feel a lot better > deferring it to 5.18. As discussed, the only risk of removing the disable/enable switch and always testing is ruining some merges for cases where blkcg is enabled but no control is applied, which shouldn't be a big problem. I'll redo the patch. Thanks. -- tejun ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 for-5.18/block] block: don't merge across cgroup boundaries if blkcg is enabled [not found] <Yi71WZ3O9/YViHSb@slm.duckdns.org> [not found] ` <107965ce-a29a-b5f4-ef87-63b753380891@kernel.dk> @ 2022-03-14 23:50 ` Tejun Heo 2022-03-15 0:30 ` [PATCH v3 " Tejun Heo 1 sibling, 1 reply; 4+ messages in thread From: Tejun Heo @ 2022-03-14 23:50 UTC (permalink / raw) To: Jens Axboe; +Cc: linux-block, kernel-team, linux-kernel, Josef Bacik blk-iocost and iolatency are cgroup aware rq-qos policies but they didn't disable merges across different cgroups. This obviously can lead to accounting and control errors but more importantly to priority inversions - e.g. an IO which belongs to a higher priority cgroup or IO class may end up getting throttled incorrectly because it gets merged to an IO issued from a low priority cgroup. Fix it by adding blk_cgroup_mergeable() which is called from merge paths and rejects cross-cgroup and cross-issue_as_root merges. v2: Dropped conditional enabling. Always disallow cross-blkcg merges for simpilcity. While this may spuriously prevent some merges for cases where blkcg is enabled but no control is applied, that is a small cross section. Signed-off-by: Tejun Heo <tj@kernel.org> Fixes: d70675121546 ("block: introduce blk-iolatency io controller") Cc: stable@vger.kernel.org # v4.19+ Cc: Josef Bacik <jbacik@fb.com> --- block/blk-merge.c | 11 +++++++++++ include/linux/blk-cgroup.h | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -9,6 +9,7 @@ #include <linux/blk-integrity.h> #include <linux/scatterlist.h> #include <linux/part_stat.h> +#include <linux/blk-cgroup.h> #include <trace/events/block.h> @@ -600,6 +601,9 @@ static inline unsigned int blk_rq_get_ma static inline int ll_new_hw_segment(struct request *req, struct bio *bio, unsigned int nr_phys_segs) { + if (!blk_cgroup_mergeable(req, bio)) + goto no_merge; + if (blk_integrity_merge_bio(req->q, req, bio) == false) goto no_merge; @@ -696,6 +700,9 @@ static int ll_merge_requests_fn(struct r if (total_phys_segments > blk_rq_get_max_segments(req)) return 0; + if (!blk_cgroup_mergeable(req, next->bio)) + return 0; + if (blk_integrity_merge_rq(q, req, next) == false) return 0; @@ -904,6 +911,10 @@ bool blk_rq_merge_ok(struct request *rq, if (bio_data_dir(bio) != rq_data_dir(rq)) return false; + /* don't merge across cgroup boundaries */ + if (!blk_cgroup_mergeable(rq, bio)) + return false; + /* only merge integrity protected bio into ditto rq */ if (blk_integrity_merge_bio(rq->q, rq, bio) == false) return false; --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -21,6 +21,7 @@ #include <linux/seq_file.h> #include <linux/radix-tree.h> #include <linux/blkdev.h> +#include <linux/blk-mq.h> #include <linux/atomic.h> #include <linux/kthread.h> #include <linux/fs.h> @@ -604,6 +605,21 @@ static inline void blkcg_clear_delay(str atomic_dec(&blkg->blkcg->css.cgroup->congestion_count); } +/** + * blk_cgroup_mergeable - Determine whether to allow or disallow merges + * @rq: request to merge into + * @bio: bio to merge + * + * @bio and @rq should belong to the same cgroup and their issue_as_root should + * match. The latter is necessary as we don't want to throttle e.g. a metadata + * update because it happens to be next to a regular IO. + */ +static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) +{ + return rq->bio->bi_blkg == bio->bi_blkg && + bio_issue_as_root_blkg(rq->bio) == bio_issue_as_root_blkg(bio); +} + void blk_cgroup_bio_start(struct bio *bio); void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta); void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay); @@ -659,6 +675,7 @@ static inline void blkg_put(struct blkcg static inline bool blkcg_punt_bio_submit(struct bio *bio) { return false; } static inline void blkcg_bio_issue_init(struct bio *bio) { } static inline void blk_cgroup_bio_start(struct bio *bio) { } +static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) { return true; } #define blk_queue_for_each_rl(rl, q) \ for ((rl) = &(q)->root_rl; (rl); (rl) = NULL) ^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v3 for-5.18/block] block: don't merge across cgroup boundaries if blkcg is enabled 2022-03-14 23:50 ` [PATCH v2 for-5.18/block] block: don't merge across cgroup boundaries if blkcg is enabled Tejun Heo @ 2022-03-15 0:30 ` Tejun Heo 2022-03-15 1:15 ` Jens Axboe 0 siblings, 1 reply; 4+ messages in thread From: Tejun Heo @ 2022-03-15 0:30 UTC (permalink / raw) To: Jens Axboe; +Cc: linux-block, kernel-team, linux-kernel, Josef Bacik blk-iocost and iolatency are cgroup aware rq-qos policies but they didn't disable merges across different cgroups. This obviously can lead to accounting and control errors but more importantly to priority inversions - e.g. an IO which belongs to a higher priority cgroup or IO class may end up getting throttled incorrectly because it gets merged to an IO issued from a low priority cgroup. Fix it by adding blk_cgroup_mergeable() which is called from merge paths and rejects cross-cgroup and cross-issue_as_root merges. Signed-off-by: Tejun Heo <tj@kernel.org> Fixes: d70675121546 ("block: introduce blk-iolatency io controller") Cc: stable@vger.kernel.org # v4.19+ Cc: Josef Bacik <jbacik@fb.com> --- v2 was tagged for-5.18/block but was still based on block-for-5.17. Refresh on top of for-5.18/block. My apologies about all the messiness. v3: Actually rebased on top of block/for-5.18. v2: Dropped conditional enabling. Always disallow cross-blkcg merges for simpilcity. While this may spuriously prevent some merges for cases where blkcg is enabled but no control is applied, that is a small cross section. block/blk-cgroup.h | 17 +++++++++++++++++ block/blk-merge.c | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 3e91803c4a555..47e1e38390c96 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -15,6 +15,7 @@ */ #include <linux/blk-cgroup.h> +#include <linux/blk-mq.h> /* percpu_counter batch for blkg_[rw]stats, per-cpu drift doesn't matter */ #define BLKG_STAT_CPU_BATCH (INT_MAX / 2) @@ -428,6 +429,21 @@ static inline void blkcg_clear_delay(struct blkcg_gq *blkg) atomic_dec(&blkg->blkcg->css.cgroup->congestion_count); } +/** + * blk_cgroup_mergeable - Determine whether to allow or disallow merges + * @rq: request to merge into + * @bio: bio to merge + * + * @bio and @rq should belong to the same cgroup and their issue_as_root should + * match. The latter is necessary as we don't want to throttle e.g. a metadata + * update because it happens to be next to a regular IO. + */ +static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) +{ + return rq->bio->bi_blkg == bio->bi_blkg && + bio_issue_as_root_blkg(rq->bio) == bio_issue_as_root_blkg(bio); +} + void blk_cgroup_bio_start(struct bio *bio); void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta); #else /* CONFIG_BLK_CGROUP */ @@ -467,6 +483,7 @@ static inline void blkg_put(struct blkcg_gq *blkg) { } static inline bool blkcg_punt_bio_submit(struct bio *bio) { return false; } static inline void blkcg_bio_issue_init(struct bio *bio) { } static inline void blk_cgroup_bio_start(struct bio *bio) { } +static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) { return true; } #define blk_queue_for_each_rl(rl, q) \ for ((rl) = &(q)->root_rl; (rl); (rl) = NULL) diff --git a/block/blk-merge.c b/block/blk-merge.c index 8d8177f71ebdb..ea6968313b4a8 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -9,6 +9,7 @@ #include <linux/blk-integrity.h> #include <linux/scatterlist.h> #include <linux/part_stat.h> +#include <linux/blk-cgroup.h> #include <trace/events/block.h> @@ -598,6 +599,9 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq, static inline int ll_new_hw_segment(struct request *req, struct bio *bio, unsigned int nr_phys_segs) { + if (!blk_cgroup_mergeable(req, bio)) + goto no_merge; + if (blk_integrity_merge_bio(req->q, req, bio) == false) goto no_merge; @@ -694,6 +698,9 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req, if (total_phys_segments > blk_rq_get_max_segments(req)) return 0; + if (!blk_cgroup_mergeable(req, next->bio)) + return 0; + if (blk_integrity_merge_rq(q, req, next) == false) return 0; @@ -902,6 +909,10 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) if (bio_data_dir(bio) != rq_data_dir(rq)) return false; + /* don't merge across cgroup boundaries */ + if (!blk_cgroup_mergeable(rq, bio)) + return false; + /* only merge integrity protected bio into ditto rq */ if (blk_integrity_merge_bio(rq->q, rq, bio) == false) return false; -- 2.35.1 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 for-5.18/block] block: don't merge across cgroup boundaries if blkcg is enabled 2022-03-15 0:30 ` [PATCH v3 " Tejun Heo @ 2022-03-15 1:15 ` Jens Axboe 0 siblings, 0 replies; 4+ messages in thread From: Jens Axboe @ 2022-03-15 1:15 UTC (permalink / raw) To: Tejun Heo; +Cc: Josef Bacik, linux-kernel, linux-block, kernel-team On Mon, 14 Mar 2022 14:30:11 -1000, Tejun Heo wrote: > blk-iocost and iolatency are cgroup aware rq-qos policies but they didn't > disable merges across different cgroups. This obviously can lead to > accounting and control errors but more importantly to priority inversions - > e.g. an IO which belongs to a higher priority cgroup or IO class may end up > getting throttled incorrectly because it gets merged to an IO issued from a > low priority cgroup. > > [...] Applied, thanks! [1/1] block: don't merge across cgroup boundaries if blkcg is enabled commit: 6b2b04590b51aa4cf395fcd185ce439cab5961dc Best regards, -- Jens Axboe ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-03-15 1:15 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <Yi71WZ3O9/YViHSb@slm.duckdns.org>
[not found] ` <107965ce-a29a-b5f4-ef87-63b753380891@kernel.dk>
2022-03-14 20:41 ` [PATCH block-5.17] block: don't merge across cgroup boundaries if iocost or iolatency is active Tejun Heo
2022-03-14 23:50 ` [PATCH v2 for-5.18/block] block: don't merge across cgroup boundaries if blkcg is enabled Tejun Heo
2022-03-15 0:30 ` [PATCH v3 " Tejun Heo
2022-03-15 1:15 ` Jens Axboe
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®