Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dm-integrity: fix recalculation in bitmap mode

There's a logic quirk in the handling of suspend in the bitmap mode:

This is the sequence of calls if we are reloading a dm-integrity table:
* dm_integrity_ctr reads a superblock with the flag SB_FLAG_DIRTY_BITMAP
set.
* dm_integrity_postsuspend initializes a journal and clears the flag
SB_FLAG_DIRTY_BITMAP.
* dm_integrity_resume sees the superblock with SB_FLAG_DIRTY_BITMAP set -
thus it interprets the journal as if it were a bitmap.

This quirk causes recalculation problem if the user increases the size of
the device in the bitmap mode.

Fix this by reading a fresh copy on the superblock in
dm_integrity_resume. This commit also fixes another logic quirk - the
branch that sets bitmap bits if the device was extended should only be
executed if the flag SB_FLAG_DIRTY_BITMAP is set.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Tested-by: Ondrej Kozina <okozina@redhat.com>
Fixes: 468dfca38b1a ("dm integrity: add a bitmap mode")
Cc: stable@vger.kernel.org

+13
+13
drivers/md/dm-integrity.c
··· 3788 3788 struct dm_integrity_c *ic = ti->private; 3789 3789 __u64 old_provided_data_sectors = le64_to_cpu(ic->sb->provided_data_sectors); 3790 3790 int r; 3791 + __le32 flags; 3791 3792 3792 3793 DEBUG_print("resume\n"); 3793 3794 3794 3795 ic->wrote_to_journal = false; 3795 3796 3797 + flags = ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING); 3798 + r = sync_rw_sb(ic, REQ_OP_READ); 3799 + if (r) 3800 + dm_integrity_io_error(ic, "reading superblock", r); 3801 + if ((ic->sb->flags & flags) != flags) { 3802 + ic->sb->flags |= flags; 3803 + r = sync_rw_sb(ic, REQ_OP_WRITE | REQ_FUA); 3804 + if (unlikely(r)) 3805 + dm_integrity_io_error(ic, "writing superblock", r); 3806 + } 3807 + 3796 3808 if (ic->provided_data_sectors != old_provided_data_sectors) { 3797 3809 if (ic->provided_data_sectors > old_provided_data_sectors && 3798 3810 ic->mode == 'B' && 3811 + ic->sb->flags & cpu_to_le32(SB_FLAG_DIRTY_BITMAP) && 3799 3812 ic->sb->log2_blocks_per_bitmap_bit == ic->log2_blocks_per_bitmap_bit) { 3800 3813 rw_journal_sectors(ic, REQ_OP_READ, 0, 3801 3814 ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);