In log_writes_map(), when a discard bio is received and the device
does not support discard, a pending block is allocated and its
pending_blocks refcount is incremented, but the block is never
freed. The function calls bio_endio(bio) and returns
DM_MAPIO_SUBMITTED directly, bypassing normal_end_io() which would
enqueue the block for later release via the kthread. As a result,
the refcount for the associated pending block is leaked, and
pending_blocks never reaches zero, preventing log_writes_dtr() from
completing and causing the device destruction to hang.

Free the block with free_pending_block() before completing the bio
in the !device_supports_discard path, matching the error handling
done when page allocation fails.

Cc: [email protected]
Fixes: 0e9cebe72459 ("dm: add log writes target")
Signed-off-by: Wentao Liang <[email protected]>
---
 drivers/md/dm-log-writes.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index c72e07c3f5a0..05133b1553ca 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -709,6 +709,8 @@ static int log_writes_map(struct dm_target *ti, struct bio 
*bio)
                WARN_ON(flush_bio || fua_bio);
                if (lc->device_supports_discard)
                        goto map_bio;
+               free_pending_block(lc, block);
+               pb->block = NULL;
                bio_endio(bio);
                return DM_MAPIO_SUBMITTED;
        }
-- 
2.34.1


Reply via email to