From: Christoph Hellwig Date: Mon, 7 Jun 2021 06:10:36 +0000 (+0200) Subject: block: devirtualize the integrity processing X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fintegrity-devirtualize;p=users%2Fhch%2Fblock.git block: devirtualize the integrity processing Replace the profile with a simple integer indicating the PI type and a new flag to signal that any integrity/metadata processing is enabled and remove the various indirect calls. To make this work t10-pi.c is not always built into the core kernel when BLK_DEV_INTEGRITY is enabled, but it is down to a few hundred lines of code and thus not very efficient when built as a separate module anyway. Signed-off-by: Christoph Hellwig --- diff --git a/block/Kconfig b/block/Kconfig index a2297edfdde8..8f666552b165 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -66,6 +66,7 @@ config BLK_DEV_BSGLIB config BLK_DEV_INTEGRITY bool "Block layer data integrity support" + select CRC_T10DIF help Some storage devices allow extra information to be stored/retrieved to help protect the data. The block layer @@ -73,13 +74,7 @@ config BLK_DEV_INTEGRITY filesystems to ensure better data integrity. Say yes here if you have a storage device that provides the - T10/SCSI Data Integrity Field or the T13/ATA External Path - Protection. If in doubt, say N. - -config BLK_DEV_INTEGRITY_T10 - tristate - depends on BLK_DEV_INTEGRITY - select CRC_T10DIF + T10/SCSI Data Integrity Field. If in doubt, say N. config BLK_DEV_ZONED bool "Zoned block device support" diff --git a/block/Makefile b/block/Makefile index 8d841f5f986f..0cbbdf5dbe67 100644 --- a/block/Makefile +++ b/block/Makefile @@ -25,8 +25,7 @@ bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o obj-$(CONFIG_IOSCHED_BFQ) += bfq.o obj-$(CONFIG_BLK_CMDLINE_PARSER) += cmdline-parser.o -obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o -obj-$(CONFIG_BLK_DEV_INTEGRITY_T10) += t10-pi.o +obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o obj-$(CONFIG_BLK_MQ_VIRTIO) += blk-mq-virtio.o obj-$(CONFIG_BLK_MQ_RDMA) += blk-mq-rdma.o diff --git a/block/bio-integrity.c b/block/bio-integrity.c index f17682164ea0..de48d27788d0 100644 --- a/block/bio-integrity.c +++ b/block/bio-integrity.c @@ -148,44 +148,6 @@ int bio_integrity_add_page(struct bio *bio, struct page *page, } EXPORT_SYMBOL(bio_integrity_add_page); -/** - * bio_integrity_process - Process integrity metadata for a bio - * @bio: bio to generate/verify integrity metadata for - * @proc_iter: iterator to process - * @proc_fn: Pointer to the relevant processing function - */ -static blk_status_t bio_integrity_process(struct bio *bio, - struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn) -{ - struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); - struct blk_integrity_iter iter; - struct bvec_iter bviter; - struct bio_vec bv; - struct bio_integrity_payload *bip = bio_integrity(bio); - blk_status_t ret = BLK_STS_OK; - void *prot_buf = page_address(bip->bip_vec->bv_page) + - bip->bip_vec->bv_offset; - - iter.disk_name = bio->bi_bdev->bd_disk->disk_name; - iter.interval = 1 << bi->interval_exp; - iter.seed = proc_iter->bi_sector; - iter.prot_buf = prot_buf; - - __bio_for_each_segment(bv, bio, bviter, *proc_iter) { - void *kaddr = bvec_kmap_local(&bv); - - iter.data_buf = kaddr; - iter.data_size = bv.bv_len; - ret = proc_fn(&iter); - kunmap_local(kaddr); - - if (ret) - break; - - } - return ret; -} - /** * bio_integrity_prep - Prepare bio for integrity I/O * @bio: bio to prepare @@ -221,7 +183,6 @@ bool bio_integrity_prep(struct bio *bio) /* Already protected? */ if (bio_integrity(bio)) return true; - if (bio_data_dir(bio) == READ) { if (!(bi->flags & BLK_INTEGRITY_VERIFY)) return true; @@ -288,8 +249,8 @@ bool bio_integrity_prep(struct bio *bio) /* Auto-generate integrity metadata if this is a write */ if (bio_data_dir(bio) == WRITE) { - bio_integrity_process(bio, &bio->bi_iter, - bi->profile->generate_fn); + if (bi->type > 0) + t10_pi_generate(bio); } else { bip->bio_iter = bio->bi_iter; } @@ -316,15 +277,9 @@ static void bio_integrity_verify_fn(struct work_struct *work) struct bio_integrity_payload *bip = container_of(work, struct bio_integrity_payload, bip_work); struct bio *bio = bip->bip_bio; - struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); - /* - * At the moment verify is called bio's iterator was advanced - * during split and completion, we need to rewind iterator to - * it's original position. - */ - bio->bi_status = bio_integrity_process(bio, &bip->bio_iter, - bi->profile->verify_fn); + if (blk_get_integrity(bio->bi_bdev->bd_disk)->type > 0) + t10_pi_verify(bio); bio_integrity_free(bio); bio_endio(bio); } @@ -351,7 +306,6 @@ bool __bio_integrity_endio(struct bio *bio) queue_work(kintegrityd_wq, &bip->bip_work); return false; } - bio_integrity_free(bio); return true; } diff --git a/block/blk-core.c b/block/blk-core.c index 3515a66022d7..450ea6663778 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1419,11 +1419,9 @@ bool blk_update_request(struct request *req, blk_status_t error, if (!req->bio) return false; -#ifdef CONFIG_BLK_DEV_INTEGRITY - if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ && - error == BLK_STS_OK) - req->q->integrity.profile->complete_fn(req, nr_bytes); -#endif + if (req_op(req) == REQ_OP_READ && error == BLK_STS_OK && + t10_pi_need_remap(req)) + t10_pi_type1_complete(req, nr_bytes); if (unlikely(error && !blk_rq_is_passthrough(req) && !(req->rq_flags & RQF_QUIET))) diff --git a/block/blk-integrity.c b/block/blk-integrity.c index 607600299334..b5129c23ab1b 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -13,12 +13,27 @@ #include #include #include +#include #include "blk.h" const char *blk_integrity_type_str(struct blk_integrity *bi) { - return bi->profile->name; + switch (bi->type) { + case 0: + return "nop"; + case T10_PI_TYPE1_PROTECTION: + case T10_PI_TYPE2_PROTECTION: + if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM) + return "T10-DIF-TYPE1-IP"; + return "T10-DIF-TYPE1-CRC"; + case T10_PI_TYPE3_PROTECTION: + if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM) + return "T10-DIF-TYPE3-IP"; + return "T10-DIF-TYPE3-CRC"; + default: + return "invalid"; + } } EXPORT_SYMBOL_GPL(blk_integrity_type_str); @@ -129,10 +144,10 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) struct blk_integrity *b1 = &gd1->queue->integrity; struct blk_integrity *b2 = &gd2->queue->integrity; - if (!b1->profile && !b2->profile) + if (!b1->type && !b2->type) return 0; - if (!b1->profile || !b2->profile) + if (!b1->type || !b2->type) return -1; if (b1->interval_exp != b2->interval_exp) { @@ -152,14 +167,14 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) { pr_err("%s: %s/%s tag sz %u != %u\n", __func__, gd1->disk_name, gd2->disk_name, - b1->tag_size, b2->tag_size); + blk_integrity_type_str(b1), blk_integrity_type_str(b2)); return -1; } - if (b1->profile != b2->profile) { + if (b1->type != b2->type) { pr_err("%s: %s/%s type %s != %s\n", __func__, gd1->disk_name, gd2->disk_name, - b1->profile->name, b2->profile->name); + blk_integrity_type_str(b1), blk_integrity_type_str(b2)); return -1; } @@ -246,10 +261,9 @@ static ssize_t integrity_attr_store(struct kobject *kobj, static ssize_t integrity_format_show(struct blk_integrity *bi, char *page) { - if (bi->profile && bi->profile->name) - return sprintf(page, "%s\n", bi->profile->name); - else + if (!(bi->flags & BLK_INTEGRITY_ENABLED)) return sprintf(page, "none\n"); + return sprintf(page, "%s\n", blk_integrity_type_str(bi)); } static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page) @@ -269,7 +283,7 @@ static ssize_t integrity_verify_store(struct blk_integrity *bi, char *p = (char *) page; unsigned long val = simple_strtoul(p, &p, 10); - if (!bi->profile->verify_fn) + if (!bi->type) return -EINVAL; if (val) @@ -291,7 +305,7 @@ static ssize_t integrity_generate_store(struct blk_integrity *bi, char *p = (char *) page; unsigned long val = simple_strtoul(p, &p, 10); - if (!bi->profile->generate_fn) + if (!bi->type) return -EINVAL; if (val) @@ -366,28 +380,6 @@ static struct kobj_type integrity_ktype = { .sysfs_ops = &integrity_ops, }; -static blk_status_t blk_integrity_nop_fn(struct blk_integrity_iter *iter) -{ - return BLK_STS_OK; -} - -static void blk_integrity_nop_prepare(struct request *rq) -{ -} - -static void blk_integrity_nop_complete(struct request *rq, - unsigned int nr_bytes) -{ -} - -static const struct blk_integrity_profile nop_profile = { - .name = "nop", - .generate_fn = blk_integrity_nop_fn, - .verify_fn = blk_integrity_nop_fn, - .prepare_fn = blk_integrity_nop_prepare, - .complete_fn = blk_integrity_nop_complete, -}; - /** * blk_nointegrity_register - Register a gendisk as having non-itegrity metadata * @disk: struct gendisk pointer to make integrity-aware @@ -397,8 +389,8 @@ void blk_nointegrity_register(struct gendisk *disk, unsigned char meta_size) { struct blk_integrity *bi = &disk->queue->integrity; - bi->flags = 0; - bi->profile = &nop_profile; + bi->flags = BLK_INTEGRITY_ENABLED; + bi->type = 0; bi->tuple_size = meta_size; bi->tag_size = meta_size; bi->interval_exp = ilog2(queue_logical_block_size(disk->queue)); diff --git a/block/blk-mq.c b/block/blk-mq.c index f11d4018ce2e..a821796ec952 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -727,10 +727,8 @@ void blk_mq_start_request(struct request *rq) blk_add_timer(rq); WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT); -#ifdef CONFIG_BLK_DEV_INTEGRITY - if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE) - q->integrity.profile->prepare_fn(rq); -#endif + if (req_op(rq) == REQ_OP_WRITE && t10_pi_need_remap(rq)) + t10_pi_type1_prepare(rq); } EXPORT_SYMBOL(blk_mq_start_request); diff --git a/block/blk.h b/block/blk.h index 3440142f029b..39e3d9c6dfaa 100644 --- a/block/blk.h +++ b/block/blk.h @@ -7,6 +7,7 @@ #include #include #include /* for max_pfn/max_low_pfn */ +#include #include #include "blk-crypto-internal.h" #include "blk-mq.h" @@ -134,6 +135,15 @@ static inline bool integrity_req_gap_front_merge(struct request *req, void blk_integrity_add(struct gendisk *); void blk_integrity_del(struct gendisk *); + +static inline bool t10_pi_need_remap(struct request *rq) +{ + if (!blk_integrity_rq(rq)) + return false; + /* Type 3 does not have a reference tag so no remapping is required. */ + return rq->q->integrity.type == T10_PI_TYPE1_PROTECTION || + rq->q->integrity.type == T10_PI_TYPE2_PROTECTION; +} #else /* CONFIG_BLK_DEV_INTEGRITY */ static inline bool blk_integrity_merge_rq(struct request_queue *rq, struct request *r1, struct request *r2) @@ -172,8 +182,17 @@ static inline void blk_integrity_add(struct gendisk *disk) static inline void blk_integrity_del(struct gendisk *disk) { } +static inline bool t10_pi_need_remap(struct request *rq) +{ + return false; +} #endif /* CONFIG_BLK_DEV_INTEGRITY */ +void t10_pi_generate(struct bio *bio); +void t10_pi_verify(struct bio *bio); +void t10_pi_type1_prepare(struct request *rq); +void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes); + unsigned long blk_rq_timeout(unsigned long timeout); void blk_add_timer(struct request *req); diff --git a/block/t10-pi.c b/block/t10-pi.c index 8c31bc859f24..d413868fedcd 100644 --- a/block/t10-pi.c +++ b/block/t10-pi.c @@ -9,17 +9,15 @@ #include #include #include +#include "blk.h" -typedef __be16 (csum_fn) (void *, unsigned int); - -static __be16 t10_pi_crc_fn(void *data, unsigned int len) +static __be16 t10_pi_csum(struct blk_integrity *bi, void *data) { - return cpu_to_be16(crc_t10dif(data, len)); -} + unsigned short interval = 1 << bi->interval_exp; -static __be16 t10_pi_ip_fn(void *data, unsigned int len) -{ - return (__force __be16)ip_compute_csum(data, len); + if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM) + return (__force __be16)ip_compute_csum(data, interval); + return cpu_to_be16(crc_t10dif(data, interval)); } /* @@ -27,97 +25,113 @@ static __be16 t10_pi_ip_fn(void *data, unsigned int len) * 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref * tag. */ -static blk_status_t t10_pi_generate(struct blk_integrity_iter *iter, - csum_fn *fn, enum t10_dif_type type) +static void t10_pi_generate_bvec(struct bio *bio, sector_t seed, + struct bio_vec *data_bvec, void *prot_buf) { + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + unsigned short interval = 1 << bi->interval_exp; + void *data_buf = bvec_kmap_local(data_bvec); unsigned int i; - for (i = 0 ; i < iter->data_size ; i += iter->interval) { - struct t10_pi_tuple *pi = iter->prot_buf; + for (i = 0 ; i < data_bvec->bv_len ; i += interval) { + struct t10_pi_tuple *pi = prot_buf; - pi->guard_tag = fn(iter->data_buf, iter->interval); + pi->guard_tag = t10_pi_csum(bi, data_buf); pi->app_tag = 0; - if (type == T10_PI_TYPE1_PROTECTION) - pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed)); + if (bi->type == T10_PI_TYPE1_PROTECTION) + pi->ref_tag = cpu_to_be32(lower_32_bits(seed)); else pi->ref_tag = 0; - iter->data_buf += iter->interval; - iter->prot_buf += sizeof(struct t10_pi_tuple); - iter->seed++; + data_buf += interval; + prot_buf += sizeof(struct t10_pi_tuple); + seed++; } - return BLK_STS_OK; + kunmap_local(data_buf); } -static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter, - csum_fn *fn, enum t10_dif_type type) +void t10_pi_generate(struct bio *bio) { + void *prot_buf = bvec_virt(bio_integrity(bio)->bip_vec); + struct bvec_iter iter; + struct bio_vec bv; + + __bio_for_each_segment(bv, bio, iter, bio->bi_iter) + t10_pi_generate_bvec(bio, iter.bi_sector, &bv, prot_buf); +} + +static blk_status_t t10_pi_verify_bvec(struct bio *bio, sector_t seed, + struct bio_vec *data_bvec, void *prot_buf) +{ + struct gendisk *disk = bio->bi_bdev->bd_disk; + struct blk_integrity *bi = blk_get_integrity(disk); + unsigned short interval = 1 << bi->interval_exp; + void *data_buf = bvec_kmap_local(data_bvec); + blk_status_t ret = BLK_STS_PROTECTION; unsigned int i; - BUG_ON(type == T10_PI_TYPE0_PROTECTION); + BUG_ON(bi->type == T10_PI_TYPE0_PROTECTION); - for (i = 0 ; i < iter->data_size ; i += iter->interval) { - struct t10_pi_tuple *pi = iter->prot_buf; + for (i = 0 ; i < data_bvec->bv_len ; i += interval) { + struct t10_pi_tuple *pi = prot_buf; __be16 csum; - if (type == T10_PI_TYPE1_PROTECTION || - type == T10_PI_TYPE2_PROTECTION) { + if (bi->type == T10_PI_TYPE1_PROTECTION || + bi->type == T10_PI_TYPE2_PROTECTION) { if (pi->app_tag == T10_PI_APP_ESCAPE) goto next; - if (be32_to_cpu(pi->ref_tag) != - lower_32_bits(iter->seed)) { - pr_err("%s: ref tag error at location %llu " \ - "(rcvd %u)\n", iter->disk_name, - (unsigned long long) - iter->seed, be32_to_cpu(pi->ref_tag)); - return BLK_STS_PROTECTION; + if (be32_to_cpu(pi->ref_tag) != lower_32_bits(seed)) { + pr_err("%s: ref tag error at location %llu (rcvd %u)\n", + disk->disk_name, seed, + be32_to_cpu(pi->ref_tag)); + goto out_unmap; } - } else if (type == T10_PI_TYPE3_PROTECTION) { + } else if (bi->type == T10_PI_TYPE3_PROTECTION) { if (pi->app_tag == T10_PI_APP_ESCAPE && pi->ref_tag == T10_PI_REF_ESCAPE) goto next; } - csum = fn(iter->data_buf, iter->interval); - + csum = t10_pi_csum(bi, data_buf); if (pi->guard_tag != csum) { - pr_err("%s: guard tag error at sector %llu " \ - "(rcvd %04x, want %04x)\n", iter->disk_name, - (unsigned long long)iter->seed, - be16_to_cpu(pi->guard_tag), be16_to_cpu(csum)); - return BLK_STS_PROTECTION; + pr_err("%s: guard tag error at sector %llu (rcvd %04x, want %04x)\n", + disk->disk_name, seed, + be16_to_cpu(pi->guard_tag), be16_to_cpu(csum)); + goto out_unmap; } next: - iter->data_buf += iter->interval; - iter->prot_buf += sizeof(struct t10_pi_tuple); - iter->seed++; + data_buf += interval; + prot_buf += sizeof(struct t10_pi_tuple); + seed++; } - return BLK_STS_OK; -} - -static blk_status_t t10_pi_type1_generate_crc(struct blk_integrity_iter *iter) -{ - return t10_pi_generate(iter, t10_pi_crc_fn, T10_PI_TYPE1_PROTECTION); + ret = BLK_STS_OK; +out_unmap: + kunmap_local(data_buf); + return ret; } -static blk_status_t t10_pi_type1_generate_ip(struct blk_integrity_iter *iter) +void t10_pi_verify(struct bio *bio) { - return t10_pi_generate(iter, t10_pi_ip_fn, T10_PI_TYPE1_PROTECTION); -} - -static blk_status_t t10_pi_type1_verify_crc(struct blk_integrity_iter *iter) -{ - return t10_pi_verify(iter, t10_pi_crc_fn, T10_PI_TYPE1_PROTECTION); -} + void *prot_buf = bvec_virt(bio_integrity(bio)->bip_vec); + struct bvec_iter iter; + struct bio_vec bv; + + /* + * At this point bi_iter has already been advanced, so use the copy + * saved away at submission time. + */ + __bio_for_each_segment(bv, bio, iter, bio->bi_integrity->bio_iter) { + bio->bi_status = t10_pi_verify_bvec(bio, iter.bi_sector, &bv, + prot_buf); + if (bio->bi_status) + break; -static blk_status_t t10_pi_type1_verify_ip(struct blk_integrity_iter *iter) -{ - return t10_pi_verify(iter, t10_pi_ip_fn, T10_PI_TYPE1_PROTECTION); + } } /** @@ -130,8 +144,9 @@ static blk_status_t t10_pi_type1_verify_ip(struct blk_integrity_iter *iter) * likely to be different. Remap protection information to match the * physical LBA. */ -static void t10_pi_type1_prepare(struct request *rq) +void t10_pi_type1_prepare(struct request *rq) { + struct blk_integrity *bi = &rq->q->integrity; const int tuple_sz = rq->q->integrity.tuple_size; u32 ref_tag = t10_pi_ref_tag(rq); struct bio *bio; @@ -179,10 +194,11 @@ static void t10_pi_type1_prepare(struct request *rq) * to the device, we should remap it back to virtual values expected by the * block layer. */ -static void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes) +void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes) { - unsigned intervals = nr_bytes >> rq->q->integrity.interval_exp; - const int tuple_sz = rq->q->integrity.tuple_size; + struct blk_integrity *bi = &rq->q->integrity; + unsigned intervals = nr_bytes >> bi->interval_exp; + const int tuple_sz = bi->tuple_size; u32 ref_tag = t10_pi_ref_tag(rq); struct bio *bio; @@ -212,70 +228,6 @@ static void t10_pi_type1_complete(struct request *rq, unsigned int nr_bytes) } } -static blk_status_t t10_pi_type3_generate_crc(struct blk_integrity_iter *iter) -{ - return t10_pi_generate(iter, t10_pi_crc_fn, T10_PI_TYPE3_PROTECTION); -} - -static blk_status_t t10_pi_type3_generate_ip(struct blk_integrity_iter *iter) -{ - return t10_pi_generate(iter, t10_pi_ip_fn, T10_PI_TYPE3_PROTECTION); -} - -static blk_status_t t10_pi_type3_verify_crc(struct blk_integrity_iter *iter) -{ - return t10_pi_verify(iter, t10_pi_crc_fn, T10_PI_TYPE3_PROTECTION); -} - -static blk_status_t t10_pi_type3_verify_ip(struct blk_integrity_iter *iter) -{ - return t10_pi_verify(iter, t10_pi_ip_fn, T10_PI_TYPE3_PROTECTION); -} - -/* Type 3 does not have a reference tag so no remapping is required. */ -static void t10_pi_type3_prepare(struct request *rq) -{ -} - -/* Type 3 does not have a reference tag so no remapping is required. */ -static void t10_pi_type3_complete(struct request *rq, unsigned int nr_bytes) -{ -} - -const struct blk_integrity_profile t10_pi_type1_crc = { - .name = "T10-DIF-TYPE1-CRC", - .generate_fn = t10_pi_type1_generate_crc, - .verify_fn = t10_pi_type1_verify_crc, - .prepare_fn = t10_pi_type1_prepare, - .complete_fn = t10_pi_type1_complete, -}; -EXPORT_SYMBOL(t10_pi_type1_crc); - -static const struct blk_integrity_profile t10_pi_type1_ip = { - .name = "T10-DIF-TYPE1-IP", - .generate_fn = t10_pi_type1_generate_ip, - .verify_fn = t10_pi_type1_verify_ip, - .prepare_fn = t10_pi_type1_prepare, - .complete_fn = t10_pi_type1_complete, -}; - -const struct blk_integrity_profile t10_pi_type3_crc = { - .name = "T10-DIF-TYPE3-CRC", - .generate_fn = t10_pi_type3_generate_crc, - .verify_fn = t10_pi_type3_verify_crc, - .prepare_fn = t10_pi_type3_prepare, - .complete_fn = t10_pi_type3_complete, -}; -EXPORT_SYMBOL(t10_pi_type3_crc); - -static const struct blk_integrity_profile t10_pi_type3_ip = { - .name = "T10-DIF-TYPE3-IP", - .generate_fn = t10_pi_type3_generate_ip, - .verify_fn = t10_pi_type3_verify_ip, - .prepare_fn = t10_pi_type3_prepare, - .complete_fn = t10_pi_type3_complete, -}; - /** * t10_pi_register - Register a gendisk as being T10-PI capable * @disk: struct gendisk pointer to make integrity-aware @@ -293,16 +245,7 @@ void t10_pi_register(struct gendisk *disk, enum t10_dif_type type, break; case T10_PI_TYPE2_PROTECTION: case T10_PI_TYPE1_PROTECTION: - if (flags & BLK_INTEGRITY_IP_CHECKSUM) - bi->profile = &t10_pi_type1_ip; - else - bi->profile = &t10_pi_type1_crc; - break; case T10_PI_TYPE3_PROTECTION: - if (flags & BLK_INTEGRITY_IP_CHECKSUM) - bi->profile = &t10_pi_type3_ip; - else - bi->profile = &t10_pi_type3_crc; break; default: WARN_ON_ONCE(1); @@ -311,7 +254,9 @@ void t10_pi_register(struct gendisk *disk, enum t10_dif_type type, bi->tuple_size = sizeof(struct t10_pi_tuple); bi->interval_exp = ilog2(queue_logical_block_size(disk->queue)); - bi->flags = flags | BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE; + bi->flags = flags | BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE | + BLK_INTEGRITY_ENABLED; + bi->type = type; if (!(flags & BLK_INTEGRITY_APP_TAG)) bi->tag_size = 0; @@ -331,5 +276,3 @@ void t10_pi_register(struct gendisk *disk, enum t10_dif_type type, #endif } EXPORT_SYMBOL(t10_pi_register); - -MODULE_LICENSE("GPL"); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 9a956faab135..05c13502fb1b 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1165,7 +1165,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti) struct mapped_device *md = dm_table_get_md(ti->table); /* From now we require underlying device with our integrity profile */ - if (!bi || strcmp(bi->profile->name, "nop")) { + if (!bi || bi->type != 0) { ti->error = "Integrity profile not supported."; return -EINVAL; } diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index a44d49d63968..f7da23cf7a6f 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only config NVME_CORE tristate - select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY config BLK_DEV_NVME tristate "NVM Express block device" diff --git a/drivers/nvme/target/Kconfig b/drivers/nvme/target/Kconfig index 4be2ececbc45..3d8200f8bb37 100644 --- a/drivers/nvme/target/Kconfig +++ b/drivers/nvme/target/Kconfig @@ -4,7 +4,6 @@ config NVME_TARGET tristate "NVMe Target support" depends on BLOCK depends on CONFIGFS_FS - select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY select SGL_ALLOC help This enabled target side support for the NVMe protocol, that is diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index 429263ca9b97..9e9edc972c5d 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c @@ -53,10 +53,8 @@ static void nvmet_bdev_ns_enable_integrity(struct nvmet_ns *ns) if (bi) { ns->metadata_size = bi->tuple_size; - if (bi->profile == &t10_pi_type1_crc) - ns->pi_type = NVME_NS_DPS_PI_TYPE1; - else if (bi->profile == &t10_pi_type3_crc) - ns->pi_type = NVME_NS_DPS_PI_TYPE3; + if (bi->type >= 1 && bi->type <= 3) + ns->pi_type = bi->type; else /* Unsupported metadata type */ ns->metadata_size = 0; @@ -83,7 +81,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns) ns->pi_type = 0; ns->metadata_size = 0; - if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY_T10)) + if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) nvmet_bdev_ns_enable_integrity(ns); return 0; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3d114be5b662..aa823795991e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -68,7 +68,6 @@ comment "SCSI support type (disk, tape, CD-ROM)" config BLK_DEV_SD tristate "SCSI disk support" depends on SCSI - select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY help If you want to use SCSI hard disks, Fibre Channel disks, Serial ATA (SATA) or Parallel ATA (PATA) hard disks, diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index d6fdd1c61f90..faabc130df2a 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -139,20 +139,15 @@ static int iblock_configure_device(struct se_device *dev) if (bi) { struct bio_set *bs = &ib_dev->ibd_bio_set; - if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-IP") || - !strcmp(bi->profile->name, "T10-DIF-TYPE1-IP")) { - pr_err("IBLOCK export of blk_integrity: %s not" - " supported\n", bi->profile->name); + if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM) { + pr_err("IBLOCK export of blk_integrity: %s not supported\n", + blk_integrity_type_str(bi)); ret = -ENOSYS; goto out_blkdev_put; } - if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-CRC")) { - dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT; - } else if (!strcmp(bi->profile->name, "T10-DIF-TYPE1-CRC")) { - dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT; - } - + if (bi->type >= 1 && bi->type <= 3) + dev->dev_attrib.pi_prot_type = bi->type; if (dev->dev_attrib.pi_prot_type) { if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) { pr_err("Unable to allocate bioset for PI\n"); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 24a1a230dfd5..b2858aaa26c6 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1653,30 +1653,10 @@ enum blk_integrity_flags { BLK_INTEGRITY_DEVICE_CAPABLE = 1 << 2, BLK_INTEGRITY_IP_CHECKSUM = 1 << 3, BLK_INTEGRITY_APP_TAG = 1 << 4, + BLK_INTEGRITY_ENABLED = 1 << 5, }; #ifdef CONFIG_BLK_DEV_INTEGRITY -struct blk_integrity_iter { - void *prot_buf; - void *data_buf; - sector_t seed; - unsigned int data_size; - unsigned short interval; - const char *disk_name; -}; - -typedef blk_status_t (integrity_processing_fn) (struct blk_integrity_iter *); -typedef void (integrity_prepare_fn) (struct request *); -typedef void (integrity_complete_fn) (struct request *, unsigned int); - -struct blk_integrity_profile { - integrity_processing_fn *generate_fn; - integrity_processing_fn *verify_fn; - integrity_prepare_fn *prepare_fn; - integrity_complete_fn *complete_fn; - const char *name; -}; - void blk_integrity_copy(struct gendisk *to, struct gendisk *from); void blk_nointegrity_register(struct gendisk *disk, unsigned char meta_size); extern void blk_integrity_unregister(struct gendisk *); @@ -1689,9 +1669,8 @@ static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) { struct blk_integrity *bi = &disk->queue->integrity; - if (!bi->profile) + if (!(bi->flags & BLK_INTEGRITY_ENABLED)) return NULL; - return bi; } @@ -1704,7 +1683,7 @@ struct blk_integrity *bdev_get_integrity(struct block_device *bdev) static inline bool blk_queue_supports_integrity(struct request_queue *q) { - return q->integrity.profile; + return q->integrity.flags & BLK_INTEGRITY_ENABLED; } static inline bool blk_integrity_rq(struct request *rq) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 03d684f0498f..d85ba614b2ba 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -121,7 +121,7 @@ struct disk_events; struct badblocks; struct blk_integrity { - const struct blk_integrity_profile *profile; + unsigned char type; unsigned char flags; unsigned char tuple_size; unsigned char interval_exp; diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h index 6758dd7844a7..0cb1e86de28e 100644 --- a/include/linux/t10-pi.h +++ b/include/linux/t10-pi.h @@ -51,7 +51,4 @@ static inline u32 t10_pi_ref_tag(struct request *rq) void t10_pi_register(struct gendisk *disk, enum t10_dif_type type, unsigned int flags); -extern const struct blk_integrity_profile t10_pi_type1_crc; -extern const struct blk_integrity_profile t10_pi_type3_crc; - #endif