Skip to content

Commit 6a6c561

Browse files
author
Mikulas Patocka
committed
dm-crypt: support for per-sector NVMe metadata
Support per-sector NVMe metadata in dm-crypt. This commit changes dm-crypt, so that it can use NVMe metadata to store authentication information. We can put dm-crypt directly on the top of NVMe device, without using dm-integrity. This commit improves write throughput twice, becase the will be no writes to the dm-integrity journal. Signed-off-by: Mikulas Patocka <[email protected]>
1 parent a48f6b8 commit 6a6c561

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

drivers/md/dm-crypt.c

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ struct crypt_config {
214214

215215
unsigned int integrity_tag_size;
216216
unsigned int integrity_iv_size;
217-
unsigned int on_disk_tag_size;
217+
unsigned int used_tag_size;
218+
unsigned int tuple_size;
218219

219220
/*
220221
* pool for per bio private data, crypto requests,
@@ -256,7 +257,7 @@ static unsigned get_max_request_size(struct crypt_config *cc, bool wrt)
256257
val = !wrt ? READ_ONCE(max_read_size) : READ_ONCE(max_write_size);
257258
if (likely(!val))
258259
val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE;
259-
if (wrt || cc->on_disk_tag_size) {
260+
if (wrt || cc->used_tag_size) {
260261
if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT))
261262
val = BIO_MAX_VECS << PAGE_SHIFT;
262263
}
@@ -1176,14 +1177,14 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
11761177
unsigned int tag_len;
11771178
int ret;
11781179

1179-
if (!bio_sectors(bio) || !io->cc->on_disk_tag_size)
1180+
if (!bio_sectors(bio) || !io->cc->tuple_size)
11801181
return 0;
11811182

11821183
bip = bio_integrity_alloc(bio, GFP_NOIO, 1);
11831184
if (IS_ERR(bip))
11841185
return PTR_ERR(bip);
11851186

1186-
tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
1187+
tag_len = io->cc->tuple_size * (bio_sectors(bio) >> io->cc->sector_shift);
11871188

11881189
bip->bip_iter.bi_sector = io->cc->start + io->sector;
11891190

@@ -1207,18 +1208,18 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
12071208
return -EINVAL;
12081209
}
12091210

1210-
if (bi->tag_size != cc->on_disk_tag_size ||
1211-
bi->tuple_size != cc->on_disk_tag_size) {
1211+
if (bi->tuple_size < cc->used_tag_size) {
12121212
ti->error = "Integrity profile tag size mismatch.";
12131213
return -EINVAL;
12141214
}
1215+
cc->tuple_size = bi->tuple_size;
12151216
if (1 << bi->interval_exp != cc->sector_size) {
12161217
ti->error = "Integrity profile sector size mismatch.";
12171218
return -EINVAL;
12181219
}
12191220

12201221
if (crypt_integrity_aead(cc)) {
1221-
cc->integrity_tag_size = cc->on_disk_tag_size - cc->integrity_iv_size;
1222+
cc->integrity_tag_size = cc->used_tag_size - cc->integrity_iv_size;
12221223
DMDEBUG("%s: Integrity AEAD, tag size %u, IV size %u.", dm_device_name(md),
12231224
cc->integrity_tag_size, cc->integrity_iv_size);
12241225

@@ -1230,7 +1231,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
12301231
DMDEBUG("%s: Additional per-sector space %u bytes for IV.", dm_device_name(md),
12311232
cc->integrity_iv_size);
12321233

1233-
if ((cc->integrity_tag_size + cc->integrity_iv_size) != bi->tag_size) {
1234+
if ((cc->integrity_tag_size + cc->integrity_iv_size) > cc->tuple_size) {
12341235
ti->error = "Not enough space for integrity tag in the profile.";
12351236
return -EINVAL;
12361237
}
@@ -1309,7 +1310,7 @@ static void *tag_from_dmreq(struct crypt_config *cc,
13091310
struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
13101311

13111312
return &io->integrity_metadata[*org_tag_of_dmreq(cc, dmreq) *
1312-
cc->on_disk_tag_size];
1313+
cc->tuple_size];
13131314
}
13141315

13151316
static void *iv_tag_from_dmreq(struct crypt_config *cc,
@@ -1390,9 +1391,9 @@ static int crypt_convert_block_aead(struct crypt_config *cc,
13901391
aead_request_set_crypt(req, dmreq->sg_in, dmreq->sg_out,
13911392
cc->sector_size, iv);
13921393
r = crypto_aead_encrypt(req);
1393-
if (cc->integrity_tag_size + cc->integrity_iv_size != cc->on_disk_tag_size)
1394+
if (cc->integrity_tag_size + cc->integrity_iv_size != cc->tuple_size)
13941395
memset(tag + cc->integrity_tag_size + cc->integrity_iv_size, 0,
1395-
cc->on_disk_tag_size - (cc->integrity_tag_size + cc->integrity_iv_size));
1396+
cc->tuple_size - (cc->integrity_tag_size + cc->integrity_iv_size));
13961397
} else {
13971398
aead_request_set_crypt(req, dmreq->sg_in, dmreq->sg_out,
13981399
cc->sector_size + cc->integrity_tag_size, iv);
@@ -1822,7 +1823,7 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
18221823
return;
18231824

18241825
if (likely(!io->ctx.aead_recheck) && unlikely(io->ctx.aead_failed) &&
1825-
cc->on_disk_tag_size && bio_data_dir(base_bio) == READ) {
1826+
cc->used_tag_size && bio_data_dir(base_bio) == READ) {
18261827
io->ctx.aead_recheck = true;
18271828
io->ctx.aead_failed = false;
18281829
io->error = 0;
@@ -3206,7 +3207,7 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar
32063207
ti->error = "Invalid integrity arguments";
32073208
return -EINVAL;
32083209
}
3209-
cc->on_disk_tag_size = val;
3210+
cc->used_tag_size = val;
32103211
sval = strchr(opt_string + strlen("integrity:"), ':') + 1;
32113212
if (!strcasecmp(sval, "aead")) {
32123213
set_bit(CRYPT_MODE_INTEGRITY_AEAD, &cc->cipher_flags);
@@ -3418,12 +3419,12 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
34183419
if (ret)
34193420
goto bad;
34203421

3421-
cc->tag_pool_max_sectors = POOL_ENTRY_SIZE / cc->on_disk_tag_size;
3422+
cc->tag_pool_max_sectors = POOL_ENTRY_SIZE / cc->tuple_size;
34223423
if (!cc->tag_pool_max_sectors)
34233424
cc->tag_pool_max_sectors = 1;
34243425

34253426
ret = mempool_init_kmalloc_pool(&cc->tag_pool, MIN_IOS,
3426-
cc->tag_pool_max_sectors * cc->on_disk_tag_size);
3427+
cc->tag_pool_max_sectors * cc->tuple_size);
34273428
if (ret) {
34283429
ti->error = "Cannot allocate integrity tags mempool";
34293430
goto bad;
@@ -3535,8 +3536,8 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
35353536
io = dm_per_bio_data(bio, cc->per_bio_data_size);
35363537
crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector));
35373538

3538-
if (cc->on_disk_tag_size) {
3539-
unsigned int tag_len = cc->on_disk_tag_size * (bio_sectors(bio) >> cc->sector_shift);
3539+
if (cc->tuple_size) {
3540+
unsigned int tag_len = cc->tuple_size * (bio_sectors(bio) >> cc->sector_shift);
35403541

35413542
if (unlikely(tag_len > KMALLOC_MAX_SIZE))
35423543
io->integrity_metadata = NULL;
@@ -3608,7 +3609,7 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
36083609
num_feature_args += test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags);
36093610
num_feature_args += cc->sector_size != (1 << SECTOR_SHIFT);
36103611
num_feature_args += test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags);
3611-
if (cc->on_disk_tag_size)
3612+
if (cc->used_tag_size)
36123613
num_feature_args++;
36133614
if (num_feature_args) {
36143615
DMEMIT(" %d", num_feature_args);
@@ -3624,8 +3625,8 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
36243625
DMEMIT(" no_read_workqueue");
36253626
if (test_bit(DM_CRYPT_NO_WRITE_WORKQUEUE, &cc->flags))
36263627
DMEMIT(" no_write_workqueue");
3627-
if (cc->on_disk_tag_size)
3628-
DMEMIT(" integrity:%u:%s", cc->on_disk_tag_size, cc->cipher_auth);
3628+
if (cc->used_tag_size)
3629+
DMEMIT(" integrity:%u:%s", cc->used_tag_size, cc->cipher_auth);
36293630
if (cc->sector_size != (1 << SECTOR_SHIFT))
36303631
DMEMIT(" sector_size:%d", cc->sector_size);
36313632
if (test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags))
@@ -3647,9 +3648,9 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
36473648
DMEMIT(",iv_large_sectors=%c", test_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags) ?
36483649
'y' : 'n');
36493650

3650-
if (cc->on_disk_tag_size)
3651+
if (cc->used_tag_size)
36513652
DMEMIT(",integrity_tag_size=%u,cipher_auth=%s",
3652-
cc->on_disk_tag_size, cc->cipher_auth);
3653+
cc->used_tag_size, cc->cipher_auth);
36533654
if (cc->sector_size != (1 << SECTOR_SHIFT))
36543655
DMEMIT(",sector_size=%d", cc->sector_size);
36553656
if (cc->cipher_string)
@@ -3757,7 +3758,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
37573758

37583759
static struct target_type crypt_target = {
37593760
.name = "crypt",
3760-
.version = {1, 26, 0},
3761+
.version = {1, 27, 0},
37613762
.module = THIS_MODULE,
37623763
.ctr = crypt_ctr,
37633764
.dtr = crypt_dtr,

0 commit comments

Comments
 (0)