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; }
