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; 827878cba9SMartin K. Petersen 837878cba9SMartin K. Petersen return bip; 849f060e22SKent Overstreet err: 859f060e22SKent Overstreet mempool_free(bip, bs->bio_integrity_pool); 869f060e22SKent Overstreet return NULL; 877878cba9SMartin K. Petersen } 887ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_alloc); 897ba1ba12SMartin K. Petersen 907ba1ba12SMartin K. Petersen /** 917ba1ba12SMartin K. Petersen * bio_integrity_free - Free bio integrity payload 927ba1ba12SMartin K. Petersen * @bio: bio containing bip to be freed 937ba1ba12SMartin K. Petersen * 947ba1ba12SMartin K. Petersen * Description: Used to free the integrity portion of a bio. Usually 957ba1ba12SMartin K. Petersen * called from bio_free(). 967ba1ba12SMartin K. Petersen */ 971e2a410fSKent Overstreet void bio_integrity_free(struct bio *bio) 987ba1ba12SMartin K. Petersen { 997ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = bio->bi_integrity; 1001e2a410fSKent Overstreet struct bio_set *bs = bio->bi_pool; 1011e2a410fSKent Overstreet 10229ed7813SKent Overstreet if (bip->bip_owns_buf) 1037ba1ba12SMartin K. Petersen kfree(bip->bip_buf); 1047ba1ba12SMartin K. Petersen 1059f060e22SKent Overstreet if (bs) { 1069f060e22SKent Overstreet if (bip->bip_slab != BIO_POOL_NONE) 1079f060e22SKent Overstreet bvec_free(bs->bvec_integrity_pool, bip->bip_vec, 1089f060e22SKent Overstreet bip->bip_slab); 1099f060e22SKent Overstreet 1107878cba9SMartin K. Petersen mempool_free(bip, bs->bio_integrity_pool); 1119f060e22SKent Overstreet } else { 1129f060e22SKent Overstreet kfree(bip); 1139f060e22SKent Overstreet } 1147ba1ba12SMartin K. Petersen 1157ba1ba12SMartin K. Petersen bio->bi_integrity = NULL; 1167ba1ba12SMartin K. Petersen } 1177ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_free); 1187ba1ba12SMartin K. Petersen 1197ba1ba12SMartin K. Petersen /** 1207ba1ba12SMartin K. Petersen * bio_integrity_add_page - Attach integrity metadata 1217ba1ba12SMartin K. Petersen * @bio: bio to update 1227ba1ba12SMartin K. Petersen * @page: page containing integrity metadata 1237ba1ba12SMartin K. Petersen * @len: number of bytes of integrity metadata in page 1247ba1ba12SMartin K. Petersen * @offset: start offset within page 1257ba1ba12SMartin K. Petersen * 1267ba1ba12SMartin K. Petersen * Description: Attach a page containing integrity metadata to bio. 1277ba1ba12SMartin K. Petersen */ 1287ba1ba12SMartin K. Petersen int bio_integrity_add_page(struct bio *bio, struct page *page, 1297ba1ba12SMartin K. Petersen unsigned int len, unsigned int offset) 1307ba1ba12SMartin K. Petersen { 1317ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = bio->bi_integrity; 1327ba1ba12SMartin K. Petersen struct bio_vec *iv; 1337ba1ba12SMartin K. Petersen 134cbcd1054SGu Zheng if (bip->bip_vcnt >= bip->bip_max_vcnt) { 1357ba1ba12SMartin K. Petersen printk(KERN_ERR "%s: bip_vec full\n", __func__); 1367ba1ba12SMartin K. Petersen return 0; 1377ba1ba12SMartin K. Petersen } 1387ba1ba12SMartin K. Petersen 139d57a5f7cSKent Overstreet iv = bip->bip_vec + bip->bip_vcnt; 1407ba1ba12SMartin K. Petersen 1417ba1ba12SMartin K. Petersen iv->bv_page = page; 1427ba1ba12SMartin K. Petersen iv->bv_len = len; 1437ba1ba12SMartin K. Petersen iv->bv_offset = offset; 1447ba1ba12SMartin K. Petersen bip->bip_vcnt++; 1457ba1ba12SMartin K. Petersen 1467ba1ba12SMartin K. Petersen return len; 1477ba1ba12SMartin K. Petersen } 1487ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_add_page); 1497ba1ba12SMartin K. Petersen 1507ba1ba12SMartin K. Petersen /** 1517ba1ba12SMartin K. Petersen * bio_integrity_enabled - Check whether integrity can be passed 1527ba1ba12SMartin K. Petersen * @bio: bio to check 1537ba1ba12SMartin K. Petersen * 1547ba1ba12SMartin K. Petersen * Description: Determines whether bio_integrity_prep() can be called 1557ba1ba12SMartin K. Petersen * on this bio or not. bio data direction and target device must be 1567ba1ba12SMartin K. Petersen * set prior to calling. The functions honors the write_generate and 1577ba1ba12SMartin K. Petersen * read_verify flags in sysfs. 1587ba1ba12SMartin K. Petersen */ 159*e7258c1aSMartin K. Petersen bool bio_integrity_enabled(struct bio *bio) 1607ba1ba12SMartin K. Petersen { 161*e7258c1aSMartin K. Petersen struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); 162*e7258c1aSMartin K. Petersen 163e69f18f0SMartin K. Petersen if (!bio_is_rw(bio)) 164*e7258c1aSMartin K. Petersen return false; 165e69f18f0SMartin K. Petersen 1667ba1ba12SMartin K. Petersen /* Already protected? */ 1677ba1ba12SMartin K. Petersen if (bio_integrity(bio)) 168*e7258c1aSMartin K. Petersen return false; 1697ba1ba12SMartin K. Petersen 170*e7258c1aSMartin K. Petersen if (bi == NULL) 171*e7258c1aSMartin K. Petersen return false; 172*e7258c1aSMartin K. Petersen 173*e7258c1aSMartin K. Petersen if (bio_data_dir(bio) == READ && bi->verify_fn != NULL && 174*e7258c1aSMartin K. Petersen (bi->flags & INTEGRITY_FLAG_READ)) 175*e7258c1aSMartin K. Petersen return true; 176*e7258c1aSMartin K. Petersen 177*e7258c1aSMartin K. Petersen if (bio_data_dir(bio) == WRITE && bi->generate_fn != NULL && 178*e7258c1aSMartin K. Petersen (bi->flags & INTEGRITY_FLAG_WRITE)) 179*e7258c1aSMartin K. Petersen return true; 180*e7258c1aSMartin K. Petersen 181*e7258c1aSMartin K. Petersen return false; 1827ba1ba12SMartin K. Petersen } 1837ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_enabled); 1847ba1ba12SMartin K. Petersen 1857ba1ba12SMartin K. Petersen /** 1867ba1ba12SMartin K. Petersen * bio_integrity_hw_sectors - Convert 512b sectors to hardware ditto 1877ba1ba12SMartin K. Petersen * @bi: blk_integrity profile for device 1887ba1ba12SMartin K. Petersen * @sectors: Number of 512 sectors to convert 1897ba1ba12SMartin K. Petersen * 1907ba1ba12SMartin K. Petersen * Description: The block layer calculates everything in 512 byte 1917ba1ba12SMartin K. Petersen * sectors but integrity metadata is done in terms of the hardware 1927ba1ba12SMartin K. Petersen * sector size of the storage device. Convert the block layer sectors 1937ba1ba12SMartin K. Petersen * to physical sectors. 1947ba1ba12SMartin K. Petersen */ 195b984679eSJens Axboe static inline unsigned int bio_integrity_hw_sectors(struct blk_integrity *bi, 196b984679eSJens Axboe unsigned int sectors) 1977ba1ba12SMartin K. Petersen { 1987ba1ba12SMartin K. Petersen /* At this point there are only 512b or 4096b DIF/EPP devices */ 1997ba1ba12SMartin K. Petersen if (bi->sector_size == 4096) 2007ba1ba12SMartin K. Petersen return sectors >>= 3; 2017ba1ba12SMartin K. Petersen 2027ba1ba12SMartin K. Petersen return sectors; 2037ba1ba12SMartin K. Petersen } 2047ba1ba12SMartin K. Petersen 205d57a5f7cSKent Overstreet static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi, 206d57a5f7cSKent Overstreet unsigned int sectors) 207d57a5f7cSKent Overstreet { 208d57a5f7cSKent Overstreet return bio_integrity_hw_sectors(bi, sectors) * bi->tuple_size; 209d57a5f7cSKent Overstreet } 210d57a5f7cSKent Overstreet 2117ba1ba12SMartin K. Petersen /** 2127ba1ba12SMartin K. Petersen * bio_integrity_tag_size - Retrieve integrity tag space 2137ba1ba12SMartin K. Petersen * @bio: bio to inspect 2147ba1ba12SMartin K. Petersen * 2157ba1ba12SMartin K. Petersen * Description: Returns the maximum number of tag bytes that can be 2167ba1ba12SMartin K. Petersen * attached to this bio. Filesystems can use this to determine how 2177ba1ba12SMartin K. Petersen * much metadata to attach to an I/O. 2187ba1ba12SMartin K. Petersen */ 2197ba1ba12SMartin K. Petersen unsigned int bio_integrity_tag_size(struct bio *bio) 2207ba1ba12SMartin K. Petersen { 2217ba1ba12SMartin K. Petersen struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); 2227ba1ba12SMartin K. Petersen 2234f024f37SKent Overstreet BUG_ON(bio->bi_iter.bi_size == 0); 2247ba1ba12SMartin K. Petersen 2254f024f37SKent Overstreet return bi->tag_size * (bio->bi_iter.bi_size / bi->sector_size); 2267ba1ba12SMartin K. Petersen } 2277ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_tag_size); 2287ba1ba12SMartin K. Petersen 2290b4ef8deSRashika Kheria static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, 2300b4ef8deSRashika Kheria int set) 2317ba1ba12SMartin K. Petersen { 2327ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = bio->bi_integrity; 2337ba1ba12SMartin K. Petersen struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); 2347ba1ba12SMartin K. Petersen unsigned int nr_sectors; 2357ba1ba12SMartin K. Petersen 2367ba1ba12SMartin K. Petersen BUG_ON(bip->bip_buf == NULL); 2377ba1ba12SMartin K. Petersen 2387ba1ba12SMartin K. Petersen if (bi->tag_size == 0) 2397ba1ba12SMartin K. Petersen return -1; 2407ba1ba12SMartin K. Petersen 241b984679eSJens Axboe nr_sectors = bio_integrity_hw_sectors(bi, 242b984679eSJens Axboe DIV_ROUND_UP(len, bi->tag_size)); 2437ba1ba12SMartin K. Petersen 244d57a5f7cSKent Overstreet if (nr_sectors * bi->tuple_size > bip->bip_iter.bi_size) { 245d57a5f7cSKent Overstreet printk(KERN_ERR "%s: tag too big for bio: %u > %u\n", __func__, 246d57a5f7cSKent Overstreet nr_sectors * bi->tuple_size, bip->bip_iter.bi_size); 2477ba1ba12SMartin K. Petersen return -1; 2487ba1ba12SMartin K. Petersen } 2497ba1ba12SMartin K. Petersen 2507ba1ba12SMartin K. Petersen if (set) 2517ba1ba12SMartin K. Petersen bi->set_tag_fn(bip->bip_buf, tag_buf, nr_sectors); 2527ba1ba12SMartin K. Petersen else 2537ba1ba12SMartin K. Petersen bi->get_tag_fn(bip->bip_buf, tag_buf, nr_sectors); 2547ba1ba12SMartin K. Petersen 2557ba1ba12SMartin K. Petersen return 0; 2567ba1ba12SMartin K. Petersen } 2577ba1ba12SMartin K. Petersen 2587ba1ba12SMartin K. Petersen /** 2597ba1ba12SMartin K. Petersen * bio_integrity_set_tag - Attach a tag buffer to a bio 2607ba1ba12SMartin K. Petersen * @bio: bio to attach buffer to 2617ba1ba12SMartin K. Petersen * @tag_buf: Pointer to a buffer containing tag data 2627ba1ba12SMartin K. Petersen * @len: Length of the included buffer 2637ba1ba12SMartin K. Petersen * 2647ba1ba12SMartin K. Petersen * Description: Use this function to tag a bio by leveraging the extra 2657ba1ba12SMartin K. Petersen * space provided by devices formatted with integrity protection. The 2667ba1ba12SMartin K. Petersen * size of the integrity buffer must be <= to the size reported by 2677ba1ba12SMartin K. Petersen * bio_integrity_tag_size(). 2687ba1ba12SMartin K. Petersen */ 2697ba1ba12SMartin K. Petersen int bio_integrity_set_tag(struct bio *bio, void *tag_buf, unsigned int len) 2707ba1ba12SMartin K. Petersen { 2717ba1ba12SMartin K. Petersen BUG_ON(bio_data_dir(bio) != WRITE); 2727ba1ba12SMartin K. Petersen 2737ba1ba12SMartin K. Petersen return bio_integrity_tag(bio, tag_buf, len, 1); 2747ba1ba12SMartin K. Petersen } 2757ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_set_tag); 2767ba1ba12SMartin K. Petersen 2777ba1ba12SMartin K. Petersen /** 2787ba1ba12SMartin K. Petersen * bio_integrity_get_tag - Retrieve a tag buffer from a bio 2797ba1ba12SMartin K. Petersen * @bio: bio to retrieve buffer from 2807ba1ba12SMartin K. Petersen * @tag_buf: Pointer to a buffer for the tag data 2817ba1ba12SMartin K. Petersen * @len: Length of the target buffer 2827ba1ba12SMartin K. Petersen * 2837ba1ba12SMartin K. Petersen * Description: Use this function to retrieve the tag buffer from a 2847ba1ba12SMartin K. Petersen * completed I/O. The size of the integrity buffer must be <= to the 2857ba1ba12SMartin K. Petersen * size reported by bio_integrity_tag_size(). 2867ba1ba12SMartin K. Petersen */ 2877ba1ba12SMartin K. Petersen int bio_integrity_get_tag(struct bio *bio, void *tag_buf, unsigned int len) 2887ba1ba12SMartin K. Petersen { 2897ba1ba12SMartin K. Petersen BUG_ON(bio_data_dir(bio) != READ); 2907ba1ba12SMartin K. Petersen 2917ba1ba12SMartin K. Petersen return bio_integrity_tag(bio, tag_buf, len, 0); 2927ba1ba12SMartin K. Petersen } 2937ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_get_tag); 2947ba1ba12SMartin K. Petersen 2957ba1ba12SMartin K. Petersen /** 296bf36f9cfSGu Zheng * bio_integrity_generate_verify - Generate/verify integrity metadata for a bio 297bf36f9cfSGu Zheng * @bio: bio to generate/verify integrity metadata for 298bf36f9cfSGu Zheng * @operate: operate number, 1 for generate, 0 for verify 2997ba1ba12SMartin K. Petersen */ 300bf36f9cfSGu Zheng static int bio_integrity_generate_verify(struct bio *bio, int operate) 3017ba1ba12SMartin K. Petersen { 3027ba1ba12SMartin K. Petersen struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); 3037ba1ba12SMartin K. Petersen struct blk_integrity_exchg bix; 3040bc69973SMartin K. Petersen struct bio_vec *bv; 305bf36f9cfSGu Zheng sector_t sector; 3060bc69973SMartin K. Petersen unsigned int sectors, ret = 0, i; 3077ba1ba12SMartin K. Petersen void *prot_buf = bio->bi_integrity->bip_buf; 3087ba1ba12SMartin K. Petersen 309bf36f9cfSGu Zheng if (operate) 310bf36f9cfSGu Zheng sector = bio->bi_iter.bi_sector; 311bf36f9cfSGu Zheng else 312bf36f9cfSGu Zheng sector = bio->bi_integrity->bip_iter.bi_sector; 313bf36f9cfSGu Zheng 3147ba1ba12SMartin K. Petersen bix.disk_name = bio->bi_bdev->bd_disk->disk_name; 3157ba1ba12SMartin K. Petersen bix.sector_size = bi->sector_size; 3167ba1ba12SMartin K. Petersen 3170bc69973SMartin K. Petersen bio_for_each_segment_all(bv, bio, i) { 3180bc69973SMartin K. Petersen void *kaddr = kmap_atomic(bv->bv_page); 3190bc69973SMartin K. Petersen bix.data_buf = kaddr + bv->bv_offset; 3200bc69973SMartin K. Petersen bix.data_size = bv->bv_len; 3217ba1ba12SMartin K. Petersen bix.prot_buf = prot_buf; 3227ba1ba12SMartin K. Petersen bix.sector = sector; 3237ba1ba12SMartin K. Petersen 3240bc69973SMartin K. Petersen if (operate) 3257ba1ba12SMartin K. Petersen bi->generate_fn(&bix); 3260bc69973SMartin K. Petersen else { 327bf36f9cfSGu Zheng ret = bi->verify_fn(&bix); 328bf36f9cfSGu Zheng if (ret) { 329bf36f9cfSGu Zheng kunmap_atomic(kaddr); 330bf36f9cfSGu Zheng return ret; 331bf36f9cfSGu Zheng } 332bf36f9cfSGu Zheng } 3337ba1ba12SMartin K. Petersen 3340bc69973SMartin K. Petersen sectors = bv->bv_len / bi->sector_size; 3357ba1ba12SMartin K. Petersen sector += sectors; 3367ba1ba12SMartin K. Petersen prot_buf += sectors * bi->tuple_size; 3377ba1ba12SMartin K. Petersen 338e8e3c3d6SCong Wang kunmap_atomic(kaddr); 3397ba1ba12SMartin K. Petersen } 340bf36f9cfSGu Zheng return ret; 341bf36f9cfSGu Zheng } 342bf36f9cfSGu Zheng 343bf36f9cfSGu Zheng /** 344bf36f9cfSGu Zheng * bio_integrity_generate - Generate integrity metadata for a bio 345bf36f9cfSGu Zheng * @bio: bio to generate integrity metadata for 346bf36f9cfSGu Zheng * 347bf36f9cfSGu Zheng * Description: Generates integrity metadata for a bio by calling the 348bf36f9cfSGu Zheng * block device's generation callback function. The bio must have a 349bf36f9cfSGu Zheng * bip attached with enough room to accommodate the generated 350bf36f9cfSGu Zheng * integrity metadata. 351bf36f9cfSGu Zheng */ 352bf36f9cfSGu Zheng static void bio_integrity_generate(struct bio *bio) 353bf36f9cfSGu Zheng { 354bf36f9cfSGu Zheng bio_integrity_generate_verify(bio, 1); 3557ba1ba12SMartin K. Petersen } 3567ba1ba12SMartin K. Petersen 3579c02f2b0SJens Axboe static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi) 3589c02f2b0SJens Axboe { 3599c02f2b0SJens Axboe if (bi) 3609c02f2b0SJens Axboe return bi->tuple_size; 3619c02f2b0SJens Axboe 3629c02f2b0SJens Axboe return 0; 3639c02f2b0SJens Axboe } 3649c02f2b0SJens Axboe 3657ba1ba12SMartin K. Petersen /** 3667ba1ba12SMartin K. Petersen * bio_integrity_prep - Prepare bio for integrity I/O 3677ba1ba12SMartin K. Petersen * @bio: bio to prepare 3687ba1ba12SMartin K. Petersen * 3697ba1ba12SMartin K. Petersen * Description: Allocates a buffer for integrity metadata, maps the 3707ba1ba12SMartin K. Petersen * pages and attaches them to a bio. The bio must have data 3717ba1ba12SMartin K. Petersen * direction, target device and start sector set priot to calling. In 3727ba1ba12SMartin K. Petersen * the WRITE case, integrity metadata will be generated using the 3737ba1ba12SMartin K. Petersen * block device's integrity function. In the READ case, the buffer 3747ba1ba12SMartin K. Petersen * will be prepared for DMA and a suitable end_io handler set up. 3757ba1ba12SMartin K. Petersen */ 3767ba1ba12SMartin K. Petersen int bio_integrity_prep(struct bio *bio) 3777ba1ba12SMartin K. Petersen { 3787ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip; 3797ba1ba12SMartin K. Petersen struct blk_integrity *bi; 3807ba1ba12SMartin K. Petersen struct request_queue *q; 3817ba1ba12SMartin K. Petersen void *buf; 3827ba1ba12SMartin K. Petersen unsigned long start, end; 3837ba1ba12SMartin K. Petersen unsigned int len, nr_pages; 3847ba1ba12SMartin K. Petersen unsigned int bytes, offset, i; 3857ba1ba12SMartin K. Petersen unsigned int sectors; 3867ba1ba12SMartin K. Petersen 3877ba1ba12SMartin K. Petersen bi = bdev_get_integrity(bio->bi_bdev); 3887ba1ba12SMartin K. Petersen q = bdev_get_queue(bio->bi_bdev); 3897ba1ba12SMartin K. Petersen BUG_ON(bi == NULL); 3907ba1ba12SMartin K. Petersen BUG_ON(bio_integrity(bio)); 3917ba1ba12SMartin K. Petersen 3927ba1ba12SMartin K. Petersen sectors = bio_integrity_hw_sectors(bi, bio_sectors(bio)); 3937ba1ba12SMartin K. Petersen 3947ba1ba12SMartin K. Petersen /* Allocate kernel buffer for protection data */ 3957ba1ba12SMartin K. Petersen len = sectors * blk_integrity_tuple_size(bi); 39672f46503SDavid Rientjes buf = kmalloc(len, GFP_NOIO | q->bounce_gfp); 3977ba1ba12SMartin K. Petersen if (unlikely(buf == NULL)) { 3987ba1ba12SMartin K. Petersen printk(KERN_ERR "could not allocate integrity buffer\n"); 399220eb7fdSAndrew Morton return -ENOMEM; 4007ba1ba12SMartin K. Petersen } 4017ba1ba12SMartin K. Petersen 4027ba1ba12SMartin K. Petersen end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT; 4037ba1ba12SMartin K. Petersen start = ((unsigned long) buf) >> PAGE_SHIFT; 4047ba1ba12SMartin K. Petersen nr_pages = end - start; 4057ba1ba12SMartin K. Petersen 4067ba1ba12SMartin K. Petersen /* Allocate bio integrity payload and integrity vectors */ 4077ba1ba12SMartin K. Petersen bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages); 4087ba1ba12SMartin K. Petersen if (unlikely(bip == NULL)) { 4097ba1ba12SMartin K. Petersen printk(KERN_ERR "could not allocate data integrity bioset\n"); 4107ba1ba12SMartin K. Petersen kfree(buf); 4117ba1ba12SMartin K. Petersen return -EIO; 4127ba1ba12SMartin K. Petersen } 4137ba1ba12SMartin K. Petersen 41429ed7813SKent Overstreet bip->bip_owns_buf = 1; 4157ba1ba12SMartin K. Petersen bip->bip_buf = buf; 416d57a5f7cSKent Overstreet bip->bip_iter.bi_size = len; 417d57a5f7cSKent Overstreet bip->bip_iter.bi_sector = bio->bi_iter.bi_sector; 4187ba1ba12SMartin K. Petersen 4197ba1ba12SMartin K. Petersen /* Map it */ 4207ba1ba12SMartin K. Petersen offset = offset_in_page(buf); 4217ba1ba12SMartin K. Petersen for (i = 0 ; i < nr_pages ; i++) { 4227ba1ba12SMartin K. Petersen int ret; 4237ba1ba12SMartin K. Petersen bytes = PAGE_SIZE - offset; 4247ba1ba12SMartin K. Petersen 4257ba1ba12SMartin K. Petersen if (len <= 0) 4267ba1ba12SMartin K. Petersen break; 4277ba1ba12SMartin K. Petersen 4287ba1ba12SMartin K. Petersen if (bytes > len) 4297ba1ba12SMartin K. Petersen bytes = len; 4307ba1ba12SMartin K. Petersen 4317ba1ba12SMartin K. Petersen ret = bio_integrity_add_page(bio, virt_to_page(buf), 4327ba1ba12SMartin K. Petersen bytes, offset); 4337ba1ba12SMartin K. Petersen 4347ba1ba12SMartin K. Petersen if (ret == 0) 4357ba1ba12SMartin K. Petersen return 0; 4367ba1ba12SMartin K. Petersen 4377ba1ba12SMartin K. Petersen if (ret < bytes) 4387ba1ba12SMartin K. Petersen break; 4397ba1ba12SMartin K. Petersen 4407ba1ba12SMartin K. Petersen buf += bytes; 4417ba1ba12SMartin K. Petersen len -= bytes; 4427ba1ba12SMartin K. Petersen offset = 0; 4437ba1ba12SMartin K. Petersen } 4447ba1ba12SMartin K. Petersen 4457ba1ba12SMartin K. Petersen /* Install custom I/O completion handler if read verify is enabled */ 4467ba1ba12SMartin K. Petersen if (bio_data_dir(bio) == READ) { 4477ba1ba12SMartin K. Petersen bip->bip_end_io = bio->bi_end_io; 4487ba1ba12SMartin K. Petersen bio->bi_end_io = bio_integrity_endio; 4497ba1ba12SMartin K. Petersen } 4507ba1ba12SMartin K. Petersen 4517ba1ba12SMartin K. Petersen /* Auto-generate integrity metadata if this is a write */ 4527ba1ba12SMartin K. Petersen if (bio_data_dir(bio) == WRITE) 4537ba1ba12SMartin K. Petersen bio_integrity_generate(bio); 4547ba1ba12SMartin K. Petersen 4557ba1ba12SMartin K. Petersen return 0; 4567ba1ba12SMartin K. Petersen } 4577ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_prep); 4587ba1ba12SMartin K. Petersen 4597ba1ba12SMartin K. Petersen /** 4607ba1ba12SMartin K. Petersen * bio_integrity_verify - Verify integrity metadata for a bio 4617ba1ba12SMartin K. Petersen * @bio: bio to verify 4627ba1ba12SMartin K. Petersen * 4637ba1ba12SMartin K. Petersen * Description: This function is called to verify the integrity of a 4647ba1ba12SMartin K. Petersen * bio. The data in the bio io_vec is compared to the integrity 4657ba1ba12SMartin K. Petersen * metadata returned by the HBA. 4667ba1ba12SMartin K. Petersen */ 4677ba1ba12SMartin K. Petersen static int bio_integrity_verify(struct bio *bio) 4687ba1ba12SMartin K. Petersen { 469bf36f9cfSGu Zheng return bio_integrity_generate_verify(bio, 0); 4707ba1ba12SMartin K. Petersen } 4717ba1ba12SMartin K. Petersen 4727ba1ba12SMartin K. Petersen /** 4737ba1ba12SMartin K. Petersen * bio_integrity_verify_fn - Integrity I/O completion worker 4747ba1ba12SMartin K. Petersen * @work: Work struct stored in bio to be verified 4757ba1ba12SMartin K. Petersen * 4767ba1ba12SMartin K. Petersen * Description: This workqueue function is called to complete a READ 4777ba1ba12SMartin K. Petersen * request. The function verifies the transferred integrity metadata 4787ba1ba12SMartin K. Petersen * and then calls the original bio end_io function. 4797ba1ba12SMartin K. Petersen */ 4807ba1ba12SMartin K. Petersen static void bio_integrity_verify_fn(struct work_struct *work) 4817ba1ba12SMartin K. Petersen { 4827ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = 4837ba1ba12SMartin K. Petersen container_of(work, struct bio_integrity_payload, bip_work); 4847ba1ba12SMartin K. Petersen struct bio *bio = bip->bip_bio; 4857b24fc4dSMartin K. Petersen int error; 4867ba1ba12SMartin K. Petersen 4877b24fc4dSMartin K. Petersen error = bio_integrity_verify(bio); 4887ba1ba12SMartin K. Petersen 4897ba1ba12SMartin K. Petersen /* Restore original bio completion handler */ 4907ba1ba12SMartin K. Petersen bio->bi_end_io = bip->bip_end_io; 491196d38bcSKent Overstreet bio_endio_nodec(bio, error); 4927ba1ba12SMartin K. Petersen } 4937ba1ba12SMartin K. Petersen 4947ba1ba12SMartin K. Petersen /** 4957ba1ba12SMartin K. Petersen * bio_integrity_endio - Integrity I/O completion function 4967ba1ba12SMartin K. Petersen * @bio: Protected bio 4977ba1ba12SMartin K. Petersen * @error: Pointer to errno 4987ba1ba12SMartin K. Petersen * 4997ba1ba12SMartin K. Petersen * Description: Completion for integrity I/O 5007ba1ba12SMartin K. Petersen * 5017ba1ba12SMartin K. Petersen * Normally I/O completion is done in interrupt context. However, 5027ba1ba12SMartin K. Petersen * verifying I/O integrity is a time-consuming task which must be run 5037ba1ba12SMartin K. Petersen * in process context. This function postpones completion 5047ba1ba12SMartin K. Petersen * accordingly. 5057ba1ba12SMartin K. Petersen */ 5067ba1ba12SMartin K. Petersen void bio_integrity_endio(struct bio *bio, int error) 5077ba1ba12SMartin K. Petersen { 5087ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = bio->bi_integrity; 5097ba1ba12SMartin K. Petersen 5107ba1ba12SMartin K. Petersen BUG_ON(bip->bip_bio != bio); 5117ba1ba12SMartin K. Petersen 5127b24fc4dSMartin K. Petersen /* In case of an I/O error there is no point in verifying the 5137b24fc4dSMartin K. Petersen * integrity metadata. Restore original bio end_io handler 5147b24fc4dSMartin K. Petersen * and run it. 5157b24fc4dSMartin K. Petersen */ 5167b24fc4dSMartin K. Petersen if (error) { 5177b24fc4dSMartin K. Petersen bio->bi_end_io = bip->bip_end_io; 51816f408dcSSagi Grimberg bio_endio_nodec(bio, error); 5197b24fc4dSMartin K. Petersen 5207b24fc4dSMartin K. Petersen return; 5217b24fc4dSMartin K. Petersen } 5227b24fc4dSMartin K. Petersen 5237ba1ba12SMartin K. Petersen INIT_WORK(&bip->bip_work, bio_integrity_verify_fn); 5247ba1ba12SMartin K. Petersen queue_work(kintegrityd_wq, &bip->bip_work); 5257ba1ba12SMartin K. Petersen } 5267ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_endio); 5277ba1ba12SMartin K. Petersen 5287ba1ba12SMartin K. Petersen /** 5297ba1ba12SMartin K. Petersen * bio_integrity_advance - Advance integrity vector 5307ba1ba12SMartin K. Petersen * @bio: bio whose integrity vector to update 5317ba1ba12SMartin K. Petersen * @bytes_done: number of data bytes that have been completed 5327ba1ba12SMartin K. Petersen * 5337ba1ba12SMartin K. Petersen * Description: This function calculates how many integrity bytes the 5347ba1ba12SMartin K. Petersen * number of completed data bytes correspond to and advances the 5357ba1ba12SMartin K. Petersen * integrity vector accordingly. 5367ba1ba12SMartin K. Petersen */ 5377ba1ba12SMartin K. Petersen void bio_integrity_advance(struct bio *bio, unsigned int bytes_done) 5387ba1ba12SMartin K. Petersen { 5397ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = bio->bi_integrity; 5407ba1ba12SMartin K. Petersen struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); 541d57a5f7cSKent Overstreet unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9); 5427ba1ba12SMartin K. Petersen 543d57a5f7cSKent Overstreet bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes); 5447ba1ba12SMartin K. Petersen } 5457ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_advance); 5467ba1ba12SMartin K. Petersen 5477ba1ba12SMartin K. Petersen /** 5487ba1ba12SMartin K. Petersen * bio_integrity_trim - Trim integrity vector 5497ba1ba12SMartin K. Petersen * @bio: bio whose integrity vector to update 5507ba1ba12SMartin K. Petersen * @offset: offset to first data sector 5517ba1ba12SMartin K. Petersen * @sectors: number of data sectors 5527ba1ba12SMartin K. Petersen * 5537ba1ba12SMartin K. Petersen * Description: Used to trim the integrity vector in a cloned bio. 5547ba1ba12SMartin K. Petersen * The ivec will be advanced corresponding to 'offset' data sectors 5557ba1ba12SMartin K. Petersen * and the length will be truncated corresponding to 'len' data 5567ba1ba12SMartin K. Petersen * sectors. 5577ba1ba12SMartin K. Petersen */ 558b984679eSJens Axboe void bio_integrity_trim(struct bio *bio, unsigned int offset, 559b984679eSJens Axboe unsigned int sectors) 5607ba1ba12SMartin K. Petersen { 5617ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip = bio->bi_integrity; 5627ba1ba12SMartin K. Petersen struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); 5637ba1ba12SMartin K. Petersen 564d57a5f7cSKent Overstreet bio_integrity_advance(bio, offset << 9); 565d57a5f7cSKent Overstreet bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors); 5667ba1ba12SMartin K. Petersen } 5677ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_trim); 5687ba1ba12SMartin K. Petersen 5697ba1ba12SMartin K. Petersen /** 5707ba1ba12SMartin K. Petersen * bio_integrity_clone - Callback for cloning bios with integrity metadata 5717ba1ba12SMartin K. Petersen * @bio: New bio 5727ba1ba12SMartin K. Petersen * @bio_src: Original bio 57387092698Sun'ichi Nomura * @gfp_mask: Memory allocation mask 5747ba1ba12SMartin K. Petersen * 5757ba1ba12SMartin K. Petersen * Description: Called to allocate a bip when cloning a bio 5767ba1ba12SMartin K. Petersen */ 5777878cba9SMartin K. Petersen int bio_integrity_clone(struct bio *bio, struct bio *bio_src, 5781e2a410fSKent Overstreet gfp_t gfp_mask) 5797ba1ba12SMartin K. Petersen { 5807ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip_src = bio_src->bi_integrity; 5817ba1ba12SMartin K. Petersen struct bio_integrity_payload *bip; 5827ba1ba12SMartin K. Petersen 5837ba1ba12SMartin K. Petersen BUG_ON(bip_src == NULL); 5847ba1ba12SMartin K. Petersen 5851e2a410fSKent Overstreet bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt); 5867ba1ba12SMartin K. Petersen 5877ba1ba12SMartin K. Petersen if (bip == NULL) 5887ba1ba12SMartin K. Petersen return -EIO; 5897ba1ba12SMartin K. Petersen 5907ba1ba12SMartin K. Petersen memcpy(bip->bip_vec, bip_src->bip_vec, 5917ba1ba12SMartin K. Petersen bip_src->bip_vcnt * sizeof(struct bio_vec)); 5927ba1ba12SMartin K. Petersen 5937ba1ba12SMartin K. Petersen bip->bip_vcnt = bip_src->bip_vcnt; 594d57a5f7cSKent Overstreet bip->bip_iter = bip_src->bip_iter; 5957ba1ba12SMartin K. Petersen 5967ba1ba12SMartin K. Petersen return 0; 5977ba1ba12SMartin K. Petersen } 5987ba1ba12SMartin K. Petersen EXPORT_SYMBOL(bio_integrity_clone); 5997ba1ba12SMartin K. Petersen 6007878cba9SMartin K. Petersen int bioset_integrity_create(struct bio_set *bs, int pool_size) 6017ba1ba12SMartin K. Petersen { 602a91a2785SMartin K. Petersen if (bs->bio_integrity_pool) 603a91a2785SMartin K. Petersen return 0; 604a91a2785SMartin K. Petersen 6059f060e22SKent Overstreet bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab); 6067878cba9SMartin K. Petersen if (!bs->bio_integrity_pool) 6077878cba9SMartin K. Petersen return -1; 6086d2a78e7SMartin K. Petersen 609a6c39cb4SFabian Frederick bs->bvec_integrity_pool = biovec_create_pool(pool_size); 610bc5c8f07SGu Zheng if (!bs->bvec_integrity_pool) { 611bc5c8f07SGu Zheng mempool_destroy(bs->bio_integrity_pool); 612bc5c8f07SGu Zheng return -1; 613bc5c8f07SGu Zheng } 614bc5c8f07SGu Zheng 6157ba1ba12SMartin K. Petersen return 0; 6167ba1ba12SMartin K. Petersen } 6177878cba9SMartin K. Petersen EXPORT_SYMBOL(bioset_integrity_create); 6187878cba9SMartin K. Petersen 6197878cba9SMartin K. Petersen void bioset_integrity_free(struct bio_set *bs) 6207878cba9SMartin K. Petersen { 6217878cba9SMartin K. Petersen if (bs->bio_integrity_pool) 6227878cba9SMartin K. Petersen mempool_destroy(bs->bio_integrity_pool); 6239f060e22SKent Overstreet 6249f060e22SKent Overstreet if (bs->bvec_integrity_pool) 625adbe6991SBjorn Helgaas mempool_destroy(bs->bvec_integrity_pool); 6267878cba9SMartin K. Petersen } 6277878cba9SMartin K. Petersen EXPORT_SYMBOL(bioset_integrity_free); 6287878cba9SMartin K. Petersen 6297878cba9SMartin K. Petersen void __init bio_integrity_init(void) 6307878cba9SMartin K. Petersen { 631a6e8dc46STejun Heo /* 632a6e8dc46STejun Heo * kintegrityd won't block much but may burn a lot of CPU cycles. 633a6e8dc46STejun Heo * Make it highpri CPU intensive wq with max concurrency of 1. 634a6e8dc46STejun Heo */ 635a6e8dc46STejun Heo kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM | 636a6e8dc46STejun Heo WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1); 6377878cba9SMartin K. Petersen if (!kintegrityd_wq) 6387878cba9SMartin K. Petersen panic("Failed to create kintegrityd\n"); 6397878cba9SMartin K. Petersen 6409f060e22SKent Overstreet bip_slab = kmem_cache_create("bio_integrity_payload", 6419f060e22SKent Overstreet sizeof(struct bio_integrity_payload) + 6429f060e22SKent Overstreet sizeof(struct bio_vec) * BIP_INLINE_VECS, 6439f060e22SKent Overstreet 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); 6449f060e22SKent Overstreet if (!bip_slab) 6459f060e22SKent Overstreet panic("Failed to create slab\n"); 6467878cba9SMartin K. Petersen } 647