Skip to content

Commit 3f72821

Browse files
committed
Merge tag 'for-5.18/64bit-pi-2022-03-25' of git://git.kernel.dk/linux-block
Pull block layer 64-bit data integrity support from Jens Axboe: "This adds support for 64-bit data integrity in the block layer and in NVMe" * tag 'for-5.18/64bit-pi-2022-03-25' of git://git.kernel.dk/linux-block: crypto: fix crc64 testmgr digest byte order nvme: add support for enhanced metadata block: add pi for extended integrity crypto: add rocksoft 64b crc guard tag framework lib: add rocksoft model crc64 linux/kernel: introduce lower_48_bits function asm-generic: introduce be48 unaligned accessors nvme: allow integrity on extended metadata formats block: support pi with extended metadata
2 parents 752d422 + 1e21270 commit 3f72821

File tree

21 files changed

+770
-47
lines changed

21 files changed

+770
-47
lines changed

block/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ config BLK_DEV_INTEGRITY_T10
7373
tristate
7474
depends on BLK_DEV_INTEGRITY
7575
select CRC_T10DIF
76+
select CRC64_ROCKSOFT
7677

7778
config BLK_DEV_ZONED
7879
bool "Zoned block device support"

block/bio-integrity.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ static blk_status_t bio_integrity_process(struct bio *bio,
165165

166166
iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
167167
iter.interval = 1 << bi->interval_exp;
168+
iter.tuple_size = bi->tuple_size;
168169
iter.seed = proc_iter->bi_sector;
169170
iter.prot_buf = bvec_virt(bip->bip_vec);
170171

block/t10-pi.c

Lines changed: 196 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
#include <linux/t10-pi.h>
88
#include <linux/blk-integrity.h>
99
#include <linux/crc-t10dif.h>
10+
#include <linux/crc64.h>
1011
#include <linux/module.h>
1112
#include <net/checksum.h>
13+
#include <asm/unaligned.h>
1214

1315
typedef __be16 (csum_fn) (void *, unsigned int);
1416

@@ -44,7 +46,7 @@ static blk_status_t t10_pi_generate(struct blk_integrity_iter *iter,
4446
pi->ref_tag = 0;
4547

4648
iter->data_buf += iter->interval;
47-
iter->prot_buf += sizeof(struct t10_pi_tuple);
49+
iter->prot_buf += iter->tuple_size;
4850
iter->seed++;
4951
}
5052

@@ -93,7 +95,7 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
9395

9496
next:
9597
iter->data_buf += iter->interval;
96-
iter->prot_buf += sizeof(struct t10_pi_tuple);
98+
iter->prot_buf += iter->tuple_size;
9799
iter->seed++;
98100
}
99101

@@ -278,4 +280,196 @@ const struct blk_integrity_profile t10_pi_type3_ip = {
278280
};
279281
EXPORT_SYMBOL(t10_pi_type3_ip);
280282

283+
static __be64 ext_pi_crc64(void *data, unsigned int len)
284+
{
285+
return cpu_to_be64(crc64_rocksoft(data, len));
286+
}
287+
288+
static blk_status_t ext_pi_crc64_generate(struct blk_integrity_iter *iter,
289+
enum t10_dif_type type)
290+
{
291+
unsigned int i;
292+
293+
for (i = 0 ; i < iter->data_size ; i += iter->interval) {
294+
struct crc64_pi_tuple *pi = iter->prot_buf;
295+
296+
pi->guard_tag = ext_pi_crc64(iter->data_buf, iter->interval);
297+
pi->app_tag = 0;
298+
299+
if (type == T10_PI_TYPE1_PROTECTION)
300+
put_unaligned_be48(iter->seed, pi->ref_tag);
301+
else
302+
put_unaligned_be48(0ULL, pi->ref_tag);
303+
304+
iter->data_buf += iter->interval;
305+
iter->prot_buf += iter->tuple_size;
306+
iter->seed++;
307+
}
308+
309+
return BLK_STS_OK;
310+
}
311+
312+
static bool ext_pi_ref_escape(u8 *ref_tag)
313+
{
314+
static u8 ref_escape[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
315+
316+
return memcmp(ref_tag, ref_escape, sizeof(ref_escape)) == 0;
317+
}
318+
319+
static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
320+
enum t10_dif_type type)
321+
{
322+
unsigned int i;
323+
324+
for (i = 0; i < iter->data_size; i += iter->interval) {
325+
struct crc64_pi_tuple *pi = iter->prot_buf;
326+
u64 ref, seed;
327+
__be64 csum;
328+
329+
if (type == T10_PI_TYPE1_PROTECTION) {
330+
if (pi->app_tag == T10_PI_APP_ESCAPE)
331+
goto next;
332+
333+
ref = get_unaligned_be48(pi->ref_tag);
334+
seed = lower_48_bits(iter->seed);
335+
if (ref != seed) {
336+
pr_err("%s: ref tag error at location %llu (rcvd %llu)\n",
337+
iter->disk_name, seed, ref);
338+
return BLK_STS_PROTECTION;
339+
}
340+
} else if (type == T10_PI_TYPE3_PROTECTION) {
341+
if (pi->app_tag == T10_PI_APP_ESCAPE &&
342+
ext_pi_ref_escape(pi->ref_tag))
343+
goto next;
344+
}
345+
346+
csum = ext_pi_crc64(iter->data_buf, iter->interval);
347+
if (pi->guard_tag != csum) {
348+
pr_err("%s: guard tag error at sector %llu " \
349+
"(rcvd %016llx, want %016llx)\n",
350+
iter->disk_name, (unsigned long long)iter->seed,
351+
be64_to_cpu(pi->guard_tag), be64_to_cpu(csum));
352+
return BLK_STS_PROTECTION;
353+
}
354+
355+
next:
356+
iter->data_buf += iter->interval;
357+
iter->prot_buf += iter->tuple_size;
358+
iter->seed++;
359+
}
360+
361+
return BLK_STS_OK;
362+
}
363+
364+
static blk_status_t ext_pi_type1_verify_crc64(struct blk_integrity_iter *iter)
365+
{
366+
return ext_pi_crc64_verify(iter, T10_PI_TYPE1_PROTECTION);
367+
}
368+
369+
static blk_status_t ext_pi_type1_generate_crc64(struct blk_integrity_iter *iter)
370+
{
371+
return ext_pi_crc64_generate(iter, T10_PI_TYPE1_PROTECTION);
372+
}
373+
374+
static void ext_pi_type1_prepare(struct request *rq)
375+
{
376+
const int tuple_sz = rq->q->integrity.tuple_size;
377+
u64 ref_tag = ext_pi_ref_tag(rq);
378+
struct bio *bio;
379+
380+
__rq_for_each_bio(bio, rq) {
381+
struct bio_integrity_payload *bip = bio_integrity(bio);
382+
u64 virt = lower_48_bits(bip_get_seed(bip));
383+
struct bio_vec iv;
384+
struct bvec_iter iter;
385+
386+
/* Already remapped? */
387+
if (bip->bip_flags & BIP_MAPPED_INTEGRITY)
388+
break;
389+
390+
bip_for_each_vec(iv, bip, iter) {
391+
unsigned int j;
392+
void *p;
393+
394+
p = bvec_kmap_local(&iv);
395+
for (j = 0; j < iv.bv_len; j += tuple_sz) {
396+
struct crc64_pi_tuple *pi = p;
397+
u64 ref = get_unaligned_be48(pi->ref_tag);
398+
399+
if (ref == virt)
400+
put_unaligned_be48(ref_tag, pi->ref_tag);
401+
virt++;
402+
ref_tag++;
403+
p += tuple_sz;
404+
}
405+
kunmap_local(p);
406+
}
407+
408+
bip->bip_flags |= BIP_MAPPED_INTEGRITY;
409+
}
410+
}
411+
412+
static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
413+
{
414+
unsigned intervals = nr_bytes >> rq->q->integrity.interval_exp;
415+
const int tuple_sz = rq->q->integrity.tuple_size;
416+
u64 ref_tag = ext_pi_ref_tag(rq);
417+
struct bio *bio;
418+
419+
__rq_for_each_bio(bio, rq) {
420+
struct bio_integrity_payload *bip = bio_integrity(bio);
421+
u64 virt = lower_48_bits(bip_get_seed(bip));
422+
struct bio_vec iv;
423+
struct bvec_iter iter;
424+
425+
bip_for_each_vec(iv, bip, iter) {
426+
unsigned int j;
427+
void *p;
428+
429+
p = bvec_kmap_local(&iv);
430+
for (j = 0; j < iv.bv_len && intervals; j += tuple_sz) {
431+
struct crc64_pi_tuple *pi = p;
432+
u64 ref = get_unaligned_be48(pi->ref_tag);
433+
434+
if (ref == ref_tag)
435+
put_unaligned_be48(virt, pi->ref_tag);
436+
virt++;
437+
ref_tag++;
438+
intervals--;
439+
p += tuple_sz;
440+
}
441+
kunmap_local(p);
442+
}
443+
}
444+
}
445+
446+
static blk_status_t ext_pi_type3_verify_crc64(struct blk_integrity_iter *iter)
447+
{
448+
return ext_pi_crc64_verify(iter, T10_PI_TYPE3_PROTECTION);
449+
}
450+
451+
static blk_status_t ext_pi_type3_generate_crc64(struct blk_integrity_iter *iter)
452+
{
453+
return ext_pi_crc64_generate(iter, T10_PI_TYPE3_PROTECTION);
454+
}
455+
456+
const struct blk_integrity_profile ext_pi_type1_crc64 = {
457+
.name = "EXT-DIF-TYPE1-CRC64",
458+
.generate_fn = ext_pi_type1_generate_crc64,
459+
.verify_fn = ext_pi_type1_verify_crc64,
460+
.prepare_fn = ext_pi_type1_prepare,
461+
.complete_fn = ext_pi_type1_complete,
462+
};
463+
EXPORT_SYMBOL_GPL(ext_pi_type1_crc64);
464+
465+
const struct blk_integrity_profile ext_pi_type3_crc64 = {
466+
.name = "EXT-DIF-TYPE3-CRC64",
467+
.generate_fn = ext_pi_type3_generate_crc64,
468+
.verify_fn = ext_pi_type3_verify_crc64,
469+
.prepare_fn = t10_pi_type3_prepare,
470+
.complete_fn = t10_pi_type3_complete,
471+
};
472+
EXPORT_SYMBOL_GPL(ext_pi_type3_crc64);
473+
474+
MODULE_LICENSE("GPL");
281475
MODULE_LICENSE("GPL");

crypto/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,11 @@ config CRYPTO_CRCT10DIF_VPMSUM
743743
multiply-sum (vpmsum) instructions, introduced in POWER8. Enable on
744744
POWER8 and newer processors for improved performance.
745745

746+
config CRYPTO_CRC64_ROCKSOFT
747+
tristate "Rocksoft Model CRC64 algorithm"
748+
depends on CRC64
749+
select CRYPTO_HASH
750+
746751
config CRYPTO_VPMSUM_TESTER
747752
tristate "Powerpc64 vpmsum hardware acceleration tester"
748753
depends on CRYPTO_CRCT10DIF_VPMSUM && CRYPTO_CRC32C_VPMSUM

crypto/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
152152
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o
153153
obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o
154154
obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
155+
obj-$(CONFIG_CRYPTO_CRC64_ROCKSOFT) += crc64_rocksoft_generic.o
155156
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
156157
obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o
157158
obj-$(CONFIG_CRYPTO_LZ4) += lz4.o

crypto/crc64_rocksoft_generic.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include <linux/crc64.h>
4+
#include <linux/module.h>
5+
#include <crypto/internal/hash.h>
6+
#include <asm/unaligned.h>
7+
8+
static int chksum_init(struct shash_desc *desc)
9+
{
10+
u64 *crc = shash_desc_ctx(desc);
11+
12+
*crc = 0;
13+
14+
return 0;
15+
}
16+
17+
static int chksum_update(struct shash_desc *desc, const u8 *data,
18+
unsigned int length)
19+
{
20+
u64 *crc = shash_desc_ctx(desc);
21+
22+
*crc = crc64_rocksoft_generic(*crc, data, length);
23+
24+
return 0;
25+
}
26+
27+
static int chksum_final(struct shash_desc *desc, u8 *out)
28+
{
29+
u64 *crc = shash_desc_ctx(desc);
30+
31+
put_unaligned_le64(*crc, out);
32+
return 0;
33+
}
34+
35+
static int __chksum_finup(u64 crc, const u8 *data, unsigned int len, u8 *out)
36+
{
37+
crc = crc64_rocksoft_generic(crc, data, len);
38+
put_unaligned_le64(crc, out);
39+
return 0;
40+
}
41+
42+
static int chksum_finup(struct shash_desc *desc, const u8 *data,
43+
unsigned int len, u8 *out)
44+
{
45+
u64 *crc = shash_desc_ctx(desc);
46+
47+
return __chksum_finup(*crc, data, len, out);
48+
}
49+
50+
static int chksum_digest(struct shash_desc *desc, const u8 *data,
51+
unsigned int length, u8 *out)
52+
{
53+
return __chksum_finup(0, data, length, out);
54+
}
55+
56+
static struct shash_alg alg = {
57+
.digestsize = sizeof(u64),
58+
.init = chksum_init,
59+
.update = chksum_update,
60+
.final = chksum_final,
61+
.finup = chksum_finup,
62+
.digest = chksum_digest,
63+
.descsize = sizeof(u64),
64+
.base = {
65+
.cra_name = CRC64_ROCKSOFT_STRING,
66+
.cra_driver_name = "crc64-rocksoft-generic",
67+
.cra_priority = 200,
68+
.cra_blocksize = 1,
69+
.cra_module = THIS_MODULE,
70+
}
71+
};
72+
73+
static int __init crc64_rocksoft_init(void)
74+
{
75+
return crypto_register_shash(&alg);
76+
}
77+
78+
static void __exit crc64_rocksoft_exit(void)
79+
{
80+
crypto_unregister_shash(&alg);
81+
}
82+
83+
module_init(crc64_rocksoft_init);
84+
module_exit(crc64_rocksoft_exit);
85+
86+
MODULE_LICENSE("GPL");
87+
MODULE_DESCRIPTION("Rocksoft model CRC64 calculation.");
88+
MODULE_ALIAS_CRYPTO("crc64-rocksoft");
89+
MODULE_ALIAS_CRYPTO("crc64-rocksoft-generic");

crypto/testmgr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4526,6 +4526,13 @@ static const struct alg_test_desc alg_test_descs[] = {
45264526
.suite = {
45274527
.hash = __VECS(crc32c_tv_template)
45284528
}
4529+
}, {
4530+
.alg = "crc64-rocksoft",
4531+
.test = alg_test_hash,
4532+
.fips_allowed = 1,
4533+
.suite = {
4534+
.hash = __VECS(crc64_rocksoft_tv_template)
4535+
}
45294536
}, {
45304537
.alg = "crct10dif",
45314538
.test = alg_test_hash,

crypto/testmgr.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5106,6 +5106,21 @@ static const struct hash_testvec rmd160_tv_template[] = {
51065106
}
51075107
};
51085108

5109+
static const u8 zeroes[4096] = { [0 ... 4095] = 0 };
5110+
static const u8 ones[4096] = { [0 ... 4095] = 0xff };
5111+
5112+
static const struct hash_testvec crc64_rocksoft_tv_template[] = {
5113+
{
5114+
.plaintext = zeroes,
5115+
.psize = 4096,
5116+
.digest = "\x4e\xb6\x22\xeb\x67\xd3\x82\x64",
5117+
}, {
5118+
.plaintext = ones,
5119+
.psize = 4096,
5120+
.digest = "\xac\xa3\xec\x02\x73\xba\xdd\xc0",
5121+
}
5122+
};
5123+
51095124
static const struct hash_testvec crct10dif_tv_template[] = {
51105125
{
51115126
.plaintext = "abc",

0 commit comments

Comments
 (0)