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