Commit a0eb553b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-5.13/dm-fixes' of...

Merge tag 'for-5.13/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:

 - Fix a couple DM snapshot target crashes exposed by user-error.

 - Fix DM integrity target to not use discard optimization, introduced
   during 5.13 merge, when recalulating.

 - Fix some sparse warnings in DM integrity target.

* tag 'for-5.13/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm integrity: fix sparse warnings
  dm integrity: revert to not using discard filler when recalulating
  dm snapshot: fix crash with transient storage and zero chunk size
  dm snapshot: fix a crash when an origin has no snapshots
parents f01da525 bc8f3d46
Loading
Loading
Loading
Loading
+36 −45
Original line number Diff line number Diff line
@@ -66,14 +66,14 @@ struct superblock {
	__u8 magic[8];
	__u8 version;
	__u8 log2_interleave_sectors;
	__u16 integrity_tag_size;
	__u32 journal_sections;
	__u64 provided_data_sectors;	/* userspace uses this value */
	__u32 flags;
	__le16 integrity_tag_size;
	__le32 journal_sections;
	__le64 provided_data_sectors;	/* userspace uses this value */
	__le32 flags;
	__u8 log2_sectors_per_block;
	__u8 log2_blocks_per_bitmap_bit;
	__u8 pad[2];
	__u64 recalc_sector;
	__le64 recalc_sector;
	__u8 pad2[8];
	__u8 salt[SALT_SIZE];
};
@@ -86,16 +86,16 @@ struct superblock {

#define	JOURNAL_ENTRY_ROUNDUP		8

typedef __u64 commit_id_t;
typedef __le64 commit_id_t;
#define JOURNAL_MAC_PER_SECTOR		8

struct journal_entry {
	union {
		struct {
			__u32 sector_lo;
			__u32 sector_hi;
			__le32 sector_lo;
			__le32 sector_hi;
		} s;
		__u64 sector;
		__le64 sector;
	} u;
	commit_id_t last_bytes[];
	/* __u8 tag[0]; */
@@ -806,7 +806,7 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
	}

	if (ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_HMAC)) {
		uint64_t section_le;
		__le64 section_le;

		r = crypto_shash_update(desc, (__u8 *)&ic->sb->salt, SALT_SIZE);
		if (unlikely(r < 0)) {
@@ -1640,7 +1640,7 @@ static void integrity_end_io(struct bio *bio)
static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector,
				      const char *data, char *result)
{
	__u64 sector_le = cpu_to_le64(sector);
	__le64 sector_le = cpu_to_le64(sector);
	SHASH_DESC_ON_STACK(req, ic->internal_hash);
	int r;
	unsigned digest_size;
@@ -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);

@@ -3826,7 +3822,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
			for (i = 0; i < ic->journal_sections; i++) {
				struct scatterlist sg;
				struct skcipher_request *section_req;
				__u32 section_le = cpu_to_le32(i);
				__le32 section_le = cpu_to_le32(i);

				memset(crypt_iv, 0x00, ivsize);
				memset(crypt_data, 0x00, crypt_len);
@@ -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,
+3 −3
Original line number Diff line number Diff line
@@ -855,12 +855,11 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new)
static uint32_t __minimum_chunk_size(struct origin *o)
{
	struct dm_snapshot *snap;
	unsigned chunk_size = 0;
	unsigned chunk_size = rounddown_pow_of_two(UINT_MAX);

	if (o)
		list_for_each_entry(snap, &o->snapshots, list)
			chunk_size = min_not_zero(chunk_size,
						  snap->store->chunk_size);
			chunk_size = min(chunk_size, snap->store->chunk_size);

	return (uint32_t) chunk_size;
}
@@ -1409,6 +1408,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)

	if (!s->store->chunk_size) {
		ti->error = "Chunk size not set";
		r = -EINVAL;
		goto bad_read_metadata;
	}