diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2017-04-18 16:51:54 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2017-04-24 12:04:34 -0400 |
commit | 583fe7474c05ee5523e14ef791ea59604cd846dc (patch) | |
tree | 0d82a5b361093c3ddc3c791d08494334338210ec /drivers | |
parent | 9d609f85b7eb96697ae22ad1d47a3a3920174ba8 (diff) |
dm crypt: fix large block integrity support
Previously, dm-crypt could use blocks composed of multiple 512b sectors
but it created integrity profile for each 512b sector (it padded it with
zeroes). Fix dm-crypt so that the integrity profile is sent for each
block not each sector.
The user must use the same block size in the DM crypt and integrity
targets.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm-crypt.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ccbc7f36bb2e..8bff6f7a4c6c 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -938,10 +938,15 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti) return -EINVAL; } - if (bi->tag_size != cc->on_disk_tag_size) { + if (bi->tag_size != cc->on_disk_tag_size || + bi->tuple_size != cc->on_disk_tag_size) { ti->error = "Integrity profile tag size mismatch."; return -EINVAL; } + if (1 << bi->interval_exp != cc->sector_size) { + ti->error = "Integrity profile sector size mismatch."; + return -EINVAL; + } if (crypt_integrity_aead(cc)) { cc->integrity_tag_size = cc->on_disk_tag_size - cc->integrity_iv_size; @@ -1322,7 +1327,7 @@ static int crypt_convert(struct crypt_config *cc, case -EINPROGRESS: ctx->r.req = NULL; ctx->cc_sector += sector_step; - tag_offset += sector_step; + tag_offset++; continue; /* * The request was already processed (synchronously). @@ -1330,7 +1335,7 @@ static int crypt_convert(struct crypt_config *cc, case 0: atomic_dec(&ctx->cc_pending); ctx->cc_sector += sector_step; - tag_offset += sector_step; + tag_offset++; cond_resched(); continue; /* @@ -2735,6 +2740,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->error = "Cannot allocate integrity tags mempool"; goto bad; } + + cc->tag_pool_max_sectors <<= cc->sector_shift; } ret = -ENOMEM; @@ -2816,16 +2823,15 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); if (cc->on_disk_tag_size) { - unsigned tag_len = cc->on_disk_tag_size * bio_sectors(bio); + unsigned tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift); if (unlikely(tag_len > KMALLOC_MAX_SIZE) || - unlikely(!(io->integrity_metadata = kzalloc(tag_len, + unlikely(!(io->integrity_metadata = kmalloc(tag_len, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN)))) { if (bio_sectors(bio) > cc->tag_pool_max_sectors) dm_accept_partial_bio(bio, cc->tag_pool_max_sectors); io->integrity_metadata = mempool_alloc(cc->tag_pool, GFP_NOIO); io->integrity_metadata_from_pool = true; - memset(io->integrity_metadata, 0, cc->tag_pool_max_sectors * (1 << SECTOR_SHIFT)); } } |