63 lines
2.5 KiB
Diff
63 lines
2.5 KiB
Diff
From 32eefb128e8ca539632595379da05e5662b72161 Mon Sep 17 00:00:00 2001
|
|
From: Damien Le Moal <dlemoal@kernel.org>
|
|
Date: Wed, 25 Jun 2025 18:33:27 +0900
|
|
Subject: dm: Check for forbidden splitting of zone write operations
|
|
|
|
DM targets must not split zone append and write operations using
|
|
dm_accept_partial_bio() as doing so is forbidden for zone append BIOs,
|
|
breaks zone append emulation using regular write BIOs and potentially
|
|
creates deadlock situations with queue freeze operations.
|
|
|
|
Modify dm_accept_partial_bio() to add missing BUG_ON() checks for all
|
|
these cases, that is, check that the BIO is a write or write zeroes
|
|
operation. This change packs all the zone related checks together under
|
|
a static_branch_unlikely(&zoned_enabled) and done only if the target is
|
|
a zoned device.
|
|
|
|
Fixes: f211268ed1f9 ("dm: Use the block layer zone append emulation")
|
|
Cc: stable@vger.kernel.org
|
|
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
|
|
Reviewed-by: Mikulas Patocka <mpatocka@redhat.com>
|
|
Link: https://lore.kernel.org/r/20250625093327.548866-6-dlemoal@kernel.org
|
|
Signed-off-by: Jens Axboe <axboe@kernel.dk>
|
|
---
|
|
drivers/md/dm.c | 17 +++++++++++++----
|
|
1 file changed, 13 insertions(+), 4 deletions(-)
|
|
|
|
--- a/drivers/md/dm.c
|
|
+++ b/drivers/md/dm.c
|
|
@@ -1293,8 +1293,9 @@ out:
|
|
/*
|
|
* A target may call dm_accept_partial_bio only from the map routine. It is
|
|
* allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management
|
|
- * operations, REQ_OP_ZONE_APPEND (zone append writes) and any bio serviced by
|
|
- * __send_duplicate_bios().
|
|
+ * operations, zone append writes (native with REQ_OP_ZONE_APPEND or emulated
|
|
+ * with write BIOs flagged with BIO_EMULATES_ZONE_APPEND) and any bio serviced
|
|
+ * by __send_duplicate_bios().
|
|
*
|
|
* dm_accept_partial_bio informs the dm that the target only wants to process
|
|
* additional n_sectors sectors of the bio and the rest of the data should be
|
|
@@ -1327,11 +1328,19 @@ void dm_accept_partial_bio(struct bio *b
|
|
unsigned int bio_sectors = bio_sectors(bio);
|
|
|
|
BUG_ON(dm_tio_flagged(tio, DM_TIO_IS_DUPLICATE_BIO));
|
|
- BUG_ON(op_is_zone_mgmt(bio_op(bio)));
|
|
- BUG_ON(bio_op(bio) == REQ_OP_ZONE_APPEND);
|
|
BUG_ON(bio_sectors > *tio->len_ptr);
|
|
BUG_ON(n_sectors > bio_sectors);
|
|
|
|
+ if (static_branch_unlikely(&zoned_enabled) &&
|
|
+ unlikely(bdev_is_zoned(bio->bi_bdev))) {
|
|
+ enum req_op op = bio_op(bio);
|
|
+
|
|
+ BUG_ON(op_is_zone_mgmt(op));
|
|
+ BUG_ON(op == REQ_OP_WRITE);
|
|
+ BUG_ON(op == REQ_OP_WRITE_ZEROES);
|
|
+ BUG_ON(op == REQ_OP_ZONE_APPEND);
|
|
+ }
|
|
+
|
|
*tio->len_ptr -= bio_sectors - n_sectors;
|
|
bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT;
|
|
|