xref: /linux/block/bio-integrity.c (revision 594416a72032684792bb22510c538098db10b750)
17ba1ba12SMartin K. Petersen /*
27ba1ba12SMartin K. Petersen  * bio-integrity.c - bio data integrity extensions
37ba1ba12SMartin K. Petersen  *
47878cba9SMartin K. Petersen  * Copyright (C) 2007, 2008, 2009 Oracle Corporation
57ba1ba12SMartin K. Petersen  * Written by: Martin K. Petersen <martin.petersen@oracle.com>
67ba1ba12SMartin K. Petersen  *
77ba1ba12SMartin K. Petersen  * This program is free software; you can redistribute it and/or
87ba1ba12SMartin K. Petersen  * modify it under the terms of the GNU General Public License version
97ba1ba12SMartin K. Petersen  * 2 as published by the Free Software Foundation.
107ba1ba12SMartin K. Petersen  *
117ba1ba12SMartin K. Petersen  * This program is distributed in the hope that it will be useful, but
127ba1ba12SMartin K. Petersen  * WITHOUT ANY WARRANTY; without even the implied warranty of
137ba1ba12SMartin K. Petersen  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147ba1ba12SMartin K. Petersen  * General Public License for more details.
157ba1ba12SMartin K. Petersen  *
167ba1ba12SMartin K. Petersen  * You should have received a copy of the GNU General Public License
177ba1ba12SMartin K. Petersen  * along with this program; see the file COPYING.  If not, write to
187ba1ba12SMartin K. Petersen  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
197ba1ba12SMartin K. Petersen  * USA.
207ba1ba12SMartin K. Petersen  *
217ba1ba12SMartin K. Petersen  */
227ba1ba12SMartin K. Petersen 
237ba1ba12SMartin K. Petersen #include <linux/blkdev.h>
247ba1ba12SMartin K. Petersen #include <linux/mempool.h>
25afeacc8cSPaul Gortmaker #include <linux/export.h>
267ba1ba12SMartin K. Petersen #include <linux/bio.h>
277ba1ba12SMartin K. Petersen #include <linux/workqueue.h>
285a0e3ad6STejun Heo #include <linux/slab.h>
297ba1ba12SMartin K. Petersen 
309f060e22SKent Overstreet #define BIP_INLINE_VECS	4
317878cba9SMartin K. Petersen 
329f060e22SKent Overstreet static struct kmem_cache *bip_slab;
337ba1ba12SMartin K. Petersen static struct workqueue_struct *kintegrityd_wq;
347ba1ba12SMartin K. Petersen 
357878cba9SMartin K. Petersen /**
361e2a410fSKent Overstreet  * bio_integrity_alloc - Allocate integrity payload and attach it to bio
377878cba9SMartin K. Petersen  * @bio:	bio to attach integrity metadata to
387878cba9SMartin K. Petersen  * @gfp_mask:	Memory allocation mask
397878cba9SMartin K. Petersen  * @nr_vecs:	Number of integrity metadata scatter-gather elements
407878cba9SMartin K. Petersen  *
417878cba9SMartin K. Petersen  * Description: This function prepares a bio for attaching integrity
427878cba9SMartin K. Petersen  * metadata.  nr_vecs specifies the maximum number of pages containing
437878cba9SMartin K. Petersen  * integrity metadata that can be attached.
447878cba9SMartin K. Petersen  */
451e2a410fSKent Overstreet struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
467878cba9SMartin K. Petersen 						  gfp_t gfp_mask,
471e2a410fSKent Overstreet 						  unsigned int nr_vecs)
487878cba9SMartin K. Petersen {
497878cba9SMartin K. Petersen 	struct bio_integrity_payload *bip;
501e2a410fSKent Overstreet 	struct bio_set *bs = bio->bi_pool;
519f060e22SKent Overstreet 	unsigned long idx = BIO_POOL_NONE;
529f060e22SKent Overstreet 	unsigned inline_vecs;
531e2a410fSKent Overstreet 
549f060e22SKent Overstreet 	if (!bs) {
559f060e22SKent Overstreet 		bip = kmalloc(sizeof(struct bio_integrity_payload) +
569f060e22SKent Overstreet 			      sizeof(struct bio_vec) * nr_vecs, gfp_mask);
579f060e22SKent Overstreet 		inline_vecs = nr_vecs;
589f060e22SKent Overstreet 	} else {
597878cba9SMartin K. Petersen 		bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
609f060e22SKent Overstreet 		inline_vecs = BIP_INLINE_VECS;
619f060e22SKent Overstreet 	}
627878cba9SMartin K. Petersen 
639f060e22SKent Overstreet 	if (unlikely(!bip))
647878cba9SMartin K. Petersen 		return NULL;
657878cba9SMartin K. Petersen 
667878cba9SMartin K. Petersen 	memset(bip, 0, sizeof(*bip));
677878cba9SMartin K. Petersen 
689f060e22SKent Overstreet 	if (nr_vecs > inline_vecs) {
699f060e22SKent Overstreet 		bip->bip_vec = bvec_alloc(gfp_mask, nr_vecs, &idx,
709f060e22SKent Overstreet 					  bs->bvec_integrity_pool);
719f060e22SKent Overstreet 		if (!bip->bip_vec)
729f060e22SKent Overstreet 			goto err;
73cbcd1054SGu Zheng 		bip->bip_max_vcnt = bvec_nr_vecs(idx);
749f060e22SKent Overstreet 	} else {
759f060e22SKent Overstreet 		bip->bip_vec = bip->bip_inline_vecs;
76cbcd1054SGu Zheng 		bip->bip_max_vcnt = inline_vecs;
779f060e22SKent Overstreet 	}
789f060e22SKent Overstreet 
797878cba9SMartin K. Petersen 	bip->bip_slab = idx;
807878cba9SMartin K. Petersen 	bip->bip_bio = bio;
817878cba9SMartin K. Petersen 	bio->bi_integrity = bip;
82180b2f95SMartin K. Petersen 	bio->bi_rw |= REQ_INTEGRITY;
837878cba9SMartin K. Petersen 
847878cba9SMartin K. Petersen 	return bip;
859f060e22SKent Overstreet err:
869f060e22SKent Overstreet 	mempool_free(bip, bs->bio_integrity_pool);
879f060e22SKent Overstreet 	return NULL;
887878cba9SMartin K. Petersen }
897ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_alloc);
907ba1ba12SMartin K. Petersen 
917ba1ba12SMartin K. Petersen /**
927ba1ba12SMartin K. Petersen  * bio_integrity_free - Free bio integrity payload
937ba1ba12SMartin K. Petersen  * @bio:	bio containing bip to be freed
947ba1ba12SMartin K. Petersen  *
957ba1ba12SMartin K. Petersen  * Description: Used to free the integrity portion of a bio. Usually
967ba1ba12SMartin K. Petersen  * called from bio_free().
977ba1ba12SMartin K. Petersen  */
981e2a410fSKent Overstreet void bio_integrity_free(struct bio *bio)
997ba1ba12SMartin K. Petersen {
100180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
1011e2a410fSKent Overstreet 	struct bio_set *bs = bio->bi_pool;
1021e2a410fSKent Overstreet 
103b1f01388SMartin K. Petersen 	if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
1045f9378faSMartin K. Petersen 		kfree(page_address(bip->bip_vec->bv_page) +
1055f9378faSMartin K. Petersen 		      bip->bip_vec->bv_offset);
1067ba1ba12SMartin K. Petersen 
1079f060e22SKent Overstreet 	if (bs) {
1089f060e22SKent Overstreet 		if (bip->bip_slab != BIO_POOL_NONE)
1099f060e22SKent Overstreet 			bvec_free(bs->bvec_integrity_pool, bip->bip_vec,
1109f060e22SKent Overstreet 				  bip->bip_slab);
1119f060e22SKent Overstreet 
1127878cba9SMartin K. Petersen 		mempool_free(bip, bs->bio_integrity_pool);
1139f060e22SKent Overstreet 	} else {
1149f060e22SKent Overstreet 		kfree(bip);
1159f060e22SKent Overstreet 	}
1167ba1ba12SMartin K. Petersen 
1177ba1ba12SMartin K. Petersen 	bio->bi_integrity = NULL;
1187ba1ba12SMartin K. Petersen }
1197ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_free);
1207ba1ba12SMartin K. Petersen 
1217ba1ba12SMartin K. Petersen /**
1227ba1ba12SMartin K. Petersen  * bio_integrity_add_page - Attach integrity metadata
1237ba1ba12SMartin K. Petersen  * @bio:	bio to update
1247ba1ba12SMartin K. Petersen  * @page:	page containing integrity metadata
1257ba1ba12SMartin K. Petersen  * @len:	number of bytes of integrity metadata in page
1267ba1ba12SMartin K. Petersen  * @offset:	start offset within page
1277ba1ba12SMartin K. Petersen  *
1287ba1ba12SMartin K. Petersen  * Description: Attach a page containing integrity metadata to bio.
1297ba1ba12SMartin K. Petersen  */
1307ba1ba12SMartin K. Petersen int bio_integrity_add_page(struct bio *bio, struct page *page,
1317ba1ba12SMartin K. Petersen 			   unsigned int len, unsigned int offset)
1327ba1ba12SMartin K. Petersen {
133180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
1347ba1ba12SMartin K. Petersen 	struct bio_vec *iv;
1357ba1ba12SMartin K. Petersen 
136cbcd1054SGu Zheng 	if (bip->bip_vcnt >= bip->bip_max_vcnt) {
1377ba1ba12SMartin K. Petersen 		printk(KERN_ERR "%s: bip_vec full\n", __func__);
1387ba1ba12SMartin K. Petersen 		return 0;
1397ba1ba12SMartin K. Petersen 	}
1407ba1ba12SMartin K. Petersen 
141d57a5f7cSKent Overstreet 	iv = bip->bip_vec + bip->bip_vcnt;
1427ba1ba12SMartin K. Petersen 
1437ba1ba12SMartin K. Petersen 	iv->bv_page = page;
1447ba1ba12SMartin K. Petersen 	iv->bv_len = len;
1457ba1ba12SMartin K. Petersen 	iv->bv_offset = offset;
1467ba1ba12SMartin K. Petersen 	bip->bip_vcnt++;
1477ba1ba12SMartin K. Petersen 
1487ba1ba12SMartin K. Petersen 	return len;
1497ba1ba12SMartin K. Petersen }
1507ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_add_page);
1517ba1ba12SMartin K. Petersen 
1527ba1ba12SMartin K. Petersen /**
1537ba1ba12SMartin K. Petersen  * bio_integrity_enabled - Check whether integrity can be passed
1547ba1ba12SMartin K. Petersen  * @bio:	bio to check
1557ba1ba12SMartin K. Petersen  *
1567ba1ba12SMartin K. Petersen  * Description: Determines whether bio_integrity_prep() can be called
1577ba1ba12SMartin K. Petersen  * on this bio or not.	bio data direction and target device must be
1587ba1ba12SMartin K. Petersen  * set prior to calling.  The functions honors the write_generate and
1597ba1ba12SMartin K. Petersen  * read_verify flags in sysfs.
1607ba1ba12SMartin K. Petersen  */
161e7258c1aSMartin K. Petersen bool bio_integrity_enabled(struct bio *bio)
1627ba1ba12SMartin K. Petersen {
163e7258c1aSMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
164e7258c1aSMartin K. Petersen 
165e69f18f0SMartin K. Petersen 	if (!bio_is_rw(bio))
166e7258c1aSMartin K. Petersen 		return false;
167e69f18f0SMartin K. Petersen 
1687ba1ba12SMartin K. Petersen 	/* Already protected? */
1697ba1ba12SMartin K. Petersen 	if (bio_integrity(bio))
170e7258c1aSMartin K. Petersen 		return false;
1717ba1ba12SMartin K. Petersen 
172e7258c1aSMartin K. Petersen 	if (bi == NULL)
173e7258c1aSMartin K. Petersen 		return false;
174e7258c1aSMartin K. Petersen 
175e7258c1aSMartin K. Petersen 	if (bio_data_dir(bio) == READ && bi->verify_fn != NULL &&
1768288f496SMartin K. Petersen 	    (bi->flags & BLK_INTEGRITY_VERIFY))
177e7258c1aSMartin K. Petersen 		return true;
178e7258c1aSMartin K. Petersen 
179e7258c1aSMartin K. Petersen 	if (bio_data_dir(bio) == WRITE && bi->generate_fn != NULL &&
1808288f496SMartin K. Petersen 	    (bi->flags & BLK_INTEGRITY_GENERATE))
181e7258c1aSMartin K. Petersen 		return true;
182e7258c1aSMartin K. Petersen 
183e7258c1aSMartin K. Petersen 	return false;
1847ba1ba12SMartin K. Petersen }
1857ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_enabled);
1867ba1ba12SMartin K. Petersen 
1877ba1ba12SMartin K. Petersen /**
1883be91c4aSMartin K. Petersen  * bio_integrity_intervals - Return number of integrity intervals for a bio
1897ba1ba12SMartin K. Petersen  * @bi:		blk_integrity profile for device
1903be91c4aSMartin K. Petersen  * @sectors:	Size of the bio in 512-byte sectors
1917ba1ba12SMartin K. Petersen  *
1927ba1ba12SMartin K. Petersen  * Description: The block layer calculates everything in 512 byte
1933be91c4aSMartin K. Petersen  * sectors but integrity metadata is done in terms of the data integrity
1943be91c4aSMartin K. Petersen  * interval size of the storage device.  Convert the block layer sectors
1953be91c4aSMartin K. Petersen  * to the appropriate number of integrity intervals.
1967ba1ba12SMartin K. Petersen  */
1973be91c4aSMartin K. Petersen static inline unsigned int bio_integrity_intervals(struct blk_integrity *bi,
198b984679eSJens Axboe 						   unsigned int sectors)
1997ba1ba12SMartin K. Petersen {
2005a2aa873SMartin K. Petersen 	return sectors >> (ilog2(bi->interval) - 9);
2017ba1ba12SMartin K. Petersen }
2027ba1ba12SMartin K. Petersen 
203d57a5f7cSKent Overstreet static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi,
204d57a5f7cSKent Overstreet 					       unsigned int sectors)
205d57a5f7cSKent Overstreet {
2063be91c4aSMartin K. Petersen 	return bio_integrity_intervals(bi, sectors) * bi->tuple_size;
207d57a5f7cSKent Overstreet }
208d57a5f7cSKent Overstreet 
2097ba1ba12SMartin K. Petersen /**
21018593088SMartin K. Petersen  * bio_integrity_process - Process integrity metadata for a bio
211bf36f9cfSGu Zheng  * @bio:	bio to generate/verify integrity metadata for
21218593088SMartin K. Petersen  * @proc_fn:	Pointer to the relevant processing function
2137ba1ba12SMartin K. Petersen  */
21418593088SMartin K. Petersen static int bio_integrity_process(struct bio *bio,
21518593088SMartin K. Petersen 				 integrity_processing_fn *proc_fn)
2167ba1ba12SMartin K. Petersen {
2177ba1ba12SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
21818593088SMartin K. Petersen 	struct blk_integrity_iter iter;
219*594416a7SDarrick J. Wong 	struct bvec_iter bviter;
220*594416a7SDarrick J. Wong 	struct bio_vec bv;
2215f9378faSMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
222*594416a7SDarrick J. Wong 	unsigned int ret = 0;
2235f9378faSMartin K. Petersen 	void *prot_buf = page_address(bip->bip_vec->bv_page) +
2245f9378faSMartin K. Petersen 		bip->bip_vec->bv_offset;
2257ba1ba12SMartin K. Petersen 
22618593088SMartin K. Petersen 	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
22718593088SMartin K. Petersen 	iter.interval = bi->interval;
22818593088SMartin K. Petersen 	iter.seed = bip_get_seed(bip);
22918593088SMartin K. Petersen 	iter.prot_buf = prot_buf;
2307ba1ba12SMartin K. Petersen 
231*594416a7SDarrick J. Wong 	bio_for_each_segment(bv, bio, bviter) {
232*594416a7SDarrick J. Wong 		void *kaddr = kmap_atomic(bv.bv_page);
2337ba1ba12SMartin K. Petersen 
234*594416a7SDarrick J. Wong 		iter.data_buf = kaddr + bv.bv_offset;
235*594416a7SDarrick J. Wong 		iter.data_size = bv.bv_len;
23618593088SMartin K. Petersen 
23718593088SMartin K. Petersen 		ret = proc_fn(&iter);
238bf36f9cfSGu Zheng 		if (ret) {
239bf36f9cfSGu Zheng 			kunmap_atomic(kaddr);
240bf36f9cfSGu Zheng 			return ret;
241bf36f9cfSGu Zheng 		}
2427ba1ba12SMartin K. Petersen 
243e8e3c3d6SCong Wang 		kunmap_atomic(kaddr);
2447ba1ba12SMartin K. Petersen 	}
245bf36f9cfSGu Zheng 	return ret;
246bf36f9cfSGu Zheng }
247bf36f9cfSGu Zheng 
248bf36f9cfSGu Zheng /**
2497ba1ba12SMartin K. Petersen  * bio_integrity_prep - Prepare bio for integrity I/O
2507ba1ba12SMartin K. Petersen  * @bio:	bio to prepare
2517ba1ba12SMartin K. Petersen  *
2527ba1ba12SMartin K. Petersen  * Description: Allocates a buffer for integrity metadata, maps the
2537ba1ba12SMartin K. Petersen  * pages and attaches them to a bio.  The bio must have data
2547ba1ba12SMartin K. Petersen  * direction, target device and start sector set priot to calling.  In
2557ba1ba12SMartin K. Petersen  * the WRITE case, integrity metadata will be generated using the
2567ba1ba12SMartin K. Petersen  * block device's integrity function.  In the READ case, the buffer
2577ba1ba12SMartin K. Petersen  * will be prepared for DMA and a suitable end_io handler set up.
2587ba1ba12SMartin K. Petersen  */
2597ba1ba12SMartin K. Petersen int bio_integrity_prep(struct bio *bio)
2607ba1ba12SMartin K. Petersen {
2617ba1ba12SMartin K. Petersen 	struct bio_integrity_payload *bip;
2627ba1ba12SMartin K. Petersen 	struct blk_integrity *bi;
2637ba1ba12SMartin K. Petersen 	struct request_queue *q;
2647ba1ba12SMartin K. Petersen 	void *buf;
2657ba1ba12SMartin K. Petersen 	unsigned long start, end;
2667ba1ba12SMartin K. Petersen 	unsigned int len, nr_pages;
2677ba1ba12SMartin K. Petersen 	unsigned int bytes, offset, i;
2683be91c4aSMartin K. Petersen 	unsigned int intervals;
2697ba1ba12SMartin K. Petersen 
2707ba1ba12SMartin K. Petersen 	bi = bdev_get_integrity(bio->bi_bdev);
2717ba1ba12SMartin K. Petersen 	q = bdev_get_queue(bio->bi_bdev);
2727ba1ba12SMartin K. Petersen 	BUG_ON(bi == NULL);
2737ba1ba12SMartin K. Petersen 	BUG_ON(bio_integrity(bio));
2747ba1ba12SMartin K. Petersen 
2753be91c4aSMartin K. Petersen 	intervals = bio_integrity_intervals(bi, bio_sectors(bio));
2767ba1ba12SMartin K. Petersen 
2777ba1ba12SMartin K. Petersen 	/* Allocate kernel buffer for protection data */
2783be91c4aSMartin K. Petersen 	len = intervals * bi->tuple_size;
27972f46503SDavid Rientjes 	buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
2807ba1ba12SMartin K. Petersen 	if (unlikely(buf == NULL)) {
2817ba1ba12SMartin K. Petersen 		printk(KERN_ERR "could not allocate integrity buffer\n");
282220eb7fdSAndrew Morton 		return -ENOMEM;
2837ba1ba12SMartin K. Petersen 	}
2847ba1ba12SMartin K. Petersen 
2857ba1ba12SMartin K. Petersen 	end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
2867ba1ba12SMartin K. Petersen 	start = ((unsigned long) buf) >> PAGE_SHIFT;
2877ba1ba12SMartin K. Petersen 	nr_pages = end - start;
2887ba1ba12SMartin K. Petersen 
2897ba1ba12SMartin K. Petersen 	/* Allocate bio integrity payload and integrity vectors */
2907ba1ba12SMartin K. Petersen 	bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
2917ba1ba12SMartin K. Petersen 	if (unlikely(bip == NULL)) {
2927ba1ba12SMartin K. Petersen 		printk(KERN_ERR "could not allocate data integrity bioset\n");
2937ba1ba12SMartin K. Petersen 		kfree(buf);
2947ba1ba12SMartin K. Petersen 		return -EIO;
2957ba1ba12SMartin K. Petersen 	}
2967ba1ba12SMartin K. Petersen 
297b1f01388SMartin K. Petersen 	bip->bip_flags |= BIP_BLOCK_INTEGRITY;
298d57a5f7cSKent Overstreet 	bip->bip_iter.bi_size = len;
29918593088SMartin K. Petersen 	bip_set_seed(bip, bio->bi_iter.bi_sector);
3007ba1ba12SMartin K. Petersen 
301aae7df50SMartin K. Petersen 	if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM)
302aae7df50SMartin K. Petersen 		bip->bip_flags |= BIP_IP_CHECKSUM;
303aae7df50SMartin K. Petersen 
3047ba1ba12SMartin K. Petersen 	/* Map it */
3057ba1ba12SMartin K. Petersen 	offset = offset_in_page(buf);
3067ba1ba12SMartin K. Petersen 	for (i = 0 ; i < nr_pages ; i++) {
3077ba1ba12SMartin K. Petersen 		int ret;
3087ba1ba12SMartin K. Petersen 		bytes = PAGE_SIZE - offset;
3097ba1ba12SMartin K. Petersen 
3107ba1ba12SMartin K. Petersen 		if (len <= 0)
3117ba1ba12SMartin K. Petersen 			break;
3127ba1ba12SMartin K. Petersen 
3137ba1ba12SMartin K. Petersen 		if (bytes > len)
3147ba1ba12SMartin K. Petersen 			bytes = len;
3157ba1ba12SMartin K. Petersen 
3167ba1ba12SMartin K. Petersen 		ret = bio_integrity_add_page(bio, virt_to_page(buf),
3177ba1ba12SMartin K. Petersen 					     bytes, offset);
3187ba1ba12SMartin K. Petersen 
3197ba1ba12SMartin K. Petersen 		if (ret == 0)
3207ba1ba12SMartin K. Petersen 			return 0;
3217ba1ba12SMartin K. Petersen 
3227ba1ba12SMartin K. Petersen 		if (ret < bytes)
3237ba1ba12SMartin K. Petersen 			break;
3247ba1ba12SMartin K. Petersen 
3257ba1ba12SMartin K. Petersen 		buf += bytes;
3267ba1ba12SMartin K. Petersen 		len -= bytes;
3277ba1ba12SMartin K. Petersen 		offset = 0;
3287ba1ba12SMartin K. Petersen 	}
3297ba1ba12SMartin K. Petersen 
3307ba1ba12SMartin K. Petersen 	/* Install custom I/O completion handler if read verify is enabled */
3317ba1ba12SMartin K. Petersen 	if (bio_data_dir(bio) == READ) {
3327ba1ba12SMartin K. Petersen 		bip->bip_end_io = bio->bi_end_io;
3337ba1ba12SMartin K. Petersen 		bio->bi_end_io = bio_integrity_endio;
3347ba1ba12SMartin K. Petersen 	}
3357ba1ba12SMartin K. Petersen 
3367ba1ba12SMartin K. Petersen 	/* Auto-generate integrity metadata if this is a write */
3377ba1ba12SMartin K. Petersen 	if (bio_data_dir(bio) == WRITE)
33818593088SMartin K. Petersen 		bio_integrity_process(bio, bi->generate_fn);
3397ba1ba12SMartin K. Petersen 
3407ba1ba12SMartin K. Petersen 	return 0;
3417ba1ba12SMartin K. Petersen }
3427ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_prep);
3437ba1ba12SMartin K. Petersen 
3447ba1ba12SMartin K. Petersen /**
3457ba1ba12SMartin K. Petersen  * bio_integrity_verify_fn - Integrity I/O completion worker
3467ba1ba12SMartin K. Petersen  * @work:	Work struct stored in bio to be verified
3477ba1ba12SMartin K. Petersen  *
3487ba1ba12SMartin K. Petersen  * Description: This workqueue function is called to complete a READ
3497ba1ba12SMartin K. Petersen  * request.  The function verifies the transferred integrity metadata
3507ba1ba12SMartin K. Petersen  * and then calls the original bio end_io function.
3517ba1ba12SMartin K. Petersen  */
3527ba1ba12SMartin K. Petersen static void bio_integrity_verify_fn(struct work_struct *work)
3537ba1ba12SMartin K. Petersen {
3547ba1ba12SMartin K. Petersen 	struct bio_integrity_payload *bip =
3557ba1ba12SMartin K. Petersen 		container_of(work, struct bio_integrity_payload, bip_work);
3567ba1ba12SMartin K. Petersen 	struct bio *bio = bip->bip_bio;
35718593088SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
3587b24fc4dSMartin K. Petersen 	int error;
3597ba1ba12SMartin K. Petersen 
36018593088SMartin K. Petersen 	error = bio_integrity_process(bio, bi->verify_fn);
3617ba1ba12SMartin K. Petersen 
3627ba1ba12SMartin K. Petersen 	/* Restore original bio completion handler */
3637ba1ba12SMartin K. Petersen 	bio->bi_end_io = bip->bip_end_io;
364196d38bcSKent Overstreet 	bio_endio_nodec(bio, error);
3657ba1ba12SMartin K. Petersen }
3667ba1ba12SMartin K. Petersen 
3677ba1ba12SMartin K. Petersen /**
3687ba1ba12SMartin K. Petersen  * bio_integrity_endio - Integrity I/O completion function
3697ba1ba12SMartin K. Petersen  * @bio:	Protected bio
3707ba1ba12SMartin K. Petersen  * @error:	Pointer to errno
3717ba1ba12SMartin K. Petersen  *
3727ba1ba12SMartin K. Petersen  * Description: Completion for integrity I/O
3737ba1ba12SMartin K. Petersen  *
3747ba1ba12SMartin K. Petersen  * Normally I/O completion is done in interrupt context.  However,
3757ba1ba12SMartin K. Petersen  * verifying I/O integrity is a time-consuming task which must be run
3767ba1ba12SMartin K. Petersen  * in process context.	This function postpones completion
3777ba1ba12SMartin K. Petersen  * accordingly.
3787ba1ba12SMartin K. Petersen  */
3797ba1ba12SMartin K. Petersen void bio_integrity_endio(struct bio *bio, int error)
3807ba1ba12SMartin K. Petersen {
381180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
3827ba1ba12SMartin K. Petersen 
3837ba1ba12SMartin K. Petersen 	BUG_ON(bip->bip_bio != bio);
3847ba1ba12SMartin K. Petersen 
3857b24fc4dSMartin K. Petersen 	/* In case of an I/O error there is no point in verifying the
3867b24fc4dSMartin K. Petersen 	 * integrity metadata.  Restore original bio end_io handler
3877b24fc4dSMartin K. Petersen 	 * and run it.
3887b24fc4dSMartin K. Petersen 	 */
3897b24fc4dSMartin K. Petersen 	if (error) {
3907b24fc4dSMartin K. Petersen 		bio->bi_end_io = bip->bip_end_io;
39116f408dcSSagi Grimberg 		bio_endio_nodec(bio, error);
3927b24fc4dSMartin K. Petersen 
3937b24fc4dSMartin K. Petersen 		return;
3947b24fc4dSMartin K. Petersen 	}
3957b24fc4dSMartin K. Petersen 
3967ba1ba12SMartin K. Petersen 	INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
3977ba1ba12SMartin K. Petersen 	queue_work(kintegrityd_wq, &bip->bip_work);
3987ba1ba12SMartin K. Petersen }
3997ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_endio);
4007ba1ba12SMartin K. Petersen 
4017ba1ba12SMartin K. Petersen /**
4027ba1ba12SMartin K. Petersen  * bio_integrity_advance - Advance integrity vector
4037ba1ba12SMartin K. Petersen  * @bio:	bio whose integrity vector to update
4047ba1ba12SMartin K. Petersen  * @bytes_done:	number of data bytes that have been completed
4057ba1ba12SMartin K. Petersen  *
4067ba1ba12SMartin K. Petersen  * Description: This function calculates how many integrity bytes the
4077ba1ba12SMartin K. Petersen  * number of completed data bytes correspond to and advances the
4087ba1ba12SMartin K. Petersen  * integrity vector accordingly.
4097ba1ba12SMartin K. Petersen  */
4107ba1ba12SMartin K. Petersen void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
4117ba1ba12SMartin K. Petersen {
412180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
4137ba1ba12SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
414d57a5f7cSKent Overstreet 	unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
4157ba1ba12SMartin K. Petersen 
416d57a5f7cSKent Overstreet 	bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
4177ba1ba12SMartin K. Petersen }
4187ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_advance);
4197ba1ba12SMartin K. Petersen 
4207ba1ba12SMartin K. Petersen /**
4217ba1ba12SMartin K. Petersen  * bio_integrity_trim - Trim integrity vector
4227ba1ba12SMartin K. Petersen  * @bio:	bio whose integrity vector to update
4237ba1ba12SMartin K. Petersen  * @offset:	offset to first data sector
4247ba1ba12SMartin K. Petersen  * @sectors:	number of data sectors
4257ba1ba12SMartin K. Petersen  *
4267ba1ba12SMartin K. Petersen  * Description: Used to trim the integrity vector in a cloned bio.
4277ba1ba12SMartin K. Petersen  * The ivec will be advanced corresponding to 'offset' data sectors
4287ba1ba12SMartin K. Petersen  * and the length will be truncated corresponding to 'len' data
4297ba1ba12SMartin K. Petersen  * sectors.
4307ba1ba12SMartin K. Petersen  */
431b984679eSJens Axboe void bio_integrity_trim(struct bio *bio, unsigned int offset,
432b984679eSJens Axboe 			unsigned int sectors)
4337ba1ba12SMartin K. Petersen {
434180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
4357ba1ba12SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
4367ba1ba12SMartin K. Petersen 
437d57a5f7cSKent Overstreet 	bio_integrity_advance(bio, offset << 9);
438d57a5f7cSKent Overstreet 	bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors);
4397ba1ba12SMartin K. Petersen }
4407ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_trim);
4417ba1ba12SMartin K. Petersen 
4427ba1ba12SMartin K. Petersen /**
4437ba1ba12SMartin K. Petersen  * bio_integrity_clone - Callback for cloning bios with integrity metadata
4447ba1ba12SMartin K. Petersen  * @bio:	New bio
4457ba1ba12SMartin K. Petersen  * @bio_src:	Original bio
44687092698Sun'ichi Nomura  * @gfp_mask:	Memory allocation mask
4477ba1ba12SMartin K. Petersen  *
4487ba1ba12SMartin K. Petersen  * Description:	Called to allocate a bip when cloning a bio
4497ba1ba12SMartin K. Petersen  */
4507878cba9SMartin K. Petersen int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
4511e2a410fSKent Overstreet 			gfp_t gfp_mask)
4527ba1ba12SMartin K. Petersen {
453180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip_src = bio_integrity(bio_src);
4547ba1ba12SMartin K. Petersen 	struct bio_integrity_payload *bip;
4557ba1ba12SMartin K. Petersen 
4567ba1ba12SMartin K. Petersen 	BUG_ON(bip_src == NULL);
4577ba1ba12SMartin K. Petersen 
4581e2a410fSKent Overstreet 	bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
4597ba1ba12SMartin K. Petersen 
4607ba1ba12SMartin K. Petersen 	if (bip == NULL)
4617ba1ba12SMartin K. Petersen 		return -EIO;
4627ba1ba12SMartin K. Petersen 
4637ba1ba12SMartin K. Petersen 	memcpy(bip->bip_vec, bip_src->bip_vec,
4647ba1ba12SMartin K. Petersen 	       bip_src->bip_vcnt * sizeof(struct bio_vec));
4657ba1ba12SMartin K. Petersen 
4667ba1ba12SMartin K. Petersen 	bip->bip_vcnt = bip_src->bip_vcnt;
467d57a5f7cSKent Overstreet 	bip->bip_iter = bip_src->bip_iter;
4687ba1ba12SMartin K. Petersen 
4697ba1ba12SMartin K. Petersen 	return 0;
4707ba1ba12SMartin K. Petersen }
4717ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_clone);
4727ba1ba12SMartin K. Petersen 
4737878cba9SMartin K. Petersen int bioset_integrity_create(struct bio_set *bs, int pool_size)
4747ba1ba12SMartin K. Petersen {
475a91a2785SMartin K. Petersen 	if (bs->bio_integrity_pool)
476a91a2785SMartin K. Petersen 		return 0;
477a91a2785SMartin K. Petersen 
4789f060e22SKent Overstreet 	bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab);
4797878cba9SMartin K. Petersen 	if (!bs->bio_integrity_pool)
4807878cba9SMartin K. Petersen 		return -1;
4816d2a78e7SMartin K. Petersen 
482a6c39cb4SFabian Frederick 	bs->bvec_integrity_pool = biovec_create_pool(pool_size);
483bc5c8f07SGu Zheng 	if (!bs->bvec_integrity_pool) {
484bc5c8f07SGu Zheng 		mempool_destroy(bs->bio_integrity_pool);
485bc5c8f07SGu Zheng 		return -1;
486bc5c8f07SGu Zheng 	}
487bc5c8f07SGu Zheng 
4887ba1ba12SMartin K. Petersen 	return 0;
4897ba1ba12SMartin K. Petersen }
4907878cba9SMartin K. Petersen EXPORT_SYMBOL(bioset_integrity_create);
4917878cba9SMartin K. Petersen 
4927878cba9SMartin K. Petersen void bioset_integrity_free(struct bio_set *bs)
4937878cba9SMartin K. Petersen {
4947878cba9SMartin K. Petersen 	if (bs->bio_integrity_pool)
4957878cba9SMartin K. Petersen 		mempool_destroy(bs->bio_integrity_pool);
4969f060e22SKent Overstreet 
4979f060e22SKent Overstreet 	if (bs->bvec_integrity_pool)
498adbe6991SBjorn Helgaas 		mempool_destroy(bs->bvec_integrity_pool);
4997878cba9SMartin K. Petersen }
5007878cba9SMartin K. Petersen EXPORT_SYMBOL(bioset_integrity_free);
5017878cba9SMartin K. Petersen 
5027878cba9SMartin K. Petersen void __init bio_integrity_init(void)
5037878cba9SMartin K. Petersen {
504a6e8dc46STejun Heo 	/*
505a6e8dc46STejun Heo 	 * kintegrityd won't block much but may burn a lot of CPU cycles.
506a6e8dc46STejun Heo 	 * Make it highpri CPU intensive wq with max concurrency of 1.
507a6e8dc46STejun Heo 	 */
508a6e8dc46STejun Heo 	kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM |
509a6e8dc46STejun Heo 					 WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
5107878cba9SMartin K. Petersen 	if (!kintegrityd_wq)
5117878cba9SMartin K. Petersen 		panic("Failed to create kintegrityd\n");
5127878cba9SMartin K. Petersen 
5139f060e22SKent Overstreet 	bip_slab = kmem_cache_create("bio_integrity_payload",
5149f060e22SKent Overstreet 				     sizeof(struct bio_integrity_payload) +
5159f060e22SKent Overstreet 				     sizeof(struct bio_vec) * BIP_INLINE_VECS,
5169f060e22SKent Overstreet 				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
5177878cba9SMartin K. Petersen }
518