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