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