]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 Jun 2026 10:14:03 +0000 (15:44 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 16 Jun 2026 10:14:03 +0000 (15:44 +0530)
added patches:
block-fix-handling-of-dead-zone-write-plugs.patch

queue-6.12/block-fix-handling-of-dead-zone-write-plugs.patch [new file with mode: 0644]
queue-6.12/series

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 (file)
index 0000000..d6c9c44
--- /dev/null
@@ -0,0 +1,102 @@
+From 836efd35c472d89c838d7b17ef339ddb3286ffc5 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Wed, 13 May 2026 20:11:29 +0900
+Subject: block: fix handling of dead zone write plugs
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+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 <shinichiro.kawasaki@wdc.com>
+Fixes: b7d4ffb51037 ("block: fix zone write plug removal")
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Tested-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Link: https://patch.msgid.link/20260513111129.108809-1-dlemoal@kernel.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+[ context conflict due to different line offsets in blk-zoned.c ]
+Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index 534f8b7b26215943126313fee9116c8583a79aa0..7dc96baf167847bac0a10ca900c1f8517ede420d 100644 (file)
@@ -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