Commit dbae70d4 authored by Mikulas Patocka's avatar Mikulas Patocka Committed by Mike Snitzer
Browse files

dm integrity: revert to not using discard filler when recalulating



Revert the commit 7a5b96b4 ("dm integrity:
use discard support when recalculating").

There's a bug that when we write some data beyond the current recalculate
boundary, the checksum will be rewritten with the discard filler later.
And the data will no longer have integrity protection. There's no easy
fix for this case.

Also, another problematic case is if dm-integrity is used to detect
bitrot (random device errors, bit flips, etc); dm-integrity should
detect that even for unused sectors. With commit 7a5b96b4 it can
happen that such change is undetected (because discard filler is not a
valid checksum).

Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Acked-by: default avatarMilan Broz <gmazyland@gmail.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
parent c699a0db
Loading
Loading
Loading
Loading
+24 −33
Original line number Diff line number Diff line
@@ -2689,7 +2689,6 @@ static void integrity_recalc(struct work_struct *w)
	if (unlikely(dm_integrity_failed(ic)))
		goto err;

	if (!ic->discard) {
	io_req.bi_op = REQ_OP_READ;
	io_req.bi_op_flags = 0;
	io_req.mem.type = DM_IO_VMA;
@@ -2711,9 +2710,6 @@ static void integrity_recalc(struct work_struct *w)
		integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
		t += ic->tag_size;
	}
	} else {
		t = ic->recalc_tags + (n_sectors >> ic->sb->log2_sectors_per_block) * ic->tag_size;
	}

	metadata_block = get_metadata_sector_and_offset(ic, area, offset, &metadata_offset);

@@ -4368,14 +4364,12 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
			goto bad;
		}
		INIT_WORK(&ic->recalc_work, integrity_recalc);
		if (!ic->discard) {
		ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT);
		if (!ic->recalc_buffer) {
			ti->error = "Cannot allocate buffer for recalculating";
			r = -ENOMEM;
			goto bad;
		}
		}
		ic->recalc_tags = kvmalloc_array(RECALC_SECTORS >> ic->sb->log2_sectors_per_block,
						 ic->tag_size, GFP_KERNEL);
		if (!ic->recalc_tags) {
@@ -4383,9 +4377,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
			r = -ENOMEM;
			goto bad;
		}
		if (ic->discard)
			memset(ic->recalc_tags, DISCARD_FILLER,
			       (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size);
	} else {
		if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
			ti->error = "Recalculate can only be specified with internal_hash";
@@ -4579,7 +4570,7 @@ static void dm_integrity_dtr(struct dm_target *ti)

static struct target_type integrity_target = {
	.name			= "integrity",
	.version		= {1, 9, 0},
	.version		= {1, 10, 0},
	.module			= THIS_MODULE,
	.features		= DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY,
	.ctr			= dm_integrity_ctr,