Commit a0eb553b authored by Linus Torvalds's avatar Linus Torvalds

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
...@@ -66,14 +66,14 @@ struct superblock { ...@@ -66,14 +66,14 @@ struct superblock {
__u8 magic[8]; __u8 magic[8];
__u8 version; __u8 version;
__u8 log2_interleave_sectors; __u8 log2_interleave_sectors;
__u16 integrity_tag_size; __le16 integrity_tag_size;
__u32 journal_sections; __le32 journal_sections;
__u64 provided_data_sectors; /* userspace uses this value */ __le64 provided_data_sectors; /* userspace uses this value */
__u32 flags; __le32 flags;
__u8 log2_sectors_per_block; __u8 log2_sectors_per_block;
__u8 log2_blocks_per_bitmap_bit; __u8 log2_blocks_per_bitmap_bit;
__u8 pad[2]; __u8 pad[2];
__u64 recalc_sector; __le64 recalc_sector;
__u8 pad2[8]; __u8 pad2[8];
__u8 salt[SALT_SIZE]; __u8 salt[SALT_SIZE];
}; };
...@@ -86,16 +86,16 @@ struct superblock { ...@@ -86,16 +86,16 @@ struct superblock {
#define JOURNAL_ENTRY_ROUNDUP 8 #define JOURNAL_ENTRY_ROUNDUP 8
typedef __u64 commit_id_t; typedef __le64 commit_id_t;
#define JOURNAL_MAC_PER_SECTOR 8 #define JOURNAL_MAC_PER_SECTOR 8
struct journal_entry { struct journal_entry {
union { union {
struct { struct {
__u32 sector_lo; __le32 sector_lo;
__u32 sector_hi; __le32 sector_hi;
} s; } s;
__u64 sector; __le64 sector;
} u; } u;
commit_id_t last_bytes[]; commit_id_t last_bytes[];
/* __u8 tag[0]; */ /* __u8 tag[0]; */
...@@ -806,7 +806,7 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result ...@@ -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)) { 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); r = crypto_shash_update(desc, (__u8 *)&ic->sb->salt, SALT_SIZE);
if (unlikely(r < 0)) { if (unlikely(r < 0)) {
...@@ -1640,7 +1640,7 @@ static void integrity_end_io(struct bio *bio) ...@@ -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, static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector,
const char *data, char *result) 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); SHASH_DESC_ON_STACK(req, ic->internal_hash);
int r; int r;
unsigned digest_size; unsigned digest_size;
...@@ -2689,30 +2689,26 @@ static void integrity_recalc(struct work_struct *w) ...@@ -2689,30 +2689,26 @@ static void integrity_recalc(struct work_struct *w)
if (unlikely(dm_integrity_failed(ic))) if (unlikely(dm_integrity_failed(ic)))
goto err; goto err;
if (!ic->discard) { io_req.bi_op = REQ_OP_READ;
io_req.bi_op = REQ_OP_READ; io_req.bi_op_flags = 0;
io_req.bi_op_flags = 0; io_req.mem.type = DM_IO_VMA;
io_req.mem.type = DM_IO_VMA; io_req.mem.ptr.addr = ic->recalc_buffer;
io_req.mem.ptr.addr = ic->recalc_buffer; io_req.notify.fn = NULL;
io_req.notify.fn = NULL; io_req.client = ic->io;
io_req.client = ic->io; io_loc.bdev = ic->dev->bdev;
io_loc.bdev = ic->dev->bdev; io_loc.sector = get_data_sector(ic, area, offset);
io_loc.sector = get_data_sector(ic, area, offset); io_loc.count = n_sectors;
io_loc.count = n_sectors;
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL);
if (unlikely(r)) { if (unlikely(r)) {
dm_integrity_io_error(ic, "reading data", r); dm_integrity_io_error(ic, "reading data", r);
goto err; goto err;
} }
t = ic->recalc_tags; t = ic->recalc_tags;
for (i = 0; i < n_sectors; i += ic->sectors_per_block) { for (i = 0; i < n_sectors; i += ic->sectors_per_block) {
integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t); integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
t += ic->tag_size; 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); 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) ...@@ -3826,7 +3822,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
for (i = 0; i < ic->journal_sections; i++) { for (i = 0; i < ic->journal_sections; i++) {
struct scatterlist sg; struct scatterlist sg;
struct skcipher_request *section_req; 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_iv, 0x00, ivsize);
memset(crypt_data, 0x00, crypt_len); memset(crypt_data, 0x00, crypt_len);
...@@ -4368,13 +4364,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) ...@@ -4368,13 +4364,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad; goto bad;
} }
INIT_WORK(&ic->recalc_work, integrity_recalc); INIT_WORK(&ic->recalc_work, integrity_recalc);
if (!ic->discard) { ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT);
ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT); if (!ic->recalc_buffer) {
if (!ic->recalc_buffer) { ti->error = "Cannot allocate buffer for recalculating";
ti->error = "Cannot allocate buffer for recalculating"; r = -ENOMEM;
r = -ENOMEM; goto bad;
goto bad;
}
} }
ic->recalc_tags = kvmalloc_array(RECALC_SECTORS >> ic->sb->log2_sectors_per_block, ic->recalc_tags = kvmalloc_array(RECALC_SECTORS >> ic->sb->log2_sectors_per_block,
ic->tag_size, GFP_KERNEL); ic->tag_size, GFP_KERNEL);
...@@ -4383,9 +4377,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) ...@@ -4383,9 +4377,6 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
r = -ENOMEM; r = -ENOMEM;
goto bad; goto bad;
} }
if (ic->discard)
memset(ic->recalc_tags, DISCARD_FILLER,
(RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size);
} else { } else {
if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) { if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
ti->error = "Recalculate can only be specified with internal_hash"; ti->error = "Recalculate can only be specified with internal_hash";
...@@ -4579,7 +4570,7 @@ static void dm_integrity_dtr(struct dm_target *ti) ...@@ -4579,7 +4570,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
static struct target_type integrity_target = { static struct target_type integrity_target = {
.name = "integrity", .name = "integrity",
.version = {1, 9, 0}, .version = {1, 10, 0},
.module = THIS_MODULE, .module = THIS_MODULE,
.features = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY, .features = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY,
.ctr = dm_integrity_ctr, .ctr = dm_integrity_ctr,
......
...@@ -855,12 +855,11 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new) ...@@ -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) static uint32_t __minimum_chunk_size(struct origin *o)
{ {
struct dm_snapshot *snap; struct dm_snapshot *snap;
unsigned chunk_size = 0; unsigned chunk_size = rounddown_pow_of_two(UINT_MAX);
if (o) if (o)
list_for_each_entry(snap, &o->snapshots, list) list_for_each_entry(snap, &o->snapshots, list)
chunk_size = min_not_zero(chunk_size, chunk_size = min(chunk_size, snap->store->chunk_size);
snap->store->chunk_size);
return (uint32_t) chunk_size; return (uint32_t) chunk_size;
} }
...@@ -1409,6 +1408,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) ...@@ -1409,6 +1408,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
if (!s->store->chunk_size) { if (!s->store->chunk_size) {
ti->error = "Chunk size not set"; ti->error = "Chunk size not set";
r = -EINVAL;
goto bad_read_metadata; goto bad_read_metadata;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment