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: Christoph Hellwig <hch@lst.de>
Reviewed-by: Kanchan Joshi <joshi.k@samsung.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20240613084839.1044015-6-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Christoph Hellwig 2024-06-13 10:48:15 +02:00 committed by Jens Axboe
parent 63e649594a
commit e9f5f44ad3
18 changed files with 216 additions and 315 deletions

View File

@ -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
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

View File

@ -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

View File

@ -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,
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)
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)
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)
} }
/* 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)
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)
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;

View File

@ -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)
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)
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 = {
.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
{ {
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)
{ {
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 */

View File

@ -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,
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)
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);
} }

View File

@ -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,
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 */

View File

@ -11,17 +11,14 @@
#include <linux/module.h> #include <linux/module.h>
#include <net/checksum.h> #include <net/checksum.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "blk.h"
typedef __be16 (csum_fn) (__be16, void *, unsigned int); static __be16 t10_pi_csum(__be16 csum, void *data, unsigned int len,
unsigned char csum_type)
static __be16 t10_pi_crc_fn(__be16 crc, void *data, unsigned int len)
{ {
return cpu_to_be16(crc_t10dif_update(be16_to_cpu(crc), data, len)); if (csum_type == BLK_INTEGRITY_CSUM_IP)
} return (__force __be16)ip_compute_csum(data, len);
return cpu_to_be16(crc_t10dif_update(be16_to_cpu(csum), data, len));
static __be16 t10_pi_ip_fn(__be16 csum, void *data, unsigned int len)
{
return (__force __be16)ip_compute_csum(data, len);
} }
/* /*
@ -29,48 +26,44 @@ static __be16 t10_pi_ip_fn(__be16 csum, void *data, unsigned int len)
* 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref * 16 bit app tag, 32 bit reference tag. Type 3 does not define the ref
* tag. * tag.
*/ */
static blk_status_t t10_pi_generate(struct blk_integrity_iter *iter, static void t10_pi_generate(struct blk_integrity_iter *iter,
csum_fn *fn, enum t10_dif_type type) struct blk_integrity *bi)
{ {
u8 offset = iter->pi_offset; u8 offset = bi->pi_offset;
unsigned int i; unsigned int i;
for (i = 0 ; i < iter->data_size ; i += iter->interval) { for (i = 0 ; i < iter->data_size ; i += iter->interval) {
struct t10_pi_tuple *pi = iter->prot_buf + offset; struct t10_pi_tuple *pi = iter->prot_buf + offset;
pi->guard_tag = fn(0, iter->data_buf, iter->interval); pi->guard_tag = t10_pi_csum(0, iter->data_buf, iter->interval,
bi->csum_type);
if (offset) if (offset)
pi->guard_tag = fn(pi->guard_tag, iter->prot_buf, pi->guard_tag = t10_pi_csum(pi->guard_tag,
offset); iter->prot_buf, offset, bi->csum_type);
pi->app_tag = 0; pi->app_tag = 0;
if (type == T10_PI_TYPE1_PROTECTION) if (bi->flags & BLK_INTEGRITY_REF_TAG)
pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed)); pi->ref_tag = cpu_to_be32(lower_32_bits(iter->seed));
else else
pi->ref_tag = 0; pi->ref_tag = 0;
iter->data_buf += iter->interval; iter->data_buf += iter->interval;
iter->prot_buf += iter->tuple_size; iter->prot_buf += bi->tuple_size;
iter->seed++; iter->seed++;
} }
return BLK_STS_OK;
} }
static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter, static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
csum_fn *fn, enum t10_dif_type type) struct blk_integrity *bi)
{ {
u8 offset = iter->pi_offset; u8 offset = bi->pi_offset;
unsigned int i; unsigned int i;
BUG_ON(type == T10_PI_TYPE0_PROTECTION);
for (i = 0 ; i < iter->data_size ; i += iter->interval) { for (i = 0 ; i < iter->data_size ; i += iter->interval) {
struct t10_pi_tuple *pi = iter->prot_buf + offset; struct t10_pi_tuple *pi = iter->prot_buf + offset;
__be16 csum; __be16 csum;
if (type == T10_PI_TYPE1_PROTECTION || if (bi->flags & BLK_INTEGRITY_REF_TAG) {
type == T10_PI_TYPE2_PROTECTION) {
if (pi->app_tag == T10_PI_APP_ESCAPE) if (pi->app_tag == T10_PI_APP_ESCAPE)
goto next; goto next;
@ -82,15 +75,17 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
iter->seed, be32_to_cpu(pi->ref_tag)); iter->seed, be32_to_cpu(pi->ref_tag));
return BLK_STS_PROTECTION; return BLK_STS_PROTECTION;
} }
} else if (type == T10_PI_TYPE3_PROTECTION) { } else {
if (pi->app_tag == T10_PI_APP_ESCAPE && if (pi->app_tag == T10_PI_APP_ESCAPE &&
pi->ref_tag == T10_PI_REF_ESCAPE) pi->ref_tag == T10_PI_REF_ESCAPE)
goto next; goto next;
} }
csum = fn(0, iter->data_buf, iter->interval); csum = t10_pi_csum(0, iter->data_buf, iter->interval,
bi->csum_type);
if (offset) if (offset)
csum = fn(csum, iter->prot_buf, offset); csum = t10_pi_csum(csum, iter->prot_buf, offset,
bi->csum_type);
if (pi->guard_tag != csum) { if (pi->guard_tag != csum) {
pr_err("%s: guard tag error at sector %llu " \ pr_err("%s: guard tag error at sector %llu " \
@ -102,33 +97,13 @@ static blk_status_t t10_pi_verify(struct blk_integrity_iter *iter,
next: next:
iter->data_buf += iter->interval; iter->data_buf += iter->interval;
iter->prot_buf += iter->tuple_size; iter->prot_buf += bi->tuple_size;
iter->seed++; iter->seed++;
} }
return BLK_STS_OK; 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);
}
static blk_status_t t10_pi_type1_generate_ip(struct blk_integrity_iter *iter)
{
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);
}
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);
}
/** /**
* t10_pi_type1_prepare - prepare PI prior submitting request to device * t10_pi_type1_prepare - prepare PI prior submitting request to device
* @rq: request with PI that should be prepared * @rq: request with PI that should be prepared
@ -225,81 +200,15 @@ 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);
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 = {
.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 = {
.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(u64 crc, void *data, unsigned int len) static __be64 ext_pi_crc64(u64 crc, void *data, unsigned int len)
{ {
return cpu_to_be64(crc64_rocksoft_update(crc, data, len)); return cpu_to_be64(crc64_rocksoft_update(crc, data, len));
} }
static blk_status_t ext_pi_crc64_generate(struct blk_integrity_iter *iter, static void ext_pi_crc64_generate(struct blk_integrity_iter *iter,
enum t10_dif_type type) struct blk_integrity *bi)
{ {
u8 offset = iter->pi_offset; u8 offset = bi->pi_offset;
unsigned int i; unsigned int i;
for (i = 0 ; i < iter->data_size ; i += iter->interval) { for (i = 0 ; i < iter->data_size ; i += iter->interval) {
@ -311,17 +220,15 @@ static blk_status_t ext_pi_crc64_generate(struct blk_integrity_iter *iter,
iter->prot_buf, offset); iter->prot_buf, offset);
pi->app_tag = 0; pi->app_tag = 0;
if (type == T10_PI_TYPE1_PROTECTION) if (bi->flags & BLK_INTEGRITY_REF_TAG)
put_unaligned_be48(iter->seed, pi->ref_tag); put_unaligned_be48(iter->seed, pi->ref_tag);
else else
put_unaligned_be48(0ULL, pi->ref_tag); put_unaligned_be48(0ULL, pi->ref_tag);
iter->data_buf += iter->interval; iter->data_buf += iter->interval;
iter->prot_buf += iter->tuple_size; iter->prot_buf += bi->tuple_size;
iter->seed++; iter->seed++;
} }
return BLK_STS_OK;
} }
static bool ext_pi_ref_escape(u8 *ref_tag) static bool ext_pi_ref_escape(u8 *ref_tag)
@ -332,9 +239,9 @@ static bool ext_pi_ref_escape(u8 *ref_tag)
} }
static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter, static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
enum t10_dif_type type) struct blk_integrity *bi)
{ {
u8 offset = iter->pi_offset; u8 offset = bi->pi_offset;
unsigned int i; unsigned int i;
for (i = 0; i < iter->data_size; i += iter->interval) { for (i = 0; i < iter->data_size; i += iter->interval) {
@ -342,7 +249,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
u64 ref, seed; u64 ref, seed;
__be64 csum; __be64 csum;
if (type == T10_PI_TYPE1_PROTECTION) { if (bi->flags & BLK_INTEGRITY_REF_TAG) {
if (pi->app_tag == T10_PI_APP_ESCAPE) if (pi->app_tag == T10_PI_APP_ESCAPE)
goto next; goto next;
@ -353,7 +260,7 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
iter->disk_name, seed, ref); iter->disk_name, seed, ref);
return BLK_STS_PROTECTION; return BLK_STS_PROTECTION;
} }
} else if (type == T10_PI_TYPE3_PROTECTION) { } else {
if (pi->app_tag == T10_PI_APP_ESCAPE && if (pi->app_tag == T10_PI_APP_ESCAPE &&
ext_pi_ref_escape(pi->ref_tag)) ext_pi_ref_escape(pi->ref_tag))
goto next; goto next;
@ -374,23 +281,13 @@ static blk_status_t ext_pi_crc64_verify(struct blk_integrity_iter *iter,
next: next:
iter->data_buf += iter->interval; iter->data_buf += iter->interval;
iter->prot_buf += iter->tuple_size; iter->prot_buf += bi->tuple_size;
iter->seed++; iter->seed++;
} }
return BLK_STS_OK; return BLK_STS_OK;
} }
static blk_status_t ext_pi_type1_verify_crc64(struct blk_integrity_iter *iter)
{
return ext_pi_crc64_verify(iter, T10_PI_TYPE1_PROTECTION);
}
static blk_status_t ext_pi_type1_generate_crc64(struct blk_integrity_iter *iter)
{
return ext_pi_crc64_generate(iter, T10_PI_TYPE1_PROTECTION);
}
static void ext_pi_type1_prepare(struct request *rq) static void ext_pi_type1_prepare(struct request *rq)
{ {
struct blk_integrity *bi = &rq->q->integrity; struct blk_integrity *bi = &rq->q->integrity;
@ -467,33 +364,61 @@ static void ext_pi_type1_complete(struct request *rq, unsigned int nr_bytes)
} }
} }
static blk_status_t ext_pi_type3_verify_crc64(struct blk_integrity_iter *iter) void blk_integrity_generate(struct blk_integrity_iter *iter,
struct blk_integrity *bi)
{ {
return ext_pi_crc64_verify(iter, T10_PI_TYPE3_PROTECTION); switch (bi->csum_type) {
case BLK_INTEGRITY_CSUM_CRC64:
ext_pi_crc64_generate(iter, bi);
break;
case BLK_INTEGRITY_CSUM_CRC:
case BLK_INTEGRITY_CSUM_IP:
t10_pi_generate(iter, bi);
break;
default:
break;
}
} }
static blk_status_t ext_pi_type3_generate_crc64(struct blk_integrity_iter *iter) blk_status_t blk_integrity_verify(struct blk_integrity_iter *iter,
struct blk_integrity *bi)
{ {
return ext_pi_crc64_generate(iter, T10_PI_TYPE3_PROTECTION); switch (bi->csum_type) {
case BLK_INTEGRITY_CSUM_CRC64:
return ext_pi_crc64_verify(iter, bi);
case BLK_INTEGRITY_CSUM_CRC:
case BLK_INTEGRITY_CSUM_IP:
return t10_pi_verify(iter, bi);
default:
return BLK_STS_OK;
}
} }
const struct blk_integrity_profile ext_pi_type1_crc64 = { void blk_integrity_prepare(struct request *rq)
.name = "EXT-DIF-TYPE1-CRC64", {
.generate_fn = ext_pi_type1_generate_crc64, struct blk_integrity *bi = &rq->q->integrity;
.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 = { if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
.name = "EXT-DIF-TYPE3-CRC64", return;
.generate_fn = ext_pi_type3_generate_crc64,
.verify_fn = ext_pi_type3_verify_crc64, if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC64)
.prepare_fn = t10_pi_type3_prepare, ext_pi_type1_prepare(rq);
.complete_fn = t10_pi_type3_complete, else
}; t10_pi_type1_prepare(rq);
EXPORT_SYMBOL_GPL(ext_pi_type3_crc64); }
void blk_integrity_complete(struct request *rq, unsigned int nr_bytes)
{
struct blk_integrity *bi = &rq->q->integrity;
if (!(bi->flags & BLK_INTEGRITY_REF_TAG))
return;
if (bi->csum_type == BLK_INTEGRITY_CSUM_CRC64)
ext_pi_type1_complete(rq, nr_bytes);
else
t10_pi_type1_complete(rq, nr_bytes);
}
MODULE_DESCRIPTION("T10 Protection Information module"); MODULE_DESCRIPTION("T10 Protection Information module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -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;
} }

View File

@ -1,7 +1,6 @@
# 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"

View File

@ -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)
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;
} }

View File

@ -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

View File

@ -61,15 +61,17 @@ 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;
ns->metadata_size = 0; } else {
ns->metadata_size = 0;
} }
} }
@ -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)) {

View File

@ -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,

View File

@ -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.csum_type = BLK_INTEGRITY_CSUM_CRC;
bi.profile = &t10_pi_type1_ip;
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)
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);
} }

View File

@ -148,35 +148,38 @@ 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;
if (dev->dev_attrib.pi_prot_type) { break;
if (bioset_integrity_create(bs, IBLOCK_BIO_POOL_SIZE) < 0) { default:
pr_err("Unable to allocate bioset for PI\n"); break;
ret = -ENOMEM;
goto out_blkdev_put;
}
pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n",
&bs->bio_integrity_pool);
}
dev->dev_attrib.hw_pi_prot_type = 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) {
pr_err("Unable to allocate bioset for PI\n");
ret = -ENOMEM;
goto out_blkdev_put;
}
pr_debug("IBLOCK setup BIP bs->bio_integrity_pool: %p\n",
&bs->bio_integrity_pool);
}
dev->dev_attrib.hw_pi_prot_type = dev->dev_attrib.pi_prot_type;
return 0; return 0;
out_blkdev_put: out_blkdev_put:

View File

@ -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 {
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 *,
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 bool
blk_integrity_queue_supports_integrity(struct request_queue *q)
{
return q->integrity.tuple_size;
}
static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk) static inline struct blk_integrity *blk_get_integrity(struct gendisk *disk)
{ {
struct blk_integrity *bi = &disk->queue->integrity; if (!blk_integrity_queue_supports_integrity(disk->queue))
if (!bi->profile)
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)
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)
{ {

View File

@ -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;

View File

@ -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)
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