Add a new blk_integrity_verify_all helper that uses the _all iterator to verify the entire bio as built by the file system and doesn't require the extra bvec_iter used by blk_integrity_verify_iter and export blk_integrity_generate which can be used as-is. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- block/blk.h | 1 - block/t10-pi.c | 90 ++++++++++++++++++++++++----------- include/linux/bio-integrity.h | 12 +++++ 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/block/blk.h b/block/blk.h index 8f5554a6989e..176b04cdddda 100644 --- a/block/blk.h +++ b/block/blk.h @@ -709,7 +709,6 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder, const struct blk_holder_ops *hops, struct file *bdev_file); int bdev_permission(dev_t dev, blk_mode_t mode, void *holder); -void blk_integrity_generate(struct bio *bio); void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter); void blk_integrity_prepare(struct request *rq); void blk_integrity_complete(struct request *rq, unsigned int nr_bytes); diff --git a/block/t10-pi.c b/block/t10-pi.c index de172d56b1f3..b59db61a8104 100644 --- a/block/t10-pi.c +++ b/block/t10-pi.c @@ -403,42 +403,51 @@ void blk_integrity_generate(struct bio *bio) kunmap_local(kaddr); } } +EXPORT_SYMBOL_GPL(blk_integrity_generate); +static blk_status_t blk_integrity_verify_bvec(struct blk_integrity *bi, + struct blk_integrity_iter *iter, struct bio_vec *bv) +{ + void *kaddr = bvec_kmap_local(bv); + blk_status_t ret = BLK_STS_OK; + + iter->data_buf = kaddr; + iter->data_size = bv->bv_len; + switch (bi->csum_type) { + case BLK_INTEGRITY_CSUM_CRC64: + ret = ext_pi_crc64_verify(iter, bi); + break; + case BLK_INTEGRITY_CSUM_CRC: + case BLK_INTEGRITY_CSUM_IP: + ret = t10_pi_verify(iter, bi); + break; + default: + break; + } + kunmap_local(kaddr); + return ret; +} + +/* + * At the moment verify is called, bi_iter could have been advanced by splits + * and completions, thus we have to use the saved copy here. + */ void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter) { struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); struct bio_integrity_payload *bip = bio_integrity(bio); - struct blk_integrity_iter iter; + struct blk_integrity_iter iter = { + .disk_name = bio->bi_bdev->bd_disk->disk_name, + .interval = 1 << bi->interval_exp, + .seed = saved_iter->bi_sector, + .prot_buf = bvec_virt(bip->bip_vec), + }; struct bvec_iter bviter; struct bio_vec bv; + blk_status_t ret; - /* - * At the moment verify is called bi_iter has been advanced during split - * and completion, so use the copy created during submission here. - */ - iter.disk_name = bio->bi_bdev->bd_disk->disk_name; - iter.interval = 1 << bi->interval_exp; - iter.seed = saved_iter->bi_sector; - iter.prot_buf = bvec_virt(bip->bip_vec); __bio_for_each_segment(bv, bio, bviter, *saved_iter) { - void *kaddr = bvec_kmap_local(&bv); - blk_status_t ret = BLK_STS_OK; - - iter.data_buf = kaddr; - iter.data_size = bv.bv_len; - switch (bi->csum_type) { - case BLK_INTEGRITY_CSUM_CRC64: - ret = ext_pi_crc64_verify(&iter, bi); - break; - case BLK_INTEGRITY_CSUM_CRC: - case BLK_INTEGRITY_CSUM_IP: - ret = t10_pi_verify(&iter, bi); - break; - default: - break; - } - kunmap_local(kaddr); - + ret = blk_integrity_verify_bvec(bi, &iter, &bv); if (ret) { bio->bi_status = ret; return; @@ -446,6 +455,33 @@ void blk_integrity_verify_iter(struct bio *bio, struct bvec_iter *saved_iter) } } +/* + * For use by the file system which owns the entire bio. + */ +int blk_integrity_verify_all(struct bio *bio, sector_t seed) +{ + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); + struct bio_integrity_payload *bip = bio_integrity(bio); + struct blk_integrity_iter iter = { + .disk_name = bio->bi_bdev->bd_disk->disk_name, + .interval = 1 << bi->interval_exp, + .seed = seed, + .prot_buf = bvec_virt(bip->bip_vec), + }; + struct bvec_iter_all bviter; + struct bio_vec *bv; + blk_status_t ret; + + bio_for_each_segment_all(bv, bio, bviter) { + ret = blk_integrity_verify_bvec(bi, &iter, bv); + if (ret) + return blk_status_to_errno(ret); + } + + return 0; +} +EXPORT_SYMBOL_GPL(blk_integrity_verify_all); + void blk_integrity_prepare(struct request *rq) { struct blk_integrity *bi = &rq->q->limits.integrity; diff --git a/include/linux/bio-integrity.h b/include/linux/bio-integrity.h index 0a25716820fe..26419eb5425a 100644 --- a/include/linux/bio-integrity.h +++ b/include/linux/bio-integrity.h @@ -81,6 +81,9 @@ void bio_integrity_advance(struct bio *bio, unsigned int bytes_done); void bio_integrity_trim(struct bio *bio); int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask); +void blk_integrity_generate(struct bio *bio); +int blk_integrity_verify_all(struct bio *bio, sector_t seed); + #else /* CONFIG_BLK_DEV_INTEGRITY */ static inline struct bio_integrity_payload *bio_integrity(struct bio *bio) @@ -138,5 +141,14 @@ static inline int bio_integrity_add_page(struct bio *bio, struct page *page, { return 0; } + +static inline void blk_integrity_generate(struct bio *bio) +{ +} + +static inline int blk_integrity_verify_all(struct bio *bio, sector_t seed) +{ + return 0; +} #endif /* CONFIG_BLK_DEV_INTEGRITY */ #endif /* _LINUX_BIO_INTEGRITY_H */ -- 2.45.2