Commit e9f5f44a authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe

block: remove the blk_integrity_profile structure

Block layer integrity configuration is a bit complex right now, as it
indirects through operation vectors for a simple two-dimensional
configuration:

 a) the checksum type of none, ip checksum, crc, crc64
 b) the presence or absence of a reference tag

Remove the integrity profile, and instead add a separate csum_type flag
which replaces the existing ip-checksum field and a new flag that
indicates the presence of the reference tag.

This removes up to two layers of indirect calls, remove the need to
offload the no-op verification of non-PI metadata to a workqueue and
generally simplifies the code. The downside is that block/t10-pi.c now
has to be built into the kernel when CONFIG_BLK_DEV_INTEGRITY is
supported.  Given that both nvme and SCSI require t10-pi.ko, it is loaded
for all usual configurations that enabled CONFIG_BLK_DEV_INTEGRITY
already, though.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarKanchan Joshi <joshi.k@samsung.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20240613084839.1044015-6-hch@lst.deSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 63e64959
...@@ -62,6 +62,8 @@ config BLK_DEV_BSGLIB ...@@ -62,6 +62,8 @@ config BLK_DEV_BSGLIB
config BLK_DEV_INTEGRITY config BLK_DEV_INTEGRITY
bool "Block layer data integrity support" bool "Block layer data integrity support"
select CRC_T10DIF
select CRC64_ROCKSOFT
help help
Some storage devices allow extra information to be Some storage devices allow extra information to be
stored/retrieved to help protect the data. The block layer stored/retrieved to help protect the data. The block layer
...@@ -72,12 +74,6 @@ config BLK_DEV_INTEGRITY ...@@ -72,12 +74,6 @@ config BLK_DEV_INTEGRITY
T10/SCSI Data Integrity Field or the T13/ATA External Path T10/SCSI Data Integrity Field or the T13/ATA External Path
Protection. If in doubt, say N. Protection. If in doubt, say N.
config BLK_DEV_INTEGRITY_T10
tristate
depends on BLK_DEV_INTEGRITY
select CRC_T10DIF
select CRC64_ROCKSOFT
config BLK_DEV_WRITE_MOUNTED config BLK_DEV_WRITE_MOUNTED
bool "Allow writing to mounted block devices" bool "Allow writing to mounted block devices"
default y default y
......
...@@ -26,8 +26,7 @@ obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o ...@@ -26,8 +26,7 @@ obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o
bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o bfq-y := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
obj-$(CONFIG_IOSCHED_BFQ) += bfq.o obj-$(CONFIG_IOSCHED_BFQ) += bfq.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
obj-$(CONFIG_BLK_DEV_INTEGRITY_T10) += t10-pi.o
obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o obj-$(CONFIG_BLK_MQ_PCI) += blk-mq-pci.o
obj-$(CONFIG_BLK_MQ_VIRTIO) += blk-mq-virtio.o obj-$(CONFIG_BLK_MQ_VIRTIO) += blk-mq-virtio.o
obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o obj-$(CONFIG_BLK_DEV_ZONED) += blk-zoned.o
......
...@@ -378,10 +378,9 @@ EXPORT_SYMBOL_GPL(bio_integrity_map_user); ...@@ -378,10 +378,9 @@ EXPORT_SYMBOL_GPL(bio_integrity_map_user);
* bio_integrity_process - Process integrity metadata for a bio * bio_integrity_process - Process integrity metadata for a bio
* @bio: bio to generate/verify integrity metadata for * @bio: bio to generate/verify integrity metadata for
* @proc_iter: iterator to process * @proc_iter: iterator to process
* @proc_fn: Pointer to the relevant processing function
*/ */
static blk_status_t bio_integrity_process(struct bio *bio, static blk_status_t bio_integrity_process(struct bio *bio,
struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn) struct bvec_iter *proc_iter)
{ {
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
struct blk_integrity_iter iter; struct blk_integrity_iter iter;
...@@ -392,17 +391,18 @@ static blk_status_t bio_integrity_process(struct bio *bio, ...@@ -392,17 +391,18 @@ static blk_status_t bio_integrity_process(struct bio *bio,
iter.disk_name = bio->bi_bdev->bd_disk->disk_name; iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
iter.interval = 1 << bi->interval_exp; iter.interval = 1 << bi->interval_exp;
iter.tuple_size = bi->tuple_size;
iter.seed = proc_iter->bi_sector; iter.seed = proc_iter->bi_sector;
iter.prot_buf = bvec_virt(bip->bip_vec); iter.prot_buf = bvec_virt(bip->bip_vec);
iter.pi_offset = bi->pi_offset;
__bio_for_each_segment(bv, bio, bviter, *proc_iter) { __bio_for_each_segment(bv, bio, bviter, *proc_iter) {
void *kaddr = bvec_kmap_local(&bv); void *kaddr = bvec_kmap_local(&bv);
iter.data_buf = kaddr; iter.data_buf = kaddr;
iter.data_size = bv.bv_len; iter.data_size = bv.bv_len;
ret = proc_fn(&iter); if (bio_data_dir(bio) == WRITE)
blk_integrity_generate(&iter, bi);
else
ret = blk_integrity_verify(&iter, bi);
kunmap_local(kaddr); kunmap_local(kaddr);
if (ret) if (ret)
...@@ -448,12 +448,10 @@ bool bio_integrity_prep(struct bio *bio) ...@@ -448,12 +448,10 @@ bool bio_integrity_prep(struct bio *bio)
return true; return true;
if (bio_data_dir(bio) == READ) { if (bio_data_dir(bio) == READ) {
if (!bi->profile->verify_fn || if (!(bi->flags & BLK_INTEGRITY_VERIFY))
!(bi->flags & BLK_INTEGRITY_VERIFY))
return true; return true;
} else { } else {
if (!bi->profile->generate_fn || if (!(bi->flags & BLK_INTEGRITY_GENERATE))
!(bi->flags & BLK_INTEGRITY_GENERATE))
return true; return true;
/* /*
...@@ -488,7 +486,7 @@ bool bio_integrity_prep(struct bio *bio) ...@@ -488,7 +486,7 @@ bool bio_integrity_prep(struct bio *bio)
bip->bip_flags |= BIP_BLOCK_INTEGRITY; bip->bip_flags |= BIP_BLOCK_INTEGRITY;
bip_set_seed(bip, bio->bi_iter.bi_sector); bip_set_seed(bip, bio->bi_iter.bi_sector);
if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM) if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
bip->bip_flags |= BIP_IP_CHECKSUM; bip->bip_flags |= BIP_IP_CHECKSUM;
/* Map it */ /* Map it */
...@@ -511,12 +509,10 @@ bool bio_integrity_prep(struct bio *bio) ...@@ -511,12 +509,10 @@ bool bio_integrity_prep(struct bio *bio)
} }
/* Auto-generate integrity metadata if this is a write */ /* Auto-generate integrity metadata if this is a write */
if (bio_data_dir(bio) == WRITE) { if (bio_data_dir(bio) == WRITE)
bio_integrity_process(bio, &bio->bi_iter, bio_integrity_process(bio, &bio->bi_iter);
bi->profile->generate_fn); else
} else {
bip->bio_iter = bio->bi_iter; bip->bio_iter = bio->bi_iter;
}
return true; return true;
err_end_io: err_end_io:
...@@ -539,15 +535,13 @@ static void bio_integrity_verify_fn(struct work_struct *work) ...@@ -539,15 +535,13 @@ static void bio_integrity_verify_fn(struct work_struct *work)
struct bio_integrity_payload *bip = struct bio_integrity_payload *bip =
container_of(work, struct bio_integrity_payload, bip_work); container_of(work, struct bio_integrity_payload, bip_work);
struct bio *bio = bip->bip_bio; 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 * At the moment verify is called bio's iterator was advanced
* during split and completion, we need to rewind iterator to * during split and completion, we need to rewind iterator to
* it's original position. * it's original position.
*/ */
bio->bi_status = bio_integrity_process(bio, &bip->bio_iter, bio->bi_status = bio_integrity_process(bio, &bip->bio_iter);
bi->profile->verify_fn);
bio_integrity_free(bio); bio_integrity_free(bio);
bio_endio(bio); bio_endio(bio);
} }
...@@ -569,7 +563,7 @@ bool __bio_integrity_endio(struct bio *bio) ...@@ -569,7 +563,7 @@ bool __bio_integrity_endio(struct bio *bio)
struct bio_integrity_payload *bip = bio_integrity(bio); struct bio_integrity_payload *bip = bio_integrity(bio);
if (bio_op(bio) == REQ_OP_READ && !bio->bi_status && if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
(bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->profile->verify_fn) { (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->csum_type) {
INIT_WORK(&bip->bip_work, bio_integrity_verify_fn); INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
queue_work(kintegrityd_wq, &bip->bip_work); queue_work(kintegrityd_wq, &bip->bip_work);
return false; return false;
......
...@@ -123,10 +123,10 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) ...@@ -123,10 +123,10 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
struct blk_integrity *b1 = &gd1->queue->integrity; struct blk_integrity *b1 = &gd1->queue->integrity;
struct blk_integrity *b2 = &gd2->queue->integrity; struct blk_integrity *b2 = &gd2->queue->integrity;
if (!b1->profile && !b2->profile) if (!b1->tuple_size && !b2->tuple_size)
return 0; return 0;
if (!b1->profile || !b2->profile) if (!b1->tuple_size || !b2->tuple_size)
return -1; return -1;
if (b1->interval_exp != b2->interval_exp) { if (b1->interval_exp != b2->interval_exp) {
...@@ -150,10 +150,13 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2) ...@@ -150,10 +150,13 @@ int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
return -1; return -1;
} }
if (b1->profile != b2->profile) { if (b1->csum_type != b2->csum_type ||
(b1->flags & BLK_INTEGRITY_REF_TAG) !=
(b2->flags & BLK_INTEGRITY_REF_TAG)) {
pr_err("%s: %s/%s type %s != %s\n", __func__, pr_err("%s: %s/%s type %s != %s\n", __func__,
gd1->disk_name, gd2->disk_name, gd1->disk_name, gd2->disk_name,
b1->profile->name, b2->profile->name); blk_integrity_profile_name(b1),
blk_integrity_profile_name(b2));
return -1; return -1;
} }
...@@ -217,14 +220,37 @@ static inline struct blk_integrity *dev_to_bi(struct device *dev) ...@@ -217,14 +220,37 @@ static inline struct blk_integrity *dev_to_bi(struct device *dev)
return &dev_to_disk(dev)->queue->integrity; return &dev_to_disk(dev)->queue->integrity;
} }
const char *blk_integrity_profile_name(struct blk_integrity *bi)
{
switch (bi->csum_type) {
case BLK_INTEGRITY_CSUM_IP:
if (bi->flags & BLK_INTEGRITY_REF_TAG)
return "T10-DIF-TYPE1-IP";
return "T10-DIF-TYPE3-IP";
case BLK_INTEGRITY_CSUM_CRC:
if (bi->flags & BLK_INTEGRITY_REF_TAG)
return "T10-DIF-TYPE1-CRC";
return "T10-DIF-TYPE3-CRC";
case BLK_INTEGRITY_CSUM_CRC64:
if (bi->flags & BLK_INTEGRITY_REF_TAG)
return "EXT-DIF-TYPE1-CRC64";
return "EXT-DIF-TYPE3-CRC64";
case BLK_INTEGRITY_CSUM_NONE:
break;
}
return "nop";
}
EXPORT_SYMBOL_GPL(blk_integrity_profile_name);
static ssize_t format_show(struct device *dev, struct device_attribute *attr, static ssize_t format_show(struct device *dev, struct device_attribute *attr,
char *page) char *page)
{ {
struct blk_integrity *bi = dev_to_bi(dev); struct blk_integrity *bi = dev_to_bi(dev);
if (bi->profile && bi->profile->name) if (!bi->tuple_size)
return sysfs_emit(page, "%s\n", bi->profile->name);
return sysfs_emit(page, "none\n"); return sysfs_emit(page, "none\n");
return sysfs_emit(page, "%s\n", blk_integrity_profile_name(bi));
} }
static ssize_t tag_size_show(struct device *dev, struct device_attribute *attr, static ssize_t tag_size_show(struct device *dev, struct device_attribute *attr,
...@@ -326,28 +352,6 @@ const struct attribute_group blk_integrity_attr_group = { ...@@ -326,28 +352,6 @@ const struct attribute_group blk_integrity_attr_group = {
.attrs = integrity_attrs, .attrs = integrity_attrs,
}; };
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_integrity_register - Register a gendisk as being integrity-capable * blk_integrity_register - Register a gendisk as being integrity-capable
* @disk: struct gendisk pointer to make integrity-aware * @disk: struct gendisk pointer to make integrity-aware
...@@ -363,11 +367,11 @@ void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template ...@@ -363,11 +367,11 @@ void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template
{ {
struct blk_integrity *bi = &disk->queue->integrity; struct blk_integrity *bi = &disk->queue->integrity;
bi->csum_type = template->csum_type;
bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE | bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
template->flags; template->flags;
bi->interval_exp = template->interval_exp ? : bi->interval_exp = template->interval_exp ? :
ilog2(queue_logical_block_size(disk->queue)); ilog2(queue_logical_block_size(disk->queue));
bi->profile = template->profile ? template->profile : &nop_profile;
bi->tuple_size = template->tuple_size; bi->tuple_size = template->tuple_size;
bi->tag_size = template->tag_size; bi->tag_size = template->tag_size;
bi->pi_offset = template->pi_offset; bi->pi_offset = template->pi_offset;
...@@ -394,7 +398,7 @@ void blk_integrity_unregister(struct gendisk *disk) ...@@ -394,7 +398,7 @@ void blk_integrity_unregister(struct gendisk *disk)
{ {
struct blk_integrity *bi = &disk->queue->integrity; struct blk_integrity *bi = &disk->queue->integrity;
if (!bi->profile) if (!bi->tuple_size)
return; return;
/* ensure all bios are off the integrity workqueue */ /* ensure all bios are off the integrity workqueue */
......
...@@ -804,10 +804,8 @@ static void blk_complete_request(struct request *req) ...@@ -804,10 +804,8 @@ static void blk_complete_request(struct request *req)
if (!bio) if (!bio)
return; return;
#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ) if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ)
req->q->integrity.profile->complete_fn(req, total_bytes); blk_integrity_complete(req, total_bytes);
#endif
/* /*
* Upper layers may call blk_crypto_evict_key() anytime after the last * Upper layers may call blk_crypto_evict_key() anytime after the last
...@@ -875,11 +873,9 @@ bool blk_update_request(struct request *req, blk_status_t error, ...@@ -875,11 +873,9 @@ bool blk_update_request(struct request *req, blk_status_t error,
if (!req->bio) if (!req->bio)
return false; return false;
#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ && if (blk_integrity_rq(req) && req_op(req) == REQ_OP_READ &&
error == BLK_STS_OK) error == BLK_STS_OK)
req->q->integrity.profile->complete_fn(req, nr_bytes); blk_integrity_complete(req, nr_bytes);
#endif
/* /*
* Upper layers may call blk_crypto_evict_key() anytime after the last * Upper layers may call blk_crypto_evict_key() anytime after the last
...@@ -1264,10 +1260,9 @@ void blk_mq_start_request(struct request *rq) ...@@ -1264,10 +1260,9 @@ void blk_mq_start_request(struct request *rq)
WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT); WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT);
rq->mq_hctx->tags->rqs[rq->tag] = rq; rq->mq_hctx->tags->rqs[rq->tag] = rq;
#ifdef CONFIG_BLK_DEV_INTEGRITY
if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE) if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE)
q->integrity.profile->prepare_fn(rq); blk_integrity_prepare(rq);
#endif
if (rq->bio && rq->bio->bi_opf & REQ_POLLED) if (rq->bio && rq->bio->bi_opf & REQ_POLLED)
WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num); WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num);
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <xen/xen.h> #include <xen/xen.h>
#include "blk-crypto-internal.h" #include "blk-crypto-internal.h"
struct blk_integrity_iter;
struct elevator_type; struct elevator_type;
/* Max future timer expiry for timeouts */ /* Max future timer expiry for timeouts */
...@@ -673,4 +674,11 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder, ...@@ -673,4 +674,11 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
const struct blk_holder_ops *hops, struct file *bdev_file); const struct blk_holder_ops *hops, struct file *bdev_file);
int bdev_permission(dev_t dev, blk_mode_t mode, void *holder); int bdev_permission(dev_t dev, blk_mode_t mode, void *holder);
void blk_integrity_generate(struct blk_integrity_iter *iter,
struct blk_integrity *bi);
blk_status_t blk_integrity_verify(struct blk_integrity_iter *iter,
struct blk_integrity *bi);
void blk_integrity_prepare(struct request *rq);
void blk_integrity_complete(struct request *rq, unsigned int nr_bytes);
#endif /* BLK_INTERNAL_H */ #endif /* BLK_INTERNAL_H */
This diff is collapsed.
...@@ -1177,7 +1177,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti) ...@@ -1177,7 +1177,7 @@ static int crypt_integrity_ctr(struct crypt_config *cc, struct dm_target *ti)
struct mapped_device *md = dm_table_get_md(ti->table); struct mapped_device *md = dm_table_get_md(ti->table);
/* We require an underlying device with non-PI metadata */ /* We require an underlying device with non-PI metadata */
if (!bi || strcmp(bi->profile->name, "nop")) { if (!bi || bi->csum_type != BLK_INTEGRITY_CSUM_NONE) {
ti->error = "Integrity profile not supported."; ti->error = "Integrity profile not supported.";
return -EINVAL; return -EINVAL;
} }
......
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
config NVME_CORE config NVME_CORE
tristate tristate
select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
config BLK_DEV_NVME config BLK_DEV_NVME
tristate "NVM Express block device" tristate "NVM Express block device"
......
...@@ -1744,17 +1744,16 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head) ...@@ -1744,17 +1744,16 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head)
case NVME_NS_DPS_PI_TYPE3: case NVME_NS_DPS_PI_TYPE3:
switch (head->guard_type) { switch (head->guard_type) {
case NVME_NVM_NS_16B_GUARD: case NVME_NVM_NS_16B_GUARD:
integrity.profile = &t10_pi_type3_crc; integrity.csum_type = BLK_INTEGRITY_CSUM_CRC;
integrity.tag_size = sizeof(u16) + sizeof(u32); integrity.tag_size = sizeof(u16) + sizeof(u32);
integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
break; break;
case NVME_NVM_NS_64B_GUARD: case NVME_NVM_NS_64B_GUARD:
integrity.profile = &ext_pi_type3_crc64; integrity.csum_type = BLK_INTEGRITY_CSUM_CRC64;
integrity.tag_size = sizeof(u16) + 6; integrity.tag_size = sizeof(u16) + 6;
integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE;
break; break;
default: default:
integrity.profile = NULL;
break; break;
} }
break; break;
...@@ -1762,22 +1761,22 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head) ...@@ -1762,22 +1761,22 @@ static bool nvme_init_integrity(struct gendisk *disk, struct nvme_ns_head *head)
case NVME_NS_DPS_PI_TYPE2: case NVME_NS_DPS_PI_TYPE2:
switch (head->guard_type) { switch (head->guard_type) {
case NVME_NVM_NS_16B_GUARD: case NVME_NVM_NS_16B_GUARD:
integrity.profile = &t10_pi_type1_crc; integrity.csum_type = BLK_INTEGRITY_CSUM_CRC;
integrity.tag_size = sizeof(u16); integrity.tag_size = sizeof(u16);
integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE |
BLK_INTEGRITY_REF_TAG;
break; break;
case NVME_NVM_NS_64B_GUARD: case NVME_NVM_NS_64B_GUARD:
integrity.profile = &ext_pi_type1_crc64; integrity.csum_type = BLK_INTEGRITY_CSUM_CRC64;
integrity.tag_size = sizeof(u16); integrity.tag_size = sizeof(u16);
integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE; integrity.flags |= BLK_INTEGRITY_DEVICE_CAPABLE |
BLK_INTEGRITY_REF_TAG;
break; break;
default: default:
integrity.profile = NULL;
break; break;
} }
break; break;
default: default:
integrity.profile = NULL;
break; break;
} }
......
...@@ -6,7 +6,6 @@ config NVME_TARGET ...@@ -6,7 +6,6 @@ config NVME_TARGET
depends on CONFIGFS_FS depends on CONFIGFS_FS
select NVME_KEYRING if NVME_TARGET_TCP_TLS select NVME_KEYRING if NVME_TARGET_TCP_TLS
select KEYS if NVME_TARGET_TCP_TLS select KEYS if NVME_TARGET_TCP_TLS
select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
select SGL_ALLOC select SGL_ALLOC
help help
This enabled target side support for the NVMe protocol, that is This enabled target side support for the NVMe protocol, that is
......
...@@ -61,14 +61,16 @@ static void nvmet_bdev_ns_enable_integrity(struct nvmet_ns *ns) ...@@ -61,14 +61,16 @@ static void nvmet_bdev_ns_enable_integrity(struct nvmet_ns *ns)
{ {
struct blk_integrity *bi = bdev_get_integrity(ns->bdev); struct blk_integrity *bi = bdev_get_integrity(ns->bdev);
if (bi) { if (!bi)
return;
if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC) {
ns->metadata_size = bi->tuple_size; ns->metadata_size = bi->tuple_size;
if (bi->profile == &t10_pi_type1_crc) if (bi->flags & BLK_INTEGRITY_REF_TAG)
ns->pi_type = NVME_NS_DPS_PI_TYPE1; ns->pi_type = NVME_NS_DPS_PI_TYPE1;
else if (bi->profile == &t10_pi_type3_crc)
ns->pi_type = NVME_NS_DPS_PI_TYPE3;
else else
/* Unsupported metadata type */ ns->pi_type = NVME_NS_DPS_PI_TYPE3;
} else {
ns->metadata_size = 0; ns->metadata_size = 0;
} }
} }
...@@ -102,7 +104,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns) ...@@ -102,7 +104,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
ns->pi_type = 0; ns->pi_type = 0;
ns->metadata_size = 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); nvmet_bdev_ns_enable_integrity(ns);
if (bdev_is_zoned(ns->bdev)) { if (bdev_is_zoned(ns->bdev)) {
......
...@@ -82,7 +82,6 @@ comment "SCSI support type (disk, tape, CD-ROM)" ...@@ -82,7 +82,6 @@ comment "SCSI support type (disk, tape, CD-ROM)"
config BLK_DEV_SD config BLK_DEV_SD
tristate "SCSI disk support" tristate "SCSI disk support"
depends on SCSI depends on SCSI
select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
help help
If you want to use SCSI hard disks, Fibre Channel disks, If you want to use SCSI hard disks, Fibre Channel disks,
Serial ATA (SATA) or Parallel ATA (PATA) hard disks, Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
......
...@@ -47,18 +47,13 @@ void sd_dif_config_host(struct scsi_disk *sdkp) ...@@ -47,18 +47,13 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
/* Enable DMA of protection information */ /* Enable DMA of protection information */
if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP) { if (scsi_host_get_guard(sdkp->device->host) & SHOST_DIX_GUARD_IP)
if (type == T10_PI_TYPE3_PROTECTION) bi.csum_type = BLK_INTEGRITY_CSUM_IP;
bi.profile = &t10_pi_type3_ip;
else else
bi.profile = &t10_pi_type1_ip; bi.csum_type = BLK_INTEGRITY_CSUM_CRC;
bi.flags |= BLK_INTEGRITY_IP_CHECKSUM; if (type != T10_PI_TYPE3_PROTECTION)
} else bi.flags |= BLK_INTEGRITY_REF_TAG;
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); bi.tuple_size = sizeof(struct t10_pi_tuple);
...@@ -76,7 +71,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp) ...@@ -76,7 +71,7 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
sd_first_printk(KERN_NOTICE, sdkp, sd_first_printk(KERN_NOTICE, sdkp,
"Enabling DIX %s, application tag size %u bytes\n", "Enabling DIX %s, application tag size %u bytes\n",
bi.profile->name, bi.tag_size); blk_integrity_profile_name(&bi), bi.tag_size);
out: out:
blk_integrity_register(disk, &bi); blk_integrity_register(disk, &bi);
} }
......
...@@ -148,24 +148,28 @@ static int iblock_configure_device(struct se_device *dev) ...@@ -148,24 +148,28 @@ static int iblock_configure_device(struct se_device *dev)
dev->dev_attrib.is_nonrot = 1; dev->dev_attrib.is_nonrot = 1;
bi = bdev_get_integrity(bd); bi = bdev_get_integrity(bd);
if (bi) { if (!bi)
struct bio_set *bs = &ib_dev->ibd_bio_set; return 0;
if (!strcmp(bi->profile->name, "T10-DIF-TYPE3-IP") || switch (bi->csum_type) {
!strcmp(bi->profile->name, "T10-DIF-TYPE1-IP")) { case BLK_INTEGRITY_CSUM_IP:
pr_err("IBLOCK export of blk_integrity: %s not" pr_err("IBLOCK export of blk_integrity: %s not supported\n",
" supported\n", bi->profile->name); blk_integrity_profile_name(bi));
ret = -ENOSYS; ret = -ENOSYS;
goto out_blkdev_put; goto out_blkdev_put;
} case BLK_INTEGRITY_CSUM_CRC:
if (bi->flags & BLK_INTEGRITY_REF_TAG)
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; dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE1_PROT;
else
dev->dev_attrib.pi_prot_type = TARGET_DIF_TYPE3_PROT;
break;
default:
break;
} }
if (dev->dev_attrib.pi_prot_type) { if (dev->dev_attrib.pi_prot_type) {
struct bio_set *bs = &ib_dev->ibd_bio_set;
if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) { if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) {
pr_err("Unable to allocate bioset for PI\n"); pr_err("Unable to allocate bioset for PI\n");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -174,9 +178,8 @@ static int iblock_configure_device(struct se_device *dev) ...@@ -174,9 +178,8 @@ static int iblock_configure_device(struct se_device *dev)
pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n", pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n",
&bs->bio_integrity_pool); &bs->bio_integrity_pool);
} }
dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type;
}
dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type;
return 0; return 0;
out_blkdev_put: out_blkdev_put:
......
...@@ -10,7 +10,7 @@ enum blk_integrity_flags { ...@@ -10,7 +10,7 @@ enum blk_integrity_flags {
BLK_INTEGRITY_VERIFY = 1 << 0, BLK_INTEGRITY_VERIFY = 1 << 0,
BLK_INTEGRITY_GENERATE = 1 << 1, BLK_INTEGRITY_GENERATE = 1 << 1,
BLK_INTEGRITY_DEVICE_CAPABLE = 1 << 2, BLK_INTEGRITY_DEVICE_CAPABLE = 1 << 2,
BLK_INTEGRITY_IP_CHECKSUM = 1 << 3, BLK_INTEGRITY_REF_TAG = 1 << 3,
}; };
struct blk_integrity_iter { struct blk_integrity_iter {
...@@ -19,22 +19,10 @@ struct blk_integrity_iter { ...@@ -19,22 +19,10 @@ struct blk_integrity_iter {
sector_t seed; sector_t seed;
unsigned int data_size; unsigned int data_size;
unsigned short interval; unsigned short interval;
unsigned char tuple_size;
unsigned char pi_offset;
const char *disk_name; const char *disk_name;
}; };
typedef blk_status_t (integrity_processing_fn) (struct blk_integrity_iter *); const char *blk_integrity_profile_name(struct blk_integrity *bi);
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;
};
#ifdef CONFIG_BLK_DEV_INTEGRITY #ifdef CONFIG_BLK_DEV_INTEGRITY
void blk_integrity_register(struct gendisk *, struct blk_integrity *); void blk_integrity_register(struct gendisk *, struct blk_integrity *);
...@@ -44,14 +32,17 @@ int blk_rq_map_integrity_sg(struct request_queue *, struct bio *, ...@@ -44,14 +32,17 @@ int blk_rq_map_integrity_sg(struct request_queue *, struct bio *,
struct scatterlist *); struct scatterlist *);
int blk_rq_count_integrity_sg(struct request_queue *, struct bio *); int blk_rq_count_integrity_sg(struct request_queue *, struct bio *);
static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) static inline bool
blk_integrity_queue_supports_integrity(struct request_queue *q)
{ {
struct blk_integrity *bi = &disk->queue->integrity; return q->integrity.tuple_size;
}
if (!bi->profile) static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk)
{
if (!blk_integrity_queue_supports_integrity(disk->queue))
return NULL; return NULL;
return &disk->queue->integrity;
return bi;
} }
static inline struct blk_integrity * static inline struct blk_integrity *
...@@ -60,12 +51,6 @@ bdev_get_integrity(struct block_device *bdev) ...@@ -60,12 +51,6 @@ bdev_get_integrity(struct block_device *bdev)
return blk_get_integrity(bdev->bd_disk); return blk_get_integrity(bdev->bd_disk);
} }
static inline bool
blk_integrity_queue_supports_integrity(struct request_queue *q)
{
return q->integrity.profile;
}
static inline unsigned short static inline unsigned short
queue_max_integrity_segments(const struct request_queue *q) queue_max_integrity_segments(const struct request_queue *q)
{ {
......
...@@ -105,9 +105,16 @@ enum { ...@@ -105,9 +105,16 @@ enum {
struct disk_events; struct disk_events;
struct badblocks; struct badblocks;
enum blk_integrity_checksum {
BLK_INTEGRITY_CSUM_NONE = 0,
BLK_INTEGRITY_CSUM_IP = 1,
BLK_INTEGRITY_CSUM_CRC = 2,
BLK_INTEGRITY_CSUM_CRC64 = 3,
} __packed ;
struct blk_integrity { struct blk_integrity {
const struct blk_integrity_profile *profile;
unsigned char flags; unsigned char flags;
enum blk_integrity_checksum csum_type;
unsigned char tuple_size; unsigned char tuple_size;
unsigned char pi_offset; unsigned char pi_offset;
unsigned char interval_exp; unsigned char interval_exp;
......
...@@ -48,11 +48,6 @@ static inline u32 t10_pi_ref_tag(struct request *rq) ...@@ -48,11 +48,6 @@ static inline u32 t10_pi_ref_tag(struct request *rq)
return blk_rq_pos(rq) >> (shift - SECTOR_SHIFT) & 0xffffffff; 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 { struct crc64_pi_tuple {
__be64 guard_tag; __be64 guard_tag;
__be16 app_tag; __be16 app_tag;
...@@ -79,7 +74,4 @@ static inline u64 ext_pi_ref_tag(struct request *rq) ...@@ -79,7 +74,4 @@ static inline u64 ext_pi_ref_tag(struct request *rq)
return lower_48_bits(blk_rq_pos(rq) >> (shift - SECTOR_SHIFT)); 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;
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment