]> www.infradead.org Git - users/hch/misc.git/commitdiff
block: support integrity generation and verification from file systems
authorChristoph Hellwig <hch@lst.de>
Sat, 1 Feb 2025 04:42:43 +0000 (05:42 +0100)
committerChristoph Hellwig <hch@lst.de>
Mon, 3 Feb 2025 09:21:32 +0000 (10:21 +0100)
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
block/t10-pi.c
include/linux/bio-integrity.h

index 8f5554a6989e585866d8e749fd01a69d3c188fe2..176b04cddddaa2ecdfbee91527838d4da10eace6 100644 (file)
@@ -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);
index de172d56b1f3b5dd5ef963e2482eeae7afe45ab6..b59db61a8104e69c9265575b005baba77c85bfaa 100644 (file)
@@ -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;
index 0a25716820fe0705e93bedc5cbc47ccc598e129f..26419eb5425afcda7266e53ce4f28ea0389cd6fd 100644 (file)
@@ -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 */