From: Sasha Levin Date: Tue, 10 Jan 2023 15:19:32 +0000 (-0500) Subject: Fixes for 6.0 X-Git-Tag: v5.15.87~24^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=499f131031df6468ea4b7774b46feb357add6798;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.0 Signed-off-by: Sasha Levin --- diff --git a/queue-6.0/btrfs-handle-case-when-repair-happens-with-dev-repla.patch b/queue-6.0/btrfs-handle-case-when-repair-happens-with-dev-repla.patch new file mode 100644 index 00000000000..7e78652e028 --- /dev/null +++ b/queue-6.0/btrfs-handle-case-when-repair-happens-with-dev-repla.patch @@ -0,0 +1,115 @@ +From 7d511ebaf5a6617ee2f385a24047d01dfc3116fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Jan 2023 09:02:21 +0800 +Subject: btrfs: handle case when repair happens with dev-replace +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Qu Wenruo + +[ Upstream commit d73a27b86fc722c28a26ec64002e3a7dc86d1c07 ] + +[BUG] +There is a bug report that a BUG_ON() in btrfs_repair_io_failure() +(originally repair_io_failure() in v6.0 kernel) got triggered when +replacing a unreliable disk: + + BTRFS warning (device sda1): csum failed root 257 ino 2397453 off 39624704 csum 0xb0d18c75 expected csum 0x4dae9c5e mirror 3 + kernel BUG at fs/btrfs/extent_io.c:2380! + invalid opcode: 0000 [#1] PREEMPT SMP NOPTI + CPU: 9 PID: 3614331 Comm: kworker/u257:2 Tainted: G OE 6.0.0-5-amd64 #1 Debian 6.0.10-2 + Hardware name: Micro-Star International Co., Ltd. MS-7C60/TRX40 PRO WIFI (MS-7C60), BIOS 2.70 07/01/2021 + Workqueue: btrfs-endio btrfs_end_bio_work [btrfs] + RIP: 0010:repair_io_failure+0x24a/0x260 [btrfs] + Call Trace: + + clean_io_failure+0x14d/0x180 [btrfs] + end_bio_extent_readpage+0x412/0x6e0 [btrfs] + ? __switch_to+0x106/0x420 + process_one_work+0x1c7/0x380 + worker_thread+0x4d/0x380 + ? rescuer_thread+0x3a0/0x3a0 + kthread+0xe9/0x110 + ? kthread_complete_and_exit+0x20/0x20 + ret_from_fork+0x22/0x30 + +[CAUSE] + +Before the BUG_ON(), we got some read errors from the replace target +first, note the mirror number (3, which is beyond RAID1 duplication, +thus it's read from the replace target device). + +Then at the BUG_ON() location, we are trying to writeback the repaired +sectors back the failed device. + +The check looks like this: + + ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, logical, + &map_length, &bioc, mirror_num); + if (ret) + goto out_counter_dec; + BUG_ON(mirror_num != bioc->mirror_num); + +But inside btrfs_map_block(), we can modify bioc->mirror_num especially +for dev-replace: + + if (dev_replace_is_ongoing && mirror_num == map->num_stripes + 1 && + !need_full_stripe(op) && dev_replace->tgtdev != NULL) { + ret = get_extra_mirror_from_replace(fs_info, logical, *length, + dev_replace->srcdev->devid, + &mirror_num, + &physical_to_patch_in_first_stripe); + patch_the_first_stripe_for_dev_replace = 1; + } + +Thus if we're repairing the replace target device, we're going to +trigger that BUG_ON(). + +But in reality, the read failure from the replace target device may be +that, our replace hasn't reached the range we're reading, thus we're +reading garbage, but with replace running, the range would be properly +filled later. + +Thus in that case, we don't need to do anything but let the replace +routine to handle it. + +[FIX] +Instead of a BUG_ON(), just skip the repair if we're repairing the +device replace target device. + +Reported-by: 小太 +Link: https://lore.kernel.org/linux-btrfs/CACsxjPYyJGQZ+yvjzxA1Nn2LuqkYqTCcUH43S=+wXhyf8S00Ag@mail.gmail.com/ +CC: stable@vger.kernel.org # 6.0+ +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index cf4f19e80e2f..0982995177a6 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2377,7 +2377,16 @@ static int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start, + &map_length, &bioc, mirror_num); + if (ret) + goto out_counter_dec; +- BUG_ON(mirror_num != bioc->mirror_num); ++ /* ++ * This happens when dev-replace is also running, and the ++ * mirror_num indicates the dev-replace target. ++ * ++ * In this case, we don't need to do anything, as the read ++ * error just means the replace progress hasn't reached our ++ * read range, and later replace routine would handle it well. ++ */ ++ if (mirror_num != bioc->mirror_num) ++ goto out_counter_dec; + } + + sector = bioc->stripes[bioc->mirror_num - 1].physical >> 9; +-- +2.35.1 + diff --git a/queue-6.0/series b/queue-6.0/series index 027a9ccc03d..35a16499eb8 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -137,3 +137,6 @@ of-fdt-run-soc-memory-setup-when-early_init_dt_scan_memory-fails.patch drm-amdkfd-fix-kernel-warning-during-topology-setup.patch drm-i915-gvt-fix-gvt-debugfs-destroy.patch drm-i915-gvt-fix-vgpu-debugfs-clean-in-remove.patch +virtio-blk-use-a-helper-to-handle-request-queuing-er.patch +virtio_blk-fix-signedness-bug-in-virtblk_prep_rq.patch +btrfs-handle-case-when-repair-happens-with-dev-repla.patch diff --git a/queue-6.0/virtio-blk-use-a-helper-to-handle-request-queuing-er.patch b/queue-6.0/virtio-blk-use-a-helper-to-handle-request-queuing-er.patch new file mode 100644 index 00000000000..22bef4383b7 --- /dev/null +++ b/queue-6.0/virtio-blk-use-a-helper-to-handle-request-queuing-er.patch @@ -0,0 +1,78 @@ +From 48d43a447997d6abccf7fcb125251a8047c1a1ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Oct 2022 23:41:26 -0400 +Subject: virtio-blk: use a helper to handle request queuing errors + +From: Dmitry Fomichev + +[ Upstream commit 258896fcc786b4e7db238eba26f6dd080e0ff41e ] + +Define a new helper function, virtblk_fail_to_queue(), to +clean up the error handling code in virtio_queue_rq(). + +Signed-off-by: Dmitry Fomichev +Message-Id: <20221016034127.330942-2-dmitry.fomichev@wdc.com> +Signed-off-by: Michael S. Tsirkin +Stable-dep-of: a26116c1e740 ("virtio_blk: Fix signedness bug in virtblk_prep_rq()") +Signed-off-by: Sasha Levin +--- + drivers/block/virtio_blk.c | 29 ++++++++++++++++------------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index dd9a05174726..b3b1191281ea 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -311,6 +311,19 @@ static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx) + virtqueue_notify(vq->vq); + } + ++static blk_status_t virtblk_fail_to_queue(struct request *req, int rc) ++{ ++ virtblk_cleanup_cmd(req); ++ switch (rc) { ++ case -ENOSPC: ++ return BLK_STS_DEV_RESOURCE; ++ case -ENOMEM: ++ return BLK_STS_RESOURCE; ++ default: ++ return BLK_STS_IOERR; ++ } ++} ++ + static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx, + struct virtio_blk *vblk, + struct request *req, +@@ -323,10 +336,8 @@ static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx, + return status; + + vbr->sg_table.nents = virtblk_map_data(hctx, req, vbr); +- if (unlikely(vbr->sg_table.nents < 0)) { +- virtblk_cleanup_cmd(req); +- return BLK_STS_RESOURCE; +- } ++ if (unlikely(vbr->sg_table.nents < 0)) ++ return virtblk_fail_to_queue(req, -ENOMEM); + + blk_mq_start_request(req); + +@@ -360,15 +371,7 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx, + blk_mq_stop_hw_queue(hctx); + spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); + virtblk_unmap_data(req, vbr); +- virtblk_cleanup_cmd(req); +- switch (err) { +- case -ENOSPC: +- return BLK_STS_DEV_RESOURCE; +- case -ENOMEM: +- return BLK_STS_RESOURCE; +- default: +- return BLK_STS_IOERR; +- } ++ return virtblk_fail_to_queue(req, err); + } + + if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq)) +-- +2.35.1 + diff --git a/queue-6.0/virtio_blk-fix-signedness-bug-in-virtblk_prep_rq.patch b/queue-6.0/virtio_blk-fix-signedness-bug-in-virtblk_prep_rq.patch new file mode 100644 index 00000000000..8deaca46721 --- /dev/null +++ b/queue-6.0/virtio_blk-fix-signedness-bug-in-virtblk_prep_rq.patch @@ -0,0 +1,53 @@ +From 4a3a0722635d5147d04a5906a6e993cd23799f42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 17:41:26 -0300 +Subject: virtio_blk: Fix signedness bug in virtblk_prep_rq() + +From: Rafael Mendonca + +[ Upstream commit a26116c1e74028914f281851488546c91cbae57d ] + +The virtblk_map_data() function returns negative error codes, however, the +'nents' field of vbr->sg_table is an unsigned int, which causes the error +handling not to work correctly. + +Cc: stable@vger.kernel.org +Fixes: 0e9911fa768f ("virtio-blk: support mq_ops->queue_rqs()") +Signed-off-by: Rafael Mendonca +Message-Id: <20221021204126.927603-1-rafaelmendsr@gmail.com> +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Stefano Garzarella +Reviewed-by: Suwan Kim +Reviewed-by: Stefan Hajnoczi +Acked-by: Jason Wang +Signed-off-by: Sasha Levin +--- + drivers/block/virtio_blk.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index b3b1191281ea..53931fcef0d5 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -330,14 +330,16 @@ static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx, + struct virtblk_req *vbr) + { + blk_status_t status; ++ int num; + + status = virtblk_setup_cmd(vblk->vdev, req, vbr); + if (unlikely(status)) + return status; + +- vbr->sg_table.nents = virtblk_map_data(hctx, req, vbr); +- if (unlikely(vbr->sg_table.nents < 0)) ++ num = virtblk_map_data(hctx, req, vbr); ++ if (unlikely(num < 0)) + return virtblk_fail_to_queue(req, -ENOMEM); ++ vbr->sg_table.nents = num; + + blk_mq_start_request(req); + +-- +2.35.1 +