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.
}
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,
{
}
-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)
{
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");
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
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)
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 {
};
#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);
{
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)
{
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;
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