| From d5bdf66108419cdb39da361b58ded661c29ff66e Mon Sep 17 00:00:00 2001 |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| Date: Fri, 7 Feb 2020 11:42:30 -0500 |
| Subject: dm integrity: fix recalculation when moving from journal mode to bitmap mode |
| |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| |
| commit d5bdf66108419cdb39da361b58ded661c29ff66e upstream. |
| |
| If we resume a device in bitmap mode and the on-disk format is in journal |
| mode, we must recalculate anything above ic->sb->recalc_sector. Otherwise, |
| there would be non-recalculated blocks which would cause I/O errors. |
| |
| Fixes: 468dfca38b1a ("dm integrity: add a bitmap mode") |
| Cc: stable@vger.kernel.org # v5.2+ |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Signed-off-by: Mike Snitzer <snitzer@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/md/dm-integrity.c | 17 ++++++++++++----- |
| 1 file changed, 12 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/md/dm-integrity.c |
| +++ b/drivers/md/dm-integrity.c |
| @@ -2888,17 +2888,24 @@ static void dm_integrity_resume(struct d |
| } else { |
| replay_journal(ic); |
| if (ic->mode == 'B') { |
| - int mode; |
| ic->sb->flags |= cpu_to_le32(SB_FLAG_DIRTY_BITMAP); |
| ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit; |
| r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA); |
| if (unlikely(r)) |
| dm_integrity_io_error(ic, "writing superblock", r); |
| |
| - mode = ic->recalculate_flag ? BITMAP_OP_SET : BITMAP_OP_CLEAR; |
| - block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, mode); |
| - block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, mode); |
| - block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, mode); |
| + block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR); |
| + block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR); |
| + block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR); |
| + if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) && |
| + le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors) { |
| + block_bitmap_op(ic, ic->journal, le64_to_cpu(ic->sb->recalc_sector), |
| + ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET); |
| + block_bitmap_op(ic, ic->recalc_bitmap, le64_to_cpu(ic->sb->recalc_sector), |
| + ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET); |
| + block_bitmap_op(ic, ic->may_write_bitmap, le64_to_cpu(ic->sb->recalc_sector), |
| + ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET); |
| + } |
| rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0, |
| ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL); |
| } |