From: Greg Kroah-Hartman Date: Tue, 16 Jun 2026 10:14:03 +0000 (+0530) Subject: 6.12-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ea6ea83d5eff90c839ef70c0fec364ae1cc1cb4a;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: block-fix-handling-of-dead-zone-write-plugs.patch --- diff --git a/queue-6.12/block-fix-handling-of-dead-zone-write-plugs.patch b/queue-6.12/block-fix-handling-of-dead-zone-write-plugs.patch new file mode 100644 index 0000000000..d6c9c44db9 --- /dev/null +++ b/queue-6.12/block-fix-handling-of-dead-zone-write-plugs.patch @@ -0,0 +1,102 @@ +From 836efd35c472d89c838d7b17ef339ddb3286ffc5 Mon Sep 17 00:00:00 2001 +From: Damien Le Moal +Date: Wed, 13 May 2026 20:11:29 +0900 +Subject: block: fix handling of dead zone write plugs + +From: Damien Le Moal + +commit 836efd35c472d89c838d7b17ef339ddb3286ffc5 upstream. + +Shin'ichiro reported hard to reproduce unaligned write errors with zoned +block devices. Under normal operation conditions (e.g. running XFS on an +SMR disk), these errors are nearly impossible to trigger. But using a +"slow" kernel with many debug options enables and some specific use +cases (e.g. fio zbd test case 46), the errors can be reproduced fairly +easily. + +The unaligned write errors come from mishandling a valid reference +counting pattern of zone write plugs. Such pattern triggers for instance +if a process A writes a zone (not necessarilly to the full state), +another process B immediately resets the zone and immediately following +the completion of the zone reset, starts issuing writes to the zone. +With such pattern, in some cases, the zone write plugs worker thread of +the device may still be holding a reference to the zone write plug of +the zone taken when process A was writing to the zone. The following +zone reset from process B marks the zone as dead but does not remove the +zone write plug from the device hash table as a reference to the plug +still exist. Once process B starts issuing new writes, the zone write +plug is seen as dead and the writes from process B are immediately +failed, despite this write pattern being perfectly legal. + +Fix this by allowing restoring a dead zone write plug to a live state if +a write is issued to the zone when the zone is: marked as dead, empty +and the write sector corresponds to the first sector of the zone (that +is, the write is aligned to the zone write pointer). This is done with +the new helper function disk_check_zone_wplug_dead(), which restores a +dead zone write plug to a live state by clearing the BLK_ZONE_WPLUG_DEAD +flag and restoring the initial reference to the zone write plug taken +when the plug was added to the device hash table. + +Reported-by: Shin'ichiro Kawasaki +Fixes: b7d4ffb51037 ("block: fix zone write plug removal") +Signed-off-by: Damien Le Moal +Tested-by: Shin'ichiro Kawasaki +Link: https://patch.msgid.link/20260513111129.108809-1-dlemoal@kernel.org +Signed-off-by: Jens Axboe +[ context conflict due to different line offsets in blk-zoned.c ] +Signed-off-by: Gyokhan Kochmarla +Signed-off-by: Greg Kroah-Hartman + +--- + block/blk-zoned.c | 32 +++++++++++++++++++++++++++----- + 1 file changed, 27 insertions(+), 5 deletions(-) + +--- a/block/blk-zoned.c ++++ b/block/blk-zoned.c +@@ -517,6 +517,28 @@ static void disk_mark_zone_wplug_dead(st + } + } + ++static inline bool disk_check_zone_wplug_dead(struct blk_zone_wplug *zwplug) ++{ ++ if (!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)) ++ return false; ++ ++ /* ++ * If a new write is received right after a zone reset completes and ++ * while the disk_zone_wplugs_worker() thread has not yet released the ++ * reference on the zone write plug after processing the last write to ++ * the zone, then the new write BIO will see the zone write plug marked ++ * as dead. This case is however a false positive and a perfectly valid ++ * pattern. In such case, restore the zone write plug to a live one. ++ */ ++ if (!zwplug->wp_offset && bio_list_empty(&zwplug->bio_list)) { ++ zwplug->flags &= ~BLK_ZONE_WPLUG_DEAD; ++ refcount_inc(&zwplug->ref); ++ return false; ++ } ++ ++ return true; ++} ++ + static void blk_zone_wplug_bio_work(struct work_struct *work); + + /* +@@ -1037,12 +1059,12 @@ static bool blk_zone_wplug_handle_write( + } + + /* +- * If we got a zone write plug marked as dead, then the user is issuing +- * writes to a full zone, or without synchronizing with zone reset or +- * zone finish operations. In such case, fail the BIO to signal this +- * invalid usage. ++ * Check if we got a zone write plug marked as dead. If yes, then the ++ * user is likely issuing writes to a full zone, or without ++ * synchronizing with zone reset or zone finish operations. In such ++ * case, fail the BIO to signal this invalid usage. + */ +- if (zwplug->flags & BLK_ZONE_WPLUG_DEAD) { ++ if (disk_check_zone_wplug_dead(zwplug)) { + spin_unlock_irqrestore(&zwplug->lock, flags); + disk_put_zone_wplug(zwplug); + bio_io_error(bio); diff --git a/queue-6.12/series b/queue-6.12/series index 534f8b7b26..7dc96baf16 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -247,3 +247,4 @@ ipmi-ssif-null-thread-on-error.patch ipvs-skip-ipv6-extension-headers-for-csum-checks.patch vsock-virtio-fix-potential-unbounded-skb-queue.patch vsock-virtio-fix-skb-overhead-accounting-to-preserve-full-buf_alloc.patch +block-fix-handling-of-dead-zone-write-plugs.patch