From: Greg Kroah-Hartman Date: Mon, 6 Jun 2022 18:06:29 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v5.10.121~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dda988a16b75e7df3dbdf694ffb67a7ca9da7b93;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: bfq-avoid-merging-queues-with-different-parents.patch bfq-drop-pointless-unlock-lock-pair.patch bfq-get-rid-of-__bio_blkcg-usage.patch bfq-make-sure-bfqg-for-which-we-are-queueing-requests-is-online.patch bfq-remove-pointless-bfq_init_rq-calls.patch block-fix-bio_clone_blkg_association-to-associate-with-proper-blkcg_gq.patch --- diff --git a/queue-5.10/bfq-avoid-merging-queues-with-different-parents.patch b/queue-5.10/bfq-avoid-merging-queues-with-different-parents.patch new file mode 100644 index 00000000000..07579b458b3 --- /dev/null +++ b/queue-5.10/bfq-avoid-merging-queues-with-different-parents.patch @@ -0,0 +1,86 @@ +From foo@baz Mon Jun 6 08:05:28 PM CEST 2022 +From: Jan Kara +Date: Mon, 6 Jun 2022 19:56:36 +0200 +Subject: bfq: Avoid merging queues with different parents +To: stable@vger.kernel.org +Cc: , Paolo Valente , Jens Axboe , Jan Kara , "yukuai (C)" , Christoph Hellwig +Message-ID: <20220606175655.8993-1-jack@suse.cz> + +From: Jan Kara + +commit c1cee4ab36acef271be9101590756ed0c0c374d9 upstream. + +It can happen that the parent of a bfqq changes between the moment we +decide two queues are worth to merge (and set bic->stable_merge_bfqq) +and the moment bfq_setup_merge() is called. This can happen e.g. because +the process submitted IO for a different cgroup and thus bfqq got +reparented. It can even happen that the bfqq we are merging with has +parent cgroup that is already offline and going to be destroyed in which +case the merge can lead to use-after-free issues such as: + +BUG: KASAN: use-after-free in __bfq_deactivate_entity+0x9cb/0xa50 +Read of size 8 at addr ffff88800693c0c0 by task runc:[2:INIT]/10544 + +CPU: 0 PID: 10544 Comm: runc:[2:INIT] Tainted: G E 5.15.2-0.g5fb85fd-default #1 openSUSE Tumbleweed (unreleased) f1f3b891c72369aebecd2e43e4641a6358867c70 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a-rebuilt.opensuse.org 04/01/2014 +Call Trace: + + dump_stack_lvl+0x46/0x5a + print_address_description.constprop.0+0x1f/0x140 + ? __bfq_deactivate_entity+0x9cb/0xa50 + kasan_report.cold+0x7f/0x11b + ? __bfq_deactivate_entity+0x9cb/0xa50 + __bfq_deactivate_entity+0x9cb/0xa50 + ? update_curr+0x32f/0x5d0 + bfq_deactivate_entity+0xa0/0x1d0 + bfq_del_bfqq_busy+0x28a/0x420 + ? resched_curr+0x116/0x1d0 + ? bfq_requeue_bfqq+0x70/0x70 + ? check_preempt_wakeup+0x52b/0xbc0 + __bfq_bfqq_expire+0x1a2/0x270 + bfq_bfqq_expire+0xd16/0x2160 + ? try_to_wake_up+0x4ee/0x1260 + ? bfq_end_wr_async_queues+0xe0/0xe0 + ? _raw_write_unlock_bh+0x60/0x60 + ? _raw_spin_lock_irq+0x81/0xe0 + bfq_idle_slice_timer+0x109/0x280 + ? bfq_dispatch_request+0x4870/0x4870 + __hrtimer_run_queues+0x37d/0x700 + ? enqueue_hrtimer+0x1b0/0x1b0 + ? kvm_clock_get_cycles+0xd/0x10 + ? ktime_get_update_offsets_now+0x6f/0x280 + hrtimer_interrupt+0x2c8/0x740 + +Fix the problem by checking that the parent of the two bfqqs we are +merging in bfq_setup_merge() is the same. + +Link: https://lore.kernel.org/linux-block/20211125172809.GC19572@quack2.suse.cz/ +CC: stable@vger.kernel.org +Fixes: 430a67f9d616 ("block, bfq: merge bursts of newly-created queues") +Tested-by: "yukuai (C)" +Signed-off-by: Jan Kara +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20220401102752.8599-2-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/bfq-iosched.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -2509,6 +2509,14 @@ bfq_setup_merge(struct bfq_queue *bfqq, + if (process_refs == 0 || new_process_refs == 0) + return NULL; + ++ /* ++ * Make sure merged queues belong to the same parent. Parents could ++ * have changed since the time we decided the two queues are suitable ++ * for merging. ++ */ ++ if (new_bfqq->entity.parent != bfqq->entity.parent) ++ return NULL; ++ + bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", + new_bfqq->pid); + diff --git a/queue-5.10/bfq-drop-pointless-unlock-lock-pair.patch b/queue-5.10/bfq-drop-pointless-unlock-lock-pair.patch new file mode 100644 index 00000000000..b898f328910 --- /dev/null +++ b/queue-5.10/bfq-drop-pointless-unlock-lock-pair.patch @@ -0,0 +1,42 @@ +From foo@baz Mon Jun 6 08:05:28 PM CEST 2022 +From: Jan Kara +Date: Mon, 6 Jun 2022 19:56:37 +0200 +Subject: bfq: Drop pointless unlock-lock pair +To: stable@vger.kernel.org +Cc: , Paolo Valente , Jens Axboe , Jan Kara , "yukuai (C)" , Christoph Hellwig +Message-ID: <20220606175655.8993-2-jack@suse.cz> + +From: Jan Kara + +commit fc84e1f941b91221092da5b3102ec82da24c5673 upstream. + +In bfq_insert_request() we unlock bfqd->lock only to call +trace_block_rq_insert() and then lock bfqd->lock again. This is really +pointless since tracing is disabled if we really care about performance +and even if the tracepoint is enabled, it is a quick call. + +CC: stable@vger.kernel.org +Tested-by: "yukuai (C)" +Signed-off-by: Jan Kara +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20220401102752.8599-5-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/bfq-iosched.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -5537,11 +5537,8 @@ static void bfq_insert_request(struct bl + return; + } + +- spin_unlock_irq(&bfqd->lock); +- + blk_mq_sched_request_inserted(rq); + +- spin_lock_irq(&bfqd->lock); + bfqq = bfq_init_rq(rq); + if (!bfqq || at_head || blk_rq_is_passthrough(rq)) { + if (at_head) diff --git a/queue-5.10/bfq-get-rid-of-__bio_blkcg-usage.patch b/queue-5.10/bfq-get-rid-of-__bio_blkcg-usage.patch new file mode 100644 index 00000000000..4e82a6efcc1 --- /dev/null +++ b/queue-5.10/bfq-get-rid-of-__bio_blkcg-usage.patch @@ -0,0 +1,199 @@ +From foo@baz Mon Jun 6 08:05:28 PM CEST 2022 +From: Jan Kara +Date: Mon, 6 Jun 2022 19:56:39 +0200 +Subject: bfq: Get rid of __bio_blkcg() usage +To: stable@vger.kernel.org +Cc: , Paolo Valente , Jens Axboe , Jan Kara , "yukuai (C)" , Christoph Hellwig +Message-ID: <20220606175655.8993-4-jack@suse.cz> + +From: Jan Kara + +commit 4e54a2493e582361adc3bfbf06c7d50d19d18837 upstream. + +BFQ usage of __bio_blkcg() is a relict from the past. Furthermore if bio +would not be associated with any blkcg, the usage of __bio_blkcg() in +BFQ is prone to races with the task being migrated between cgroups as +__bio_blkcg() calls at different places could return different blkcgs. + +Convert BFQ to the new situation where bio->bi_blkg is initialized in +bio_set_dev() and thus practically always valid. This allows us to save +blkcg_gq lookup and noticeably simplify the code. + +CC: stable@vger.kernel.org +Fixes: 0fe061b9f03c ("blkcg: fix ref count issue with bio_blkcg() using task_css") +Tested-by: "yukuai (C)" +Signed-off-by: Jan Kara +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20220401102752.8599-8-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/bfq-cgroup.c | 63 ++++++++++++++++++---------------------------------- + block/bfq-iosched.c | 10 -------- + block/bfq-iosched.h | 3 -- + 3 files changed, 25 insertions(+), 51 deletions(-) + +--- a/block/bfq-cgroup.c ++++ b/block/bfq-cgroup.c +@@ -582,27 +582,11 @@ static void bfq_group_set_parent(struct + entity->sched_data = &parent->sched_data; + } + +-static struct bfq_group *bfq_lookup_bfqg(struct bfq_data *bfqd, +- struct blkcg *blkcg) ++static void bfq_link_bfqg(struct bfq_data *bfqd, struct bfq_group *bfqg) + { +- struct blkcg_gq *blkg; +- +- blkg = blkg_lookup(blkcg, bfqd->queue); +- if (likely(blkg)) +- return blkg_to_bfqg(blkg); +- return NULL; +-} +- +-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, +- struct blkcg *blkcg) +-{ +- struct bfq_group *bfqg, *parent; ++ struct bfq_group *parent; + struct bfq_entity *entity; + +- bfqg = bfq_lookup_bfqg(bfqd, blkcg); +- if (unlikely(!bfqg)) +- return NULL; +- + /* + * Update chain of bfq_groups as we might be handling a leaf group + * which, along with some of its relatives, has not been hooked yet +@@ -619,8 +603,15 @@ struct bfq_group *bfq_find_set_group(str + bfq_group_set_parent(curr_bfqg, parent); + } + } ++} + +- return bfqg; ++struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio) ++{ ++ struct blkcg_gq *blkg = bio->bi_blkg; ++ ++ if (!blkg) ++ return bfqd->root_group; ++ return blkg_to_bfqg(blkg); + } + + /** +@@ -696,25 +687,15 @@ void bfq_bfqq_move(struct bfq_data *bfqd + * Move bic to blkcg, assuming that bfqd->lock is held; which makes + * sure that the reference to cgroup is valid across the call (see + * comments in bfq_bic_update_cgroup on this issue) +- * +- * NOTE: an alternative approach might have been to store the current +- * cgroup in bfqq and getting a reference to it, reducing the lookup +- * time here, at the price of slightly more complex code. + */ +-static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, +- struct bfq_io_cq *bic, +- struct blkcg *blkcg) ++static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd, ++ struct bfq_io_cq *bic, ++ struct bfq_group *bfqg) + { + struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); + struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); +- struct bfq_group *bfqg; + struct bfq_entity *entity; + +- bfqg = bfq_find_set_group(bfqd, blkcg); +- +- if (unlikely(!bfqg)) +- bfqg = bfqd->root_group; +- + if (async_bfqq) { + entity = &async_bfqq->entity; + +@@ -766,20 +747,24 @@ static struct bfq_group *__bfq_bic_chang + void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) + { + struct bfq_data *bfqd = bic_to_bfqd(bic); +- struct bfq_group *bfqg = NULL; ++ struct bfq_group *bfqg = bfq_bio_bfqg(bfqd, bio); + uint64_t serial_nr; + +- rcu_read_lock(); +- serial_nr = __bio_blkcg(bio)->css.serial_nr; ++ serial_nr = bfqg_to_blkg(bfqg)->blkcg->css.serial_nr; + + /* + * Check whether blkcg has changed. The condition may trigger + * spuriously on a newly created cic but there's no harm. + */ + if (unlikely(!bfqd) || likely(bic->blkcg_serial_nr == serial_nr)) +- goto out; ++ return; + +- bfqg = __bfq_bic_change_cgroup(bfqd, bic, __bio_blkcg(bio)); ++ /* ++ * New cgroup for this process. Make sure it is linked to bfq internal ++ * cgroup hierarchy. ++ */ ++ bfq_link_bfqg(bfqd, bfqg); ++ __bfq_bic_change_cgroup(bfqd, bic, bfqg); + /* + * Update blkg_path for bfq_log_* functions. We cache this + * path, and update it here, for the following +@@ -832,8 +817,6 @@ void bfq_bic_update_cgroup(struct bfq_io + */ + blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path)); + bic->blkcg_serial_nr = serial_nr; +-out: +- rcu_read_unlock(); + } + + /** +@@ -1451,7 +1434,7 @@ void bfq_end_wr_async(struct bfq_data *b + bfq_end_wr_async_queues(bfqd, bfqd->root_group); + } + +-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, struct blkcg *blkcg) ++struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio) + { + return bfqd->root_group; + } +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -5162,14 +5162,7 @@ static struct bfq_queue *bfq_get_queue(s + struct bfq_queue *bfqq; + struct bfq_group *bfqg; + +- rcu_read_lock(); +- +- bfqg = bfq_find_set_group(bfqd, __bio_blkcg(bio)); +- if (!bfqg) { +- bfqq = &bfqd->oom_bfqq; +- goto out; +- } +- ++ bfqg = bfq_bio_bfqg(bfqd, bio); + if (!is_sync) { + async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, + ioprio); +@@ -5213,7 +5206,6 @@ static struct bfq_queue *bfq_get_queue(s + out: + bfqq->ref++; /* get a process reference to this queue */ + bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, bfqq->ref); +- rcu_read_unlock(); + return bfqq; + } + +--- a/block/bfq-iosched.h ++++ b/block/bfq-iosched.h +@@ -984,8 +984,7 @@ void bfq_bfqq_move(struct bfq_data *bfqd + void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg); + void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio); + void bfq_end_wr_async(struct bfq_data *bfqd); +-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, +- struct blkcg *blkcg); ++struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio); + struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg); + struct bfq_group *bfqq_group(struct bfq_queue *bfqq); + struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node); diff --git a/queue-5.10/bfq-make-sure-bfqg-for-which-we-are-queueing-requests-is-online.patch b/queue-5.10/bfq-make-sure-bfqg-for-which-we-are-queueing-requests-is-online.patch new file mode 100644 index 00000000000..d3d3ca928a2 --- /dev/null +++ b/queue-5.10/bfq-make-sure-bfqg-for-which-we-are-queueing-requests-is-online.patch @@ -0,0 +1,57 @@ +From foo@baz Mon Jun 6 08:05:28 PM CEST 2022 +From: Jan Kara +Date: Mon, 6 Jun 2022 19:56:40 +0200 +Subject: bfq: Make sure bfqg for which we are queueing requests is online +To: stable@vger.kernel.org +Cc: , Paolo Valente , Jens Axboe , Jan Kara , "yukuai (C)" , Christoph Hellwig +Message-ID: <20220606175655.8993-5-jack@suse.cz> + +From: Jan Kara + +commit 075a53b78b815301f8d3dd1ee2cd99554e34f0dd upstream. + +Bios queued into BFQ IO scheduler can be associated with a cgroup that +was already offlined. This may then cause insertion of this bfq_group +into a service tree. But this bfq_group will get freed as soon as last +bio associated with it is completed leading to use after free issues for +service tree users. Fix the problem by making sure we always operate on +online bfq_group. If the bfq_group associated with the bio is not +online, we pick the first online parent. + +CC: stable@vger.kernel.org +Fixes: e21b7a0b9887 ("block, bfq: add full hierarchical scheduling and cgroups support") +Tested-by: "yukuai (C)" +Signed-off-by: Jan Kara +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20220401102752.8599-9-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/bfq-cgroup.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/block/bfq-cgroup.c ++++ b/block/bfq-cgroup.c +@@ -608,10 +608,19 @@ static void bfq_link_bfqg(struct bfq_dat + struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio) + { + struct blkcg_gq *blkg = bio->bi_blkg; ++ struct bfq_group *bfqg; + +- if (!blkg) +- return bfqd->root_group; +- return blkg_to_bfqg(blkg); ++ while (blkg) { ++ bfqg = blkg_to_bfqg(blkg); ++ if (bfqg->online) { ++ bio_associate_blkg_from_css(bio, &blkg->blkcg->css); ++ return bfqg; ++ } ++ blkg = blkg->parent; ++ } ++ bio_associate_blkg_from_css(bio, ++ &bfqg_to_blkg(bfqd->root_group)->blkcg->css); ++ return bfqd->root_group; + } + + /** diff --git a/queue-5.10/bfq-remove-pointless-bfq_init_rq-calls.patch b/queue-5.10/bfq-remove-pointless-bfq_init_rq-calls.patch new file mode 100644 index 00000000000..d79770280d7 --- /dev/null +++ b/queue-5.10/bfq-remove-pointless-bfq_init_rq-calls.patch @@ -0,0 +1,87 @@ +From foo@baz Mon Jun 6 08:05:28 PM CEST 2022 +From: Jan Kara +Date: Mon, 6 Jun 2022 19:56:38 +0200 +Subject: bfq: Remove pointless bfq_init_rq() calls +To: stable@vger.kernel.org +Cc: , Paolo Valente , Jens Axboe , Jan Kara , "yukuai (C)" , Christoph Hellwig +Message-ID: <20220606175655.8993-3-jack@suse.cz> + +From: Jan Kara + +commit 5f550ede5edf846ecc0067be1ba80514e6fe7f8e upstream. + +We call bfq_init_rq() from request merging functions where requests we +get should have already gone through bfq_init_rq() during insert and +anyway we want to do anything only if the request is already tracked by +BFQ. So replace calls to bfq_init_rq() with RQ_BFQQ() instead to simply +skip requests untracked by BFQ. We move bfq_init_rq() call in +bfq_insert_request() a bit earlier to cover request merging and thus +can transfer FIFO position in case of a merge. + +CC: stable@vger.kernel.org +Tested-by: "yukuai (C)" +Signed-off-by: Jan Kara +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20220401102752.8599-6-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/bfq-iosched.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -2267,8 +2267,6 @@ static int bfq_request_merge(struct requ + return ELEVATOR_NO_MERGE; + } + +-static struct bfq_queue *bfq_init_rq(struct request *rq); +- + static void bfq_request_merged(struct request_queue *q, struct request *req, + enum elv_merge type) + { +@@ -2277,7 +2275,7 @@ static void bfq_request_merged(struct re + blk_rq_pos(req) < + blk_rq_pos(container_of(rb_prev(&req->rb_node), + struct request, rb_node))) { +- struct bfq_queue *bfqq = bfq_init_rq(req); ++ struct bfq_queue *bfqq = RQ_BFQQ(req); + struct bfq_data *bfqd; + struct request *prev, *next_rq; + +@@ -2329,8 +2327,8 @@ static void bfq_request_merged(struct re + static void bfq_requests_merged(struct request_queue *q, struct request *rq, + struct request *next) + { +- struct bfq_queue *bfqq = bfq_init_rq(rq), +- *next_bfqq = bfq_init_rq(next); ++ struct bfq_queue *bfqq = RQ_BFQQ(rq), ++ *next_bfqq = RQ_BFQQ(next); + + if (!bfqq) + return; +@@ -5518,6 +5516,8 @@ static inline void bfq_update_insert_sta + unsigned int cmd_flags) {} + #endif /* CONFIG_BFQ_CGROUP_DEBUG */ + ++static struct bfq_queue *bfq_init_rq(struct request *rq); ++ + static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq, + bool at_head) + { +@@ -5532,6 +5532,7 @@ static void bfq_insert_request(struct bl + bfqg_stats_update_legacy_io(q, rq); + #endif + spin_lock_irq(&bfqd->lock); ++ bfqq = bfq_init_rq(rq); + if (blk_mq_sched_try_insert_merge(q, rq)) { + spin_unlock_irq(&bfqd->lock); + return; +@@ -5539,7 +5540,6 @@ static void bfq_insert_request(struct bl + + blk_mq_sched_request_inserted(rq); + +- bfqq = bfq_init_rq(rq); + if (!bfqq || at_head || blk_rq_is_passthrough(rq)) { + if (at_head) + list_add(&rq->queuelist, &bfqd->dispatch); diff --git a/queue-5.10/block-fix-bio_clone_blkg_association-to-associate-with-proper-blkcg_gq.patch b/queue-5.10/block-fix-bio_clone_blkg_association-to-associate-with-proper-blkcg_gq.patch new file mode 100644 index 00000000000..beb48fabe6c --- /dev/null +++ b/queue-5.10/block-fix-bio_clone_blkg_association-to-associate-with-proper-blkcg_gq.patch @@ -0,0 +1,53 @@ +From foo@baz Mon Jun 6 08:05:28 PM CEST 2022 +From: Jan Kara +Date: Mon, 6 Jun 2022 19:56:41 +0200 +Subject: block: fix bio_clone_blkg_association() to associate with proper blkcg_gq +To: stable@vger.kernel.org +Cc: , Paolo Valente , Jens Axboe , Jan Kara , Logan Gunthorpe , Donald Buczek , Christoph Hellwig +Message-ID: <20220606175655.8993-6-jack@suse.cz> + +From: Jan Kara + +commit 22b106e5355d6e7a9c3b5cb5ed4ef22ae585ea94 upstream. + +Commit d92c370a16cb ("block: really clone the block cgroup in +bio_clone_blkg_association") changed bio_clone_blkg_association() to +just clone bio->bi_blkg reference from source to destination bio. This +is however wrong if the source and destination bios are against +different block devices because struct blkcg_gq is different for each +bdev-blkcg pair. This will result in IOs being accounted (and throttled +as a result) multiple times against the same device (src bdev) while +throttling of the other device (dst bdev) is ignored. In case of BFQ the +inconsistency can even result in crashes in bfq_bic_update_cgroup(). +Fix the problem by looking up correct blkcg_gq for the cloned bio. + +Reported-by: Logan Gunthorpe +Reported-and-tested-by: Donald Buczek +Fixes: d92c370a16cb ("block: really clone the block cgroup in bio_clone_blkg_association") +CC: stable@vger.kernel.org +Reviewed-by: Christoph Hellwig +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20220602081242.7731-1-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +--- + block/blk-cgroup.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/block/blk-cgroup.c ++++ b/block/blk-cgroup.c +@@ -1892,12 +1892,8 @@ EXPORT_SYMBOL_GPL(bio_associate_blkg); + */ + void bio_clone_blkg_association(struct bio *dst, struct bio *src) + { +- if (src->bi_blkg) { +- if (dst->bi_blkg) +- blkg_put(dst->bi_blkg); +- blkg_get(src->bi_blkg); +- dst->bi_blkg = src->bi_blkg; +- } ++ if (src->bi_blkg) ++ bio_associate_blkg_from_css(dst, &bio_blkcg(src)->css); + } + EXPORT_SYMBOL_GPL(bio_clone_blkg_association); + diff --git a/queue-5.10/series b/queue-5.10/series index 777beaae7fe..8f6ca7b8b6f 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -438,3 +438,9 @@ xfs-assert-in-xfs_btree_del_cursor-should-take-into-account-error.patch kseltest-cgroup-make-test_stress.sh-work-if-run-interactively.patch thermal-core-fix-a-uaf-bug-in-__thermal_cooling_device_register.patch thermal-core-fix-memory-leak-in-the-error-path.patch +bfq-avoid-merging-queues-with-different-parents.patch +bfq-drop-pointless-unlock-lock-pair.patch +bfq-remove-pointless-bfq_init_rq-calls.patch +bfq-get-rid-of-__bio_blkcg-usage.patch +bfq-make-sure-bfqg-for-which-we-are-queueing-requests-is-online.patch +block-fix-bio_clone_blkg_association-to-associate-with-proper-blkcg_gq.patch