@@ -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);
@@ -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;
@@ -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 */
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@lst.de> --- block/blk.h | 1 - block/t10-pi.c | 90 ++++++++++++++++++++++++----------- include/linux/bio-integrity.h | 12 +++++ 3 files changed, 75 insertions(+), 28 deletions(-)