]> www.infradead.org Git - users/hch/block.git/commitdiff
block: add a new interface to enable T10-PI block-pi-cleanup
authorChristoph Hellwig <hch@lst.de>
Thu, 9 Jun 2022 07:37:15 +0000 (09:37 +0200)
committerChristoph Hellwig <hch@lst.de>
Thu, 9 Jun 2022 07:38:56 +0000 (09:38 +0200)
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 <hch@lst.de>
Documentation/block/data-integrity.rst
block/blk-integrity.c
block/t10-pi.c
drivers/nvme/host/core.c
drivers/scsi/sd.c
include/linux/blk-integrity.h
include/linux/t10-pi.h

index 07a97aa266685ca19068eddb032152be4867be31..4c3adeb3910a66eebd86ef2035a3e363214338a6 100644 (file)
@@ -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.
index fdd925abf4829d3237449281c9e763f9f5a12851..b4585089d607e1bb280b5b6af10872680291b0a6 100644 (file)
@@ -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,
index 914d8cddd43a92ebc65c02c0b92d7e7825cdc3d0..7c0bc622bc13c03197438f4b3570523b0f3980eb 100644 (file)
@@ -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");
index 24165daee3c8f0819b83d90f6c4293560c04a2c6..0a8c6030fcc789bb62ca1e8e84987db12bf7f421 100644 (file)
@@ -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
index be8751f8f57aaf10567c68a99d970e389d610057..409b16806bf1e1d9ae8c8868c8bebe231eabf442 100644 (file)
@@ -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)
index 23bf81bfc7237c427367e8c8ce327992f9b777c1..1e5eaf051ca73ef0617a830d0a261477608b7e10 100644 (file)
@@ -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)
 {
index 248f4ac9564258524cd2ea897252023718c415fe..6aa0e8b7a57e13750ff252bdef8270ba32b9360b 100644 (file)
@@ -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