xref: /linux/block/bio-integrity.c (revision b1f01388574c9329922f760fc2a7335c2d14b08b)
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 
103*b1f01388SMartin 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;
2190bc69973SMartin K. Petersen 	struct bio_vec *bv;
2205f9378faSMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
22118593088SMartin K. Petersen 	unsigned int i, ret = 0;
2225f9378faSMartin K. Petersen 	void *prot_buf = page_address(bip->bip_vec->bv_page) +
2235f9378faSMartin K. Petersen 		bip->bip_vec->bv_offset;
2247ba1ba12SMartin K. Petersen 
22518593088SMartin K. Petersen 	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
22618593088SMartin K. Petersen 	iter.interval = bi->interval;
22718593088SMartin K. Petersen 	iter.seed = bip_get_seed(bip);
22818593088SMartin K. Petersen 	iter.prot_buf = prot_buf;
2297ba1ba12SMartin K. Petersen 
2300bc69973SMartin K. Petersen 	bio_for_each_segment_all(bv, bio, i) {
2310bc69973SMartin K. Petersen 		void *kaddr = kmap_atomic(bv->bv_page);
2327ba1ba12SMartin K. Petersen 
23318593088SMartin K. Petersen 		iter.data_buf = kaddr + bv->bv_offset;
23418593088SMartin K. Petersen 		iter.data_size = bv->bv_len;
23518593088SMartin K. Petersen 
23618593088SMartin K. Petersen 		ret = proc_fn(&iter);
237bf36f9cfSGu Zheng 		if (ret) {
238bf36f9cfSGu Zheng 			kunmap_atomic(kaddr);
239bf36f9cfSGu Zheng 			return ret;
240bf36f9cfSGu Zheng 		}
2417ba1ba12SMartin K. Petersen 
242e8e3c3d6SCong Wang 		kunmap_atomic(kaddr);
2437ba1ba12SMartin K. Petersen 	}
244bf36f9cfSGu Zheng 	return ret;
245bf36f9cfSGu Zheng }
246bf36f9cfSGu Zheng 
247bf36f9cfSGu Zheng /**
2487ba1ba12SMartin K. Petersen  * bio_integrity_prep - Prepare bio for integrity I/O
2497ba1ba12SMartin K. Petersen  * @bio:	bio to prepare
2507ba1ba12SMartin K. Petersen  *
2517ba1ba12SMartin K. Petersen  * Description: Allocates a buffer for integrity metadata, maps the
2527ba1ba12SMartin K. Petersen  * pages and attaches them to a bio.  The bio must have data
2537ba1ba12SMartin K. Petersen  * direction, target device and start sector set priot to calling.  In
2547ba1ba12SMartin K. Petersen  * the WRITE case, integrity metadata will be generated using the
2557ba1ba12SMartin K. Petersen  * block device's integrity function.  In the READ case, the buffer
2567ba1ba12SMartin K. Petersen  * will be prepared for DMA and a suitable end_io handler set up.
2577ba1ba12SMartin K. Petersen  */
2587ba1ba12SMartin K. Petersen int bio_integrity_prep(struct bio *bio)
2597ba1ba12SMartin K. Petersen {
2607ba1ba12SMartin K. Petersen 	struct bio_integrity_payload *bip;
2617ba1ba12SMartin K. Petersen 	struct blk_integrity *bi;
2627ba1ba12SMartin K. Petersen 	struct request_queue *q;
2637ba1ba12SMartin K. Petersen 	void *buf;
2647ba1ba12SMartin K. Petersen 	unsigned long start, end;
2657ba1ba12SMartin K. Petersen 	unsigned int len, nr_pages;
2667ba1ba12SMartin K. Petersen 	unsigned int bytes, offset, i;
2673be91c4aSMartin K. Petersen 	unsigned int intervals;
2687ba1ba12SMartin K. Petersen 
2697ba1ba12SMartin K. Petersen 	bi = bdev_get_integrity(bio->bi_bdev);
2707ba1ba12SMartin K. Petersen 	q = bdev_get_queue(bio->bi_bdev);
2717ba1ba12SMartin K. Petersen 	BUG_ON(bi == NULL);
2727ba1ba12SMartin K. Petersen 	BUG_ON(bio_integrity(bio));
2737ba1ba12SMartin K. Petersen 
2743be91c4aSMartin K. Petersen 	intervals = bio_integrity_intervals(bi, bio_sectors(bio));
2757ba1ba12SMartin K. Petersen 
2767ba1ba12SMartin K. Petersen 	/* Allocate kernel buffer for protection data */
2773be91c4aSMartin K. Petersen 	len = intervals * bi->tuple_size;
27872f46503SDavid Rientjes 	buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
2797ba1ba12SMartin K. Petersen 	if (unlikely(buf == NULL)) {
2807ba1ba12SMartin K. Petersen 		printk(KERN_ERR "could not allocate integrity buffer\n");
281220eb7fdSAndrew Morton 		return -ENOMEM;
2827ba1ba12SMartin K. Petersen 	}
2837ba1ba12SMartin K. Petersen 
2847ba1ba12SMartin K. Petersen 	end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
2857ba1ba12SMartin K. Petersen 	start = ((unsigned long) buf) >> PAGE_SHIFT;
2867ba1ba12SMartin K. Petersen 	nr_pages = end - start;
2877ba1ba12SMartin K. Petersen 
2887ba1ba12SMartin K. Petersen 	/* Allocate bio integrity payload and integrity vectors */
2897ba1ba12SMartin K. Petersen 	bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
2907ba1ba12SMartin K. Petersen 	if (unlikely(bip == NULL)) {
2917ba1ba12SMartin K. Petersen 		printk(KERN_ERR "could not allocate data integrity bioset\n");
2927ba1ba12SMartin K. Petersen 		kfree(buf);
2937ba1ba12SMartin K. Petersen 		return -EIO;
2947ba1ba12SMartin K. Petersen 	}
2957ba1ba12SMartin K. Petersen 
296*b1f01388SMartin K. Petersen 	bip->bip_flags |= BIP_BLOCK_INTEGRITY;
297d57a5f7cSKent Overstreet 	bip->bip_iter.bi_size = len;
29818593088SMartin K. Petersen 	bip_set_seed(bip, bio->bi_iter.bi_sector);
2997ba1ba12SMartin K. Petersen 
3007ba1ba12SMartin K. Petersen 	/* Map it */
3017ba1ba12SMartin K. Petersen 	offset = offset_in_page(buf);
3027ba1ba12SMartin K. Petersen 	for (i = 0 ; i < nr_pages ; i++) {
3037ba1ba12SMartin K. Petersen 		int ret;
3047ba1ba12SMartin K. Petersen 		bytes = PAGE_SIZE - offset;
3057ba1ba12SMartin K. Petersen 
3067ba1ba12SMartin K. Petersen 		if (len <= 0)
3077ba1ba12SMartin K. Petersen 			break;
3087ba1ba12SMartin K. Petersen 
3097ba1ba12SMartin K. Petersen 		if (bytes > len)
3107ba1ba12SMartin K. Petersen 			bytes = len;
3117ba1ba12SMartin K. Petersen 
3127ba1ba12SMartin K. Petersen 		ret = bio_integrity_add_page(bio, virt_to_page(buf),
3137ba1ba12SMartin K. Petersen 					     bytes, offset);
3147ba1ba12SMartin K. Petersen 
3157ba1ba12SMartin K. Petersen 		if (ret == 0)
3167ba1ba12SMartin K. Petersen 			return 0;
3177ba1ba12SMartin K. Petersen 
3187ba1ba12SMartin K. Petersen 		if (ret < bytes)
3197ba1ba12SMartin K. Petersen 			break;
3207ba1ba12SMartin K. Petersen 
3217ba1ba12SMartin K. Petersen 		buf += bytes;
3227ba1ba12SMartin K. Petersen 		len -= bytes;
3237ba1ba12SMartin K. Petersen 		offset = 0;
3247ba1ba12SMartin K. Petersen 	}
3257ba1ba12SMartin K. Petersen 
3267ba1ba12SMartin K. Petersen 	/* Install custom I/O completion handler if read verify is enabled */
3277ba1ba12SMartin K. Petersen 	if (bio_data_dir(bio) == READ) {
3287ba1ba12SMartin K. Petersen 		bip->bip_end_io = bio->bi_end_io;
3297ba1ba12SMartin K. Petersen 		bio->bi_end_io = bio_integrity_endio;
3307ba1ba12SMartin K. Petersen 	}
3317ba1ba12SMartin K. Petersen 
3327ba1ba12SMartin K. Petersen 	/* Auto-generate integrity metadata if this is a write */
3337ba1ba12SMartin K. Petersen 	if (bio_data_dir(bio) == WRITE)
33418593088SMartin K. Petersen 		bio_integrity_process(bio, bi->generate_fn);
3357ba1ba12SMartin K. Petersen 
3367ba1ba12SMartin K. Petersen 	return 0;
3377ba1ba12SMartin K. Petersen }
3387ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_prep);
3397ba1ba12SMartin K. Petersen 
3407ba1ba12SMartin K. Petersen /**
3417ba1ba12SMartin K. Petersen  * bio_integrity_verify_fn - Integrity I/O completion worker
3427ba1ba12SMartin K. Petersen  * @work:	Work struct stored in bio to be verified
3437ba1ba12SMartin K. Petersen  *
3447ba1ba12SMartin K. Petersen  * Description: This workqueue function is called to complete a READ
3457ba1ba12SMartin K. Petersen  * request.  The function verifies the transferred integrity metadata
3467ba1ba12SMartin K. Petersen  * and then calls the original bio end_io function.
3477ba1ba12SMartin K. Petersen  */
3487ba1ba12SMartin K. Petersen static void bio_integrity_verify_fn(struct work_struct *work)
3497ba1ba12SMartin K. Petersen {
3507ba1ba12SMartin K. Petersen 	struct bio_integrity_payload *bip =
3517ba1ba12SMartin K. Petersen 		container_of(work, struct bio_integrity_payload, bip_work);
3527ba1ba12SMartin K. Petersen 	struct bio *bio = bip->bip_bio;
35318593088SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
3547b24fc4dSMartin K. Petersen 	int error;
3557ba1ba12SMartin K. Petersen 
35618593088SMartin K. Petersen 	error = bio_integrity_process(bio, bi->verify_fn);
3577ba1ba12SMartin K. Petersen 
3587ba1ba12SMartin K. Petersen 	/* Restore original bio completion handler */
3597ba1ba12SMartin K. Petersen 	bio->bi_end_io = bip->bip_end_io;
360196d38bcSKent Overstreet 	bio_endio_nodec(bio, error);
3617ba1ba12SMartin K. Petersen }
3627ba1ba12SMartin K. Petersen 
3637ba1ba12SMartin K. Petersen /**
3647ba1ba12SMartin K. Petersen  * bio_integrity_endio - Integrity I/O completion function
3657ba1ba12SMartin K. Petersen  * @bio:	Protected bio
3667ba1ba12SMartin K. Petersen  * @error:	Pointer to errno
3677ba1ba12SMartin K. Petersen  *
3687ba1ba12SMartin K. Petersen  * Description: Completion for integrity I/O
3697ba1ba12SMartin K. Petersen  *
3707ba1ba12SMartin K. Petersen  * Normally I/O completion is done in interrupt context.  However,
3717ba1ba12SMartin K. Petersen  * verifying I/O integrity is a time-consuming task which must be run
3727ba1ba12SMartin K. Petersen  * in process context.	This function postpones completion
3737ba1ba12SMartin K. Petersen  * accordingly.
3747ba1ba12SMartin K. Petersen  */
3757ba1ba12SMartin K. Petersen void bio_integrity_endio(struct bio *bio, int error)
3767ba1ba12SMartin K. Petersen {
377180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
3787ba1ba12SMartin K. Petersen 
3797ba1ba12SMartin K. Petersen 	BUG_ON(bip->bip_bio != bio);
3807ba1ba12SMartin K. Petersen 
3817b24fc4dSMartin K. Petersen 	/* In case of an I/O error there is no point in verifying the
3827b24fc4dSMartin K. Petersen 	 * integrity metadata.  Restore original bio end_io handler
3837b24fc4dSMartin K. Petersen 	 * and run it.
3847b24fc4dSMartin K. Petersen 	 */
3857b24fc4dSMartin K. Petersen 	if (error) {
3867b24fc4dSMartin K. Petersen 		bio->bi_end_io = bip->bip_end_io;
38716f408dcSSagi Grimberg 		bio_endio_nodec(bio, error);
3887b24fc4dSMartin K. Petersen 
3897b24fc4dSMartin K. Petersen 		return;
3907b24fc4dSMartin K. Petersen 	}
3917b24fc4dSMartin K. Petersen 
3927ba1ba12SMartin K. Petersen 	INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
3937ba1ba12SMartin K. Petersen 	queue_work(kintegrityd_wq, &bip->bip_work);
3947ba1ba12SMartin K. Petersen }
3957ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_endio);
3967ba1ba12SMartin K. Petersen 
3977ba1ba12SMartin K. Petersen /**
3987ba1ba12SMartin K. Petersen  * bio_integrity_advance - Advance integrity vector
3997ba1ba12SMartin K. Petersen  * @bio:	bio whose integrity vector to update
4007ba1ba12SMartin K. Petersen  * @bytes_done:	number of data bytes that have been completed
4017ba1ba12SMartin K. Petersen  *
4027ba1ba12SMartin K. Petersen  * Description: This function calculates how many integrity bytes the
4037ba1ba12SMartin K. Petersen  * number of completed data bytes correspond to and advances the
4047ba1ba12SMartin K. Petersen  * integrity vector accordingly.
4057ba1ba12SMartin K. Petersen  */
4067ba1ba12SMartin K. Petersen void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
4077ba1ba12SMartin K. Petersen {
408180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
4097ba1ba12SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
410d57a5f7cSKent Overstreet 	unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
4117ba1ba12SMartin K. Petersen 
412d57a5f7cSKent Overstreet 	bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
4137ba1ba12SMartin K. Petersen }
4147ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_advance);
4157ba1ba12SMartin K. Petersen 
4167ba1ba12SMartin K. Petersen /**
4177ba1ba12SMartin K. Petersen  * bio_integrity_trim - Trim integrity vector
4187ba1ba12SMartin K. Petersen  * @bio:	bio whose integrity vector to update
4197ba1ba12SMartin K. Petersen  * @offset:	offset to first data sector
4207ba1ba12SMartin K. Petersen  * @sectors:	number of data sectors
4217ba1ba12SMartin K. Petersen  *
4227ba1ba12SMartin K. Petersen  * Description: Used to trim the integrity vector in a cloned bio.
4237ba1ba12SMartin K. Petersen  * The ivec will be advanced corresponding to 'offset' data sectors
4247ba1ba12SMartin K. Petersen  * and the length will be truncated corresponding to 'len' data
4257ba1ba12SMartin K. Petersen  * sectors.
4267ba1ba12SMartin K. Petersen  */
427b984679eSJens Axboe void bio_integrity_trim(struct bio *bio, unsigned int offset,
428b984679eSJens Axboe 			unsigned int sectors)
4297ba1ba12SMartin K. Petersen {
430180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip = bio_integrity(bio);
4317ba1ba12SMartin K. Petersen 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
4327ba1ba12SMartin K. Petersen 
433d57a5f7cSKent Overstreet 	bio_integrity_advance(bio, offset << 9);
434d57a5f7cSKent Overstreet 	bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors);
4357ba1ba12SMartin K. Petersen }
4367ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_trim);
4377ba1ba12SMartin K. Petersen 
4387ba1ba12SMartin K. Petersen /**
4397ba1ba12SMartin K. Petersen  * bio_integrity_clone - Callback for cloning bios with integrity metadata
4407ba1ba12SMartin K. Petersen  * @bio:	New bio
4417ba1ba12SMartin K. Petersen  * @bio_src:	Original bio
44287092698Sun'ichi Nomura  * @gfp_mask:	Memory allocation mask
4437ba1ba12SMartin K. Petersen  *
4447ba1ba12SMartin K. Petersen  * Description:	Called to allocate a bip when cloning a bio
4457ba1ba12SMartin K. Petersen  */
4467878cba9SMartin K. Petersen int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
4471e2a410fSKent Overstreet 			gfp_t gfp_mask)
4487ba1ba12SMartin K. Petersen {
449180b2f95SMartin K. Petersen 	struct bio_integrity_payload *bip_src = bio_integrity(bio_src);
4507ba1ba12SMartin K. Petersen 	struct bio_integrity_payload *bip;
4517ba1ba12SMartin K. Petersen 
4527ba1ba12SMartin K. Petersen 	BUG_ON(bip_src == NULL);
4537ba1ba12SMartin K. Petersen 
4541e2a410fSKent Overstreet 	bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
4557ba1ba12SMartin K. Petersen 
4567ba1ba12SMartin K. Petersen 	if (bip == NULL)
4577ba1ba12SMartin K. Petersen 		return -EIO;
4587ba1ba12SMartin K. Petersen 
4597ba1ba12SMartin K. Petersen 	memcpy(bip->bip_vec, bip_src->bip_vec,
4607ba1ba12SMartin K. Petersen 	       bip_src->bip_vcnt * sizeof(struct bio_vec));
4617ba1ba12SMartin K. Petersen 
4627ba1ba12SMartin K. Petersen 	bip->bip_vcnt = bip_src->bip_vcnt;
463d57a5f7cSKent Overstreet 	bip->bip_iter = bip_src->bip_iter;
4647ba1ba12SMartin K. Petersen 
4657ba1ba12SMartin K. Petersen 	return 0;
4667ba1ba12SMartin K. Petersen }
4677ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_clone);
4687ba1ba12SMartin K. Petersen 
4697878cba9SMartin K. Petersen int bioset_integrity_create(struct bio_set *bs, int pool_size)
4707ba1ba12SMartin K. Petersen {
471a91a2785SMartin K. Petersen 	if (bs->bio_integrity_pool)
472a91a2785SMartin K. Petersen 		return 0;
473a91a2785SMartin K. Petersen 
4749f060e22SKent Overstreet 	bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab);
4757878cba9SMartin K. Petersen 	if (!bs->bio_integrity_pool)
4767878cba9SMartin K. Petersen 		return -1;
4776d2a78e7SMartin K. Petersen 
478a6c39cb4SFabian Frederick 	bs->bvec_integrity_pool = biovec_create_pool(pool_size);
479bc5c8f07SGu Zheng 	if (!bs->bvec_integrity_pool) {
480bc5c8f07SGu Zheng 		mempool_destroy(bs->bio_integrity_pool);
481bc5c8f07SGu Zheng 		return -1;
482bc5c8f07SGu Zheng 	}
483bc5c8f07SGu Zheng 
4847ba1ba12SMartin K. Petersen 	return 0;
4857ba1ba12SMartin K. Petersen }
4867878cba9SMartin K. Petersen EXPORT_SYMBOL(bioset_integrity_create);
4877878cba9SMartin K. Petersen 
4887878cba9SMartin K. Petersen void bioset_integrity_free(struct bio_set *bs)
4897878cba9SMartin K. Petersen {
4907878cba9SMartin K. Petersen 	if (bs->bio_integrity_pool)
4917878cba9SMartin K. Petersen 		mempool_destroy(bs->bio_integrity_pool);
4929f060e22SKent Overstreet 
4939f060e22SKent Overstreet 	if (bs->bvec_integrity_pool)
494adbe6991SBjorn Helgaas 		mempool_destroy(bs->bvec_integrity_pool);
4957878cba9SMartin K. Petersen }
4967878cba9SMartin K. Petersen EXPORT_SYMBOL(bioset_integrity_free);
4977878cba9SMartin K. Petersen 
4987878cba9SMartin K. Petersen void __init bio_integrity_init(void)
4997878cba9SMartin K. Petersen {
500a6e8dc46STejun Heo 	/*
501a6e8dc46STejun Heo 	 * kintegrityd won't block much but may burn a lot of CPU cycles.
502a6e8dc46STejun Heo 	 * Make it highpri CPU intensive wq with max concurrency of 1.
503a6e8dc46STejun Heo 	 */
504a6e8dc46STejun Heo 	kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM |
505a6e8dc46STejun Heo 					 WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
5067878cba9SMartin K. Petersen 	if (!kintegrityd_wq)
5077878cba9SMartin K. Petersen 		panic("Failed to create kintegrityd\n");
5087878cba9SMartin K. Petersen 
5099f060e22SKent Overstreet 	bip_slab = kmem_cache_create("bio_integrity_payload",
5109f060e22SKent Overstreet 				     sizeof(struct bio_integrity_payload) +
5119f060e22SKent Overstreet 				     sizeof(struct bio_vec) * BIP_INLINE_VECS,
5129f060e22SKent Overstreet 				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
5139f060e22SKent Overstreet 	if (!bip_slab)
5149f060e22SKent Overstreet 		panic("Failed to create slab\n");
5157878cba9SMartin K. Petersen }
516