dm-integrity: align the outgoing bio in integrity_recheck
[sfrench/cifs-2.6.git] / drivers / md / dm-integrity.c
index 3329e1e93524868cee26ec58c9c03938b30cc745..37b9f8f1ae1a275763b974a8547ab37efd93eb21 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);