Merge tag 'for-6.9/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
[linux-2.6-microblaze.git] / drivers / md / dm-integrity.c
index d822ab2..37b9f8f 100644 (file)
@@ -1699,7 +1699,6 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
        struct bio_vec bv;
        sector_t sector, logical_sector, area, offset;
        struct page *page;
-       void *buffer;
 
        get_area_and_offset(ic, dio->range.logical_sector, &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
        logical_sector = dio->range.logical_sector;
 
        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) {
                unsigned pos = 0;
 
                do {
+                       sector_t alignment;
                        char *mem;
+                       char *buffer = page_to_virt(page);
                        int r;
                        struct dm_io_request io_req;
                        struct dm_io_region io_loc;
@@ -1727,6 +1727,14 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
                        io_loc.sector = sector;
                        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);
                        if (unlikely(r)) {
                                dio->bi_status = errno_to_blk_status(r);
@@ -1848,12 +1856,12 @@ again:
                        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);
                        if (unlikely(r)) {
+                               if (likely(checksums != checksums_onstack))
+                                       kfree(checksums);
                                if (r > 0) {
-                                       integrity_recheck(dio, checksums);
+                                       integrity_recheck(dio, checksums_onstack);
                                        goto skip_io;
                                }
-                               if (likely(checksums != checksums_onstack))
-                                       kfree(checksums);
                                goto error;
                        }