Commit 64f799ff authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.9/dm-fixes' of...

Merge tag 'for-6.9/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:

 - Fix a memory leak in DM integrity recheck code that was added during
   the 6.9 merge. Also fix the recheck code to ensure it issues bios
   with proper alignment.

 - Fix DM snapshot's dm_exception_table_exit() to schedule while
   handling an large exception table during snapshot device shutdown.

* tag 'for-6.9/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm-integrity: align the outgoing bio in integrity_recheck
  dm snapshot: fix lockup in dm_exception_table_exit
  dm-integrity: fix a memory leak when rechecking the data
parents ff9c18e4 b4d78cfe
...@@ -1699,7 +1699,6 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks ...@@ -1699,7 +1699,6 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
struct bio_vec bv; struct bio_vec bv;
sector_t sector, logical_sector, area, offset; sector_t sector, logical_sector, area, offset;
struct page *page; struct page *page;
void *buffer;
get_area_and_offset(ic, dio->range.logical_sector, &area, &offset); get_area_and_offset(ic, dio->range.logical_sector, &area, &offset);
dio->metadata_block = get_metadata_sector_and_offset(ic, area, offset, dio->metadata_block = get_metadata_sector_and_offset(ic, area, offset,
...@@ -1708,13 +1707,14 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks ...@@ -1708,13 +1707,14 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
logical_sector = dio->range.logical_sector; logical_sector = dio->range.logical_sector;
page = mempool_alloc(&ic->recheck_pool, GFP_NOIO); page = mempool_alloc(&ic->recheck_pool, GFP_NOIO);
buffer = page_to_virt(page);
__bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) { __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
unsigned pos = 0; unsigned pos = 0;
do { do {
sector_t alignment;
char *mem; char *mem;
char *buffer = page_to_virt(page);
int r; int r;
struct dm_io_request io_req; struct dm_io_request io_req;
struct dm_io_region io_loc; struct dm_io_region io_loc;
...@@ -1727,6 +1727,14 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks ...@@ -1727,6 +1727,14 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
io_loc.sector = sector; io_loc.sector = sector;
io_loc.count = ic->sectors_per_block; io_loc.count = ic->sectors_per_block;
/* Align the bio to logical block size */
alignment = dio->range.logical_sector | bio_sectors(bio) | (PAGE_SIZE >> SECTOR_SHIFT);
alignment &= -alignment;
io_loc.sector = round_down(io_loc.sector, alignment);
io_loc.count += sector - io_loc.sector;
buffer += (sector - io_loc.sector) << SECTOR_SHIFT;
io_loc.count = round_up(io_loc.count, alignment);
r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) { if (unlikely(r)) {
dio->bi_status = errno_to_blk_status(r); dio->bi_status = errno_to_blk_status(r);
...@@ -1848,12 +1856,12 @@ static void integrity_metadata(struct work_struct *w) ...@@ -1848,12 +1856,12 @@ static void integrity_metadata(struct work_struct *w)
r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset, r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset,
checksums_ptr - checksums, dio->op == REQ_OP_READ ? TAG_CMP : TAG_WRITE); checksums_ptr - checksums, dio->op == REQ_OP_READ ? TAG_CMP : TAG_WRITE);
if (unlikely(r)) { if (unlikely(r)) {
if (likely(checksums != checksums_onstack))
kfree(checksums);
if (r > 0) { if (r > 0) {
integrity_recheck(dio, checksums); integrity_recheck(dio, checksums_onstack);
goto skip_io; goto skip_io;
} }
if (likely(checksums != checksums_onstack))
kfree(checksums);
goto error; goto error;
} }
......
...@@ -684,8 +684,10 @@ static void dm_exception_table_exit(struct dm_exception_table *et, ...@@ -684,8 +684,10 @@ static void dm_exception_table_exit(struct dm_exception_table *et,
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
slot = et->table + i; slot = et->table + i;
hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) {
kmem_cache_free(mem, ex); kmem_cache_free(mem, ex);
cond_resched();
}
} }
kvfree(et->table); kvfree(et->table);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment