The "unstriped" device-mapper target incorrectly calculates the sector offset 
on the mapped device when the target's origin is not zero.

Take for example this hypothetical concatenation of the members of a two-disk 
RAID0:

linearized:       0 2097152 unstriped 2 128 0 /dev/md/raid0 0
linearized: 2097152 2097152 unstriped 2 128 1 /dev/md/raid0 0

The intent in this example is to create a single device named 
/dev/mapper/linearized that comprises all of the chunks of the first disk of 
the RAID0 set, followed by all of the chunks of the second disk of the RAID0 
set.

This fails because dm-unstripe.c's map_to_core function does its computations 
based on the sector number within the mapper device rather than the sector 
number within the target. The bug turns invisible when the target's origin is 
at sector zero of the mapper device, as is the common case. In the example 
above, however, what happens is that the first half of the mapper device gets 
mapped correctly to the first disk of the RAID0, but the second half of the 
mapper device gets mapped past the end of the RAID0 device, and accesses to any 
of those sectors return errors.

Here is a very simple (tested) patch that corrects the problem:

--- drivers/md/dm-unstripe.c~   2025-11-28 22:33:48.000000000 -0500
+++ drivers/md/dm-unstripe.c    2026-01-18 12:48:52.378293579 -0500
@@ -117,7 +117,7 @@
 static sector_t map_to_core(struct dm_target *ti, struct bio *bio)
 {
        struct unstripe_c *uc = ti->private;
-       sector_t sector = bio->bi_iter.bi_sector;
+       sector_t sector = dm_target_offset(ti, bio->bi_iter.bi_sector);
        sector_t tmp_sector = sector;
 
        /* Shift us up to the right "row" on the stripe */


Reply via email to