In the function break_up_discard_bio, if a discard hits the same block as
regular I/O, it was intended to skip the discard for the affected range.
However, the skip code only advances "data_begin", it doesn't advance
"virt_begin". So, the data_begin and virt_begin variables become
unsynchronized.

process_prepared_discard_passdown_pt1 calculates "data_end =
m->data_block + (m->virt_end - m->virt_begin);" - if m->data_block is
incremented and m->virt_begin isn't, it will overshoot the intended
discard range.

Cc: [email protected]
Fixes: e2dd8aca2d76 ("dm bio prison v1: improve concurrent IO performance")
Signed-off-by: Mikulas Patocka <[email protected]>
Assisted-by: Claude:claude-opus-5

---
 drivers/md/dm-thin.c |    1 +
 1 file changed, 1 insertion(+)

Index: linux-2.6/drivers/md/dm-thin.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-thin.c
+++ linux-2.6/drivers/md/dm-thin.c
@@ -1703,6 +1703,7 @@ static void break_up_discard_bio(struct
                        (void) build_key(tc->td, PHYSICAL, data_begin, 
data_begin + len, &data_key);
                        if (bio_detain(tc->pool, &data_key, NULL, &data_cell)) {
                                /* contention, we'll give up with this range */
+                               virt_begin += len;
                                data_begin += len;
                                continue;
                        }


Reply via email to