From: Christoph Hellwig Date: Thu, 9 Jun 2022 07:37:15 +0000 (+0200) Subject: block: add a new interface to enable T10-PI X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fblock-pi-cleanup;p=users%2Fhch%2Fblock.git block: add a new interface to enable T10-PI Replace blk_integrity_register with more targeted t10_pi_register interfaces, which just takes a PI type and flags argument. Two new flags are added to indicate support for the new 64-bit guard added in NVMe and to indicate if the HBA supports app tags. Signed-off-by: Christoph Hellwig --- diff --git a/Documentation/block/data-integrity.rst b/Documentation/block/data-integrity.rst index 07a97aa26668..4c3adeb3910a 100644 --- a/Documentation/block/data-integrity.rst +++ b/Documentation/block/data-integrity.rst @@ -156,7 +156,7 @@ bio_free() will automatically free the bip. Because the format of the protection data is tied to the physical disk, each block device has been extended with a block integrity profile (struct blk_integrity). This optional profile is registered -with the block layer using blk_integrity_register(). +with the block layer using t10_pi_register(). The profile contains callback functions for generating and verifying the protection data, as well as getting and setting application tags. diff --git a/block/blk-integrity.c b/block/blk-integrity.c index fdd925abf482..b4585089d607 100644 --- a/block/blk-integrity.c +++ b/block/blk-integrity.c @@ -407,32 +407,6 @@ void blk_nointegrity_register(struct gendisk *disk, unsigned char meta_size, } EXPORT_SYMBOL(blk_nointegrity_register); -/** - * blk_integrity_register - Register a gendisk as being integrity-capable - * @disk: struct gendisk pointer to make integrity-aware - * @template: block integrity profile to register - * - * Description: When a device needs to advertise itself as being able to - * send/receive integrity metadata it must use this function to register - * the capability with the block layer. The template is a blk_integrity - * struct with values appropriate for the underlying hardware. See - * Documentation/block/data-integrity.rst. - */ -void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template) -{ - struct blk_integrity *bi = &disk->queue->integrity; - - bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE | - template->flags; - bi->interval_exp = template->interval_exp ? : - ilog2(queue_logical_block_size(disk->queue)); - bi->profile = template->profile ? template->profile : &nop_profile; - bi->tuple_size = template->tuple_size; - bi->tag_size = template->tag_size; - blk_integrity_init(disk); -} -EXPORT_SYMBOL(blk_integrity_register); - void blk_integrity_copy(struct gendisk *to, struct gendisk *from) { memcpy(&to->queue->integrity, &from->queue->integrity, diff --git a/block/t10-pi.c b/block/t10-pi.c index 914d8cddd43a..7c0bc622bc13 100644 --- a/block/t10-pi.c +++ b/block/t10-pi.c @@ -244,41 +244,37 @@ static void t10_pi_type3_complete(struct request *rq, unsigned int nr_bytes) { } -const struct blk_integrity_profile t10_pi_type1_crc = { +static 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); -const struct blk_integrity_profile t10_pi_type1_ip = { +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, }; -EXPORT_SYMBOL(t10_pi_type1_ip); -const struct blk_integrity_profile t10_pi_type3_crc = { +static 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); -const struct blk_integrity_profile t10_pi_type3_ip = { +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, }; -EXPORT_SYMBOL(t10_pi_type3_ip); static __be64 ext_pi_crc64(void *data, unsigned int len) { @@ -453,23 +449,79 @@ static blk_status_t ext_pi_type3_generate_crc64(struct blk_integrity_iter *iter) return ext_pi_crc64_generate(iter, T10_PI_TYPE3_PROTECTION); } -const struct blk_integrity_profile ext_pi_type1_crc64 = { +static const struct blk_integrity_profile ext_pi_type1_crc64 = { .name = "EXT-DIF-TYPE1-CRC64", .generate_fn = ext_pi_type1_generate_crc64, .verify_fn = ext_pi_type1_verify_crc64, .prepare_fn = ext_pi_type1_prepare, .complete_fn = ext_pi_type1_complete, }; -EXPORT_SYMBOL_GPL(ext_pi_type1_crc64); -const struct blk_integrity_profile ext_pi_type3_crc64 = { +static const struct blk_integrity_profile ext_pi_type3_crc64 = { .name = "EXT-DIF-TYPE3-CRC64", .generate_fn = ext_pi_type3_generate_crc64, .verify_fn = ext_pi_type3_verify_crc64, .prepare_fn = t10_pi_type3_prepare, .complete_fn = t10_pi_type3_complete, }; -EXPORT_SYMBOL_GPL(ext_pi_type3_crc64); + +/** + * t10_pi_register - Register a gendisk as being T10-PI capable + * @disk: struct gendisk pointer to make integrity-aware + * @type: Protetion type + * @flags: BLK_INTEGRITY_* flags applicatble to this disk + */ +void t10_pi_register(struct gendisk *disk, enum t10_dif_type type, + unsigned int flags) +{ + struct blk_integrity *bi = &disk->queue->integrity; + + WARN_ON_ONCE((flags & BLK_INTEGRITY_16B_GUARD) && + (flags & BLK_INTEGRITY_IP_CHECKSUM)); + + switch (type) { + case T10_PI_TYPE0_PROTECTION: + flags &= ~(BLK_INTEGRITY_DEVICE_CAPABLE | BLK_INTEGRITY_APP_TAG); + break; + case T10_PI_TYPE2_PROTECTION: + case T10_PI_TYPE1_PROTECTION: + if (flags & BLK_INTEGRITY_16B_GUARD) + bi->profile = &ext_pi_type1_crc64; + else if (flags & BLK_INTEGRITY_IP_CHECKSUM) + bi->profile = &t10_pi_type1_ip; + else + bi->profile = &t10_pi_type1_crc; + bi->tag_size = sizeof(u16); + break; + case T10_PI_TYPE3_PROTECTION: + if (flags & BLK_INTEGRITY_16B_GUARD) { + bi->profile = &ext_pi_type3_crc64; + bi->tag_size = sizeof(u16) + 6; + } else { + if (flags & BLK_INTEGRITY_IP_CHECKSUM) + bi->profile = &t10_pi_type3_ip; + else + bi->profile = &t10_pi_type3_crc; + bi->tag_size = sizeof(u16) + sizeof(u32); + } + break; + default: + WARN_ON_ONCE(1); + return; + } + + if (flags & BLK_INTEGRITY_16B_GUARD) + bi->tuple_size = sizeof(struct crc64_pi_tuple); + else + 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; + + if (!(flags & BLK_INTEGRITY_APP_TAG)) + bi->tag_size = 0; + blk_integrity_init(disk); +} +EXPORT_SYMBOL_GPL(t10_pi_register); MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL"); diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 24165daee3c8..0a8c6030fcc7 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1588,51 +1588,23 @@ int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo) static void nvme_init_integrity(struct gendisk *disk, struct nvme_ns *ns, u32 max_integrity_segments) { - struct blk_integrity integrity = { }; + unsigned int flags = + BLK_INTEGRITY_DEVICE_CAPABLE | BLK_INTEGRITY_APP_TAG; + + if (ns->guard_type == NVME_NVM_NS_64B_GUARD) + flags |= BLK_INTEGRITY_16B_GUARD; switch (ns->pi_type) { case NVME_NS_DPS_PI_TYPE3: - switch (ns->guard_type) { - case NVME_NVM_NS_16B_GUARD: - integrity.profile = &t10_pi_type3_crc; - integrity.tag_size = sizeof(u16) + sizeof(u32); - integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; - break; - case NVME_NVM_NS_64B_GUARD: - integrity.profile = &ext_pi_type3_crc64; - integrity.tag_size = sizeof(u16) + 6; - integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; - break; - default: - integrity.profile = NULL; - break; - } - break; case NVME_NS_DPS_PI_TYPE1: case NVME_NS_DPS_PI_TYPE2: - switch (ns->guard_type) { - case NVME_NVM_NS_16B_GUARD: - integrity.profile = &t10_pi_type1_crc; - integrity.tag_size = sizeof(u16); - integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; - break; - case NVME_NVM_NS_64B_GUARD: - integrity.profile = &ext_pi_type1_crc64; - integrity.tag_size = sizeof(u16); - integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; - break; - default: - integrity.profile = NULL; - break; - } + t10_pi_register(disk, ns->pi_type, flags); break; default: - integrity.profile = NULL; + blk_nointegrity_register(disk, ns->ms, 0); break; } - integrity.tuple_size = ns->ms; - blk_integrity_register(disk, &integrity); blk_queue_max_integrity_segments(disk->queue, max_integrity_segments); } #else diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index be8751f8f57a..409b16806bf1 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2196,56 +2196,28 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer static void sd_dif_config_host(struct scsi_disk *sdkp) { struct scsi_device *sdp = sdkp->device; - struct gendisk *disk = sdkp->disk; - u8 type = sdkp->protection_type; - struct blk_integrity bi; - int dif, dix; + unsigned int flags = 0; - dif = scsi_host_dif_capable(sdp->host, type); - dix = scsi_host_dix_capable(sdp->host, type); - - if (!dix && scsi_host_dix_capable(sdp->host, 0)) { - dif = 0; dix = 1; + if (scsi_host_dix_capable(sdp->host, sdkp->protection_type)) { + if (scsi_host_dif_capable(sdp->host, sdkp->protection_type)) { + flags |= BLK_INTEGRITY_DEVICE_CAPABLE; + if (sdkp->ATO) + flags |= BLK_INTEGRITY_APP_TAG; + } + } else { + if (!scsi_host_dix_capable(sdp->host, 0)) + return; } - if (!dix) - return; + if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) + flags |= BLK_INTEGRITY_IP_CHECKSUM; - memset(&bi, 0, sizeof(bi)); - - /* Enable DMA of protection information */ - if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { - if (type == T10_PI_TYPE3_PROTECTION) - bi.profile = &t10_pi_type3_ip; - else - bi.profile = &t10_pi_type1_ip; - - bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; - } else - if (type == T10_PI_TYPE3_PROTECTION) - bi.profile = &t10_pi_type3_crc; - else - bi.profile = &t10_pi_type1_crc; - - bi.tuple_size = sizeof(struct t10_pi_tuple); - - if (dif && type) { - bi.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; - - if (!sdkp->ATO) - goto out; - - if (type == T10_PI_TYPE3_PROTECTION) - bi.tag_size = sizeof(u16) + sizeof(u32); - else - bi.tag_size = sizeof(u16); - } + t10_pi_register(sdkp->disk, sdkp->protection_type, flags); sd_printk(KERN_NOTICE, sdkp, - "Enabling DIX %s, application tag size %u bytes\n", - bi.profile->name, bi.tag_size); -out: - blk_integrity_register(disk, &bi); + "Enabling DIX %s, application tag size %u bytes\n", + blk_get_integrity(sdkp->disk)->profile->name, + blk_get_integrity(sdkp->disk)->tag_size); } static void sd_config_protection(struct scsi_disk *sdkp) diff --git a/include/linux/blk-integrity.h b/include/linux/blk-integrity.h index 23bf81bfc723..1e5eaf051ca7 100644 --- a/include/linux/blk-integrity.h +++ b/include/linux/blk-integrity.h @@ -11,6 +11,8 @@ enum blk_integrity_flags { BLK_INTEGRITY_GENERATE = 1 << 1, BLK_INTEGRITY_DEVICE_CAPABLE = 1 << 2, BLK_INTEGRITY_IP_CHECKSUM = 1 << 3, + BLK_INTEGRITY_APP_TAG = 1 << 4, + BLK_INTEGRITY_16B_GUARD = 1 << 5, }; struct blk_integrity_iter { @@ -36,7 +38,6 @@ struct blk_integrity_profile { }; #ifdef CONFIG_BLK_DEV_INTEGRITY -void blk_integrity_register(struct gendisk *, struct blk_integrity *); void blk_nointegrity_register(struct gendisk *disk, unsigned char meta_size, u8 interval_exp); void blk_integrity_copy(struct gendisk *to, struct gendisk *from); @@ -144,10 +145,6 @@ static inline int blk_integrity_compare(struct gendisk *a, struct gendisk *b) { return 0; } -static inline void blk_integrity_register(struct gendisk *d, - struct blk_integrity *b) -{ -} static inline void blk_nointegrity_register(struct gendisk *disk, unsigned char meta_size, u8 interval_exp) { diff --git a/include/linux/t10-pi.h b/include/linux/t10-pi.h index 248f4ac95642..6aa0e8b7a57e 100644 --- a/include/linux/t10-pi.h +++ b/include/linux/t10-pi.h @@ -48,11 +48,6 @@ static inline u32 t10_pi_ref_tag(struct request *rq) return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT) & 0xffffffff; } -extern const struct blk_integrity_profile t10_pi_type1_crc; -extern const struct blk_integrity_profile t10_pi_type1_ip; -extern const struct blk_integrity_profile t10_pi_type3_crc; -extern const struct blk_integrity_profile t10_pi_type3_ip; - struct crc64_pi_tuple { __be64 guard_tag; __be16 app_tag; @@ -79,7 +74,7 @@ static inline u64 ext_pi_ref_tag(struct request *rq) return lower_48_bits(blk_rq_pos(rq) >> (shift - SECTOR_SHIFT)); } -extern const struct blk_integrity_profile ext_pi_type1_crc64; -extern const struct blk_integrity_profile ext_pi_type3_crc64; +void t10_pi_register(struct gendisk *disk, enum t10_dif_type type, + unsigned int flags); #endif