162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * bio-integrity.c - bio data integrity extensions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2007, 2008, 2009 Oracle Corporation 662306a36Sopenharmony_ci * Written by: Martin K. Petersen <martin.petersen@oracle.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/blk-integrity.h> 1062306a36Sopenharmony_ci#include <linux/mempool.h> 1162306a36Sopenharmony_ci#include <linux/export.h> 1262306a36Sopenharmony_ci#include <linux/bio.h> 1362306a36Sopenharmony_ci#include <linux/workqueue.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include "blk.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic struct kmem_cache *bip_slab; 1862306a36Sopenharmony_cistatic struct workqueue_struct *kintegrityd_wq; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_civoid blk_flush_integrity(void) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci flush_workqueue(kintegrityd_wq); 2362306a36Sopenharmony_ci} 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic void __bio_integrity_free(struct bio_set *bs, 2662306a36Sopenharmony_ci struct bio_integrity_payload *bip) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci if (bs && mempool_initialized(&bs->bio_integrity_pool)) { 2962306a36Sopenharmony_ci if (bip->bip_vec) 3062306a36Sopenharmony_ci bvec_free(&bs->bvec_integrity_pool, bip->bip_vec, 3162306a36Sopenharmony_ci bip->bip_max_vcnt); 3262306a36Sopenharmony_ci mempool_free(bip, &bs->bio_integrity_pool); 3362306a36Sopenharmony_ci } else { 3462306a36Sopenharmony_ci kfree(bip); 3562306a36Sopenharmony_ci } 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/** 3962306a36Sopenharmony_ci * bio_integrity_alloc - Allocate integrity payload and attach it to bio 4062306a36Sopenharmony_ci * @bio: bio to attach integrity metadata to 4162306a36Sopenharmony_ci * @gfp_mask: Memory allocation mask 4262306a36Sopenharmony_ci * @nr_vecs: Number of integrity metadata scatter-gather elements 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Description: This function prepares a bio for attaching integrity 4562306a36Sopenharmony_ci * metadata. nr_vecs specifies the maximum number of pages containing 4662306a36Sopenharmony_ci * integrity metadata that can be attached. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_cistruct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, 4962306a36Sopenharmony_ci gfp_t gfp_mask, 5062306a36Sopenharmony_ci unsigned int nr_vecs) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct bio_integrity_payload *bip; 5362306a36Sopenharmony_ci struct bio_set *bs = bio->bi_pool; 5462306a36Sopenharmony_ci unsigned inline_vecs; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (WARN_ON_ONCE(bio_has_crypt_ctx(bio))) 5762306a36Sopenharmony_ci return ERR_PTR(-EOPNOTSUPP); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (!bs || !mempool_initialized(&bs->bio_integrity_pool)) { 6062306a36Sopenharmony_ci bip = kmalloc(struct_size(bip, bip_inline_vecs, nr_vecs), gfp_mask); 6162306a36Sopenharmony_ci inline_vecs = nr_vecs; 6262306a36Sopenharmony_ci } else { 6362306a36Sopenharmony_ci bip = mempool_alloc(&bs->bio_integrity_pool, gfp_mask); 6462306a36Sopenharmony_ci inline_vecs = BIO_INLINE_VECS; 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (unlikely(!bip)) 6862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci memset(bip, 0, sizeof(*bip)); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if (nr_vecs > inline_vecs) { 7362306a36Sopenharmony_ci bip->bip_max_vcnt = nr_vecs; 7462306a36Sopenharmony_ci bip->bip_vec = bvec_alloc(&bs->bvec_integrity_pool, 7562306a36Sopenharmony_ci &bip->bip_max_vcnt, gfp_mask); 7662306a36Sopenharmony_ci if (!bip->bip_vec) 7762306a36Sopenharmony_ci goto err; 7862306a36Sopenharmony_ci } else { 7962306a36Sopenharmony_ci bip->bip_vec = bip->bip_inline_vecs; 8062306a36Sopenharmony_ci bip->bip_max_vcnt = inline_vecs; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci bip->bip_bio = bio; 8462306a36Sopenharmony_ci bio->bi_integrity = bip; 8562306a36Sopenharmony_ci bio->bi_opf |= REQ_INTEGRITY; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci return bip; 8862306a36Sopenharmony_cierr: 8962306a36Sopenharmony_ci __bio_integrity_free(bs, bip); 9062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ciEXPORT_SYMBOL(bio_integrity_alloc); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/** 9562306a36Sopenharmony_ci * bio_integrity_free - Free bio integrity payload 9662306a36Sopenharmony_ci * @bio: bio containing bip to be freed 9762306a36Sopenharmony_ci * 9862306a36Sopenharmony_ci * Description: Used to free the integrity portion of a bio. Usually 9962306a36Sopenharmony_ci * called from bio_free(). 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_civoid bio_integrity_free(struct bio *bio) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci struct bio_integrity_payload *bip = bio_integrity(bio); 10462306a36Sopenharmony_ci struct bio_set *bs = bio->bi_pool; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (bip->bip_flags & BIP_BLOCK_INTEGRITY) 10762306a36Sopenharmony_ci kfree(bvec_virt(bip->bip_vec)); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci __bio_integrity_free(bs, bip); 11062306a36Sopenharmony_ci bio->bi_integrity = NULL; 11162306a36Sopenharmony_ci bio->bi_opf &= ~REQ_INTEGRITY; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * bio_integrity_add_page - Attach integrity metadata 11662306a36Sopenharmony_ci * @bio: bio to update 11762306a36Sopenharmony_ci * @page: page containing integrity metadata 11862306a36Sopenharmony_ci * @len: number of bytes of integrity metadata in page 11962306a36Sopenharmony_ci * @offset: start offset within page 12062306a36Sopenharmony_ci * 12162306a36Sopenharmony_ci * Description: Attach a page containing integrity metadata to bio. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ciint bio_integrity_add_page(struct bio *bio, struct page *page, 12462306a36Sopenharmony_ci unsigned int len, unsigned int offset) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct request_queue *q = bdev_get_queue(bio->bi_bdev); 12762306a36Sopenharmony_ci struct bio_integrity_payload *bip = bio_integrity(bio); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (((bip->bip_iter.bi_size + len) >> SECTOR_SHIFT) > 13062306a36Sopenharmony_ci queue_max_hw_sectors(q)) 13162306a36Sopenharmony_ci return 0; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (bip->bip_vcnt > 0) { 13462306a36Sopenharmony_ci struct bio_vec *bv = &bip->bip_vec[bip->bip_vcnt - 1]; 13562306a36Sopenharmony_ci bool same_page = false; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (bvec_try_merge_hw_page(q, bv, page, len, offset, 13862306a36Sopenharmony_ci &same_page)) { 13962306a36Sopenharmony_ci bip->bip_iter.bi_size += len; 14062306a36Sopenharmony_ci return len; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (bip->bip_vcnt >= 14462306a36Sopenharmony_ci min(bip->bip_max_vcnt, queue_max_integrity_segments(q))) 14562306a36Sopenharmony_ci return 0; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* 14862306a36Sopenharmony_ci * If the queue doesn't support SG gaps and adding this segment 14962306a36Sopenharmony_ci * would create a gap, disallow it. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci if (bvec_gap_to_prev(&q->limits, bv, offset)) 15262306a36Sopenharmony_ci return 0; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci bvec_set_page(&bip->bip_vec[bip->bip_vcnt], page, len, offset); 15662306a36Sopenharmony_ci bip->bip_vcnt++; 15762306a36Sopenharmony_ci bip->bip_iter.bi_size += len; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci return len; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ciEXPORT_SYMBOL(bio_integrity_add_page); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci/** 16462306a36Sopenharmony_ci * bio_integrity_process - Process integrity metadata for a bio 16562306a36Sopenharmony_ci * @bio: bio to generate/verify integrity metadata for 16662306a36Sopenharmony_ci * @proc_iter: iterator to process 16762306a36Sopenharmony_ci * @proc_fn: Pointer to the relevant processing function 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_cistatic blk_status_t bio_integrity_process(struct bio *bio, 17062306a36Sopenharmony_ci struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 17362306a36Sopenharmony_ci struct blk_integrity_iter iter; 17462306a36Sopenharmony_ci struct bvec_iter bviter; 17562306a36Sopenharmony_ci struct bio_vec bv; 17662306a36Sopenharmony_ci struct bio_integrity_payload *bip = bio_integrity(bio); 17762306a36Sopenharmony_ci blk_status_t ret = BLK_STS_OK; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci iter.disk_name = bio->bi_bdev->bd_disk->disk_name; 18062306a36Sopenharmony_ci iter.interval = 1 << bi->interval_exp; 18162306a36Sopenharmony_ci iter.tuple_size = bi->tuple_size; 18262306a36Sopenharmony_ci iter.seed = proc_iter->bi_sector; 18362306a36Sopenharmony_ci iter.prot_buf = bvec_virt(bip->bip_vec); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci __bio_for_each_segment(bv, bio, bviter, *proc_iter) { 18662306a36Sopenharmony_ci void *kaddr = bvec_kmap_local(&bv); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci iter.data_buf = kaddr; 18962306a36Sopenharmony_ci iter.data_size = bv.bv_len; 19062306a36Sopenharmony_ci ret = proc_fn(&iter); 19162306a36Sopenharmony_ci kunmap_local(kaddr); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (ret) 19462306a36Sopenharmony_ci break; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci return ret; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/** 20162306a36Sopenharmony_ci * bio_integrity_prep - Prepare bio for integrity I/O 20262306a36Sopenharmony_ci * @bio: bio to prepare 20362306a36Sopenharmony_ci * 20462306a36Sopenharmony_ci * Description: Checks if the bio already has an integrity payload attached. 20562306a36Sopenharmony_ci * If it does, the payload has been generated by another kernel subsystem, 20662306a36Sopenharmony_ci * and we just pass it through. Otherwise allocates integrity payload. 20762306a36Sopenharmony_ci * The bio must have data direction, target device and start sector set priot 20862306a36Sopenharmony_ci * to calling. In the WRITE case, integrity metadata will be generated using 20962306a36Sopenharmony_ci * the block device's integrity function. In the READ case, the buffer 21062306a36Sopenharmony_ci * will be prepared for DMA and a suitable end_io handler set up. 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_cibool bio_integrity_prep(struct bio *bio) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct bio_integrity_payload *bip; 21562306a36Sopenharmony_ci struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 21662306a36Sopenharmony_ci void *buf; 21762306a36Sopenharmony_ci unsigned long start, end; 21862306a36Sopenharmony_ci unsigned int len, nr_pages; 21962306a36Sopenharmony_ci unsigned int bytes, offset, i; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (!bi) 22262306a36Sopenharmony_ci return true; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE) 22562306a36Sopenharmony_ci return true; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (!bio_sectors(bio)) 22862306a36Sopenharmony_ci return true; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci /* Already protected? */ 23162306a36Sopenharmony_ci if (bio_integrity(bio)) 23262306a36Sopenharmony_ci return true; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (bio_data_dir(bio) == READ) { 23562306a36Sopenharmony_ci if (!bi->profile->verify_fn || 23662306a36Sopenharmony_ci !(bi->flags & BLK_INTEGRITY_VERIFY)) 23762306a36Sopenharmony_ci return true; 23862306a36Sopenharmony_ci } else { 23962306a36Sopenharmony_ci if (!bi->profile->generate_fn || 24062306a36Sopenharmony_ci !(bi->flags & BLK_INTEGRITY_GENERATE)) 24162306a36Sopenharmony_ci return true; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Allocate kernel buffer for protection data */ 24562306a36Sopenharmony_ci len = bio_integrity_bytes(bi, bio_sectors(bio)); 24662306a36Sopenharmony_ci buf = kmalloc(len, GFP_NOIO); 24762306a36Sopenharmony_ci if (unlikely(buf == NULL)) { 24862306a36Sopenharmony_ci printk(KERN_ERR "could not allocate integrity buffer\n"); 24962306a36Sopenharmony_ci goto err_end_io; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT; 25362306a36Sopenharmony_ci start = ((unsigned long) buf) >> PAGE_SHIFT; 25462306a36Sopenharmony_ci nr_pages = end - start; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Allocate bio integrity payload and integrity vectors */ 25762306a36Sopenharmony_ci bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages); 25862306a36Sopenharmony_ci if (IS_ERR(bip)) { 25962306a36Sopenharmony_ci printk(KERN_ERR "could not allocate data integrity bioset\n"); 26062306a36Sopenharmony_ci kfree(buf); 26162306a36Sopenharmony_ci goto err_end_io; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci bip->bip_flags |= BIP_BLOCK_INTEGRITY; 26562306a36Sopenharmony_ci bip_set_seed(bip, bio->bi_iter.bi_sector); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM) 26862306a36Sopenharmony_ci bip->bip_flags |= BIP_IP_CHECKSUM; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* Map it */ 27162306a36Sopenharmony_ci offset = offset_in_page(buf); 27262306a36Sopenharmony_ci for (i = 0; i < nr_pages && len > 0; i++) { 27362306a36Sopenharmony_ci bytes = PAGE_SIZE - offset; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (bytes > len) 27662306a36Sopenharmony_ci bytes = len; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (bio_integrity_add_page(bio, virt_to_page(buf), 27962306a36Sopenharmony_ci bytes, offset) < bytes) { 28062306a36Sopenharmony_ci printk(KERN_ERR "could not attach integrity payload\n"); 28162306a36Sopenharmony_ci goto err_end_io; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci buf += bytes; 28562306a36Sopenharmony_ci len -= bytes; 28662306a36Sopenharmony_ci offset = 0; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci /* Auto-generate integrity metadata if this is a write */ 29062306a36Sopenharmony_ci if (bio_data_dir(bio) == WRITE) { 29162306a36Sopenharmony_ci bio_integrity_process(bio, &bio->bi_iter, 29262306a36Sopenharmony_ci bi->profile->generate_fn); 29362306a36Sopenharmony_ci } else { 29462306a36Sopenharmony_ci bip->bio_iter = bio->bi_iter; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci return true; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cierr_end_io: 29962306a36Sopenharmony_ci bio->bi_status = BLK_STS_RESOURCE; 30062306a36Sopenharmony_ci bio_endio(bio); 30162306a36Sopenharmony_ci return false; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ciEXPORT_SYMBOL(bio_integrity_prep); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci/** 30662306a36Sopenharmony_ci * bio_integrity_verify_fn - Integrity I/O completion worker 30762306a36Sopenharmony_ci * @work: Work struct stored in bio to be verified 30862306a36Sopenharmony_ci * 30962306a36Sopenharmony_ci * Description: This workqueue function is called to complete a READ 31062306a36Sopenharmony_ci * request. The function verifies the transferred integrity metadata 31162306a36Sopenharmony_ci * and then calls the original bio end_io function. 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_cistatic void bio_integrity_verify_fn(struct work_struct *work) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci struct bio_integrity_payload *bip = 31662306a36Sopenharmony_ci container_of(work, struct bio_integrity_payload, bip_work); 31762306a36Sopenharmony_ci struct bio *bio = bip->bip_bio; 31862306a36Sopenharmony_ci struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* 32162306a36Sopenharmony_ci * At the moment verify is called bio's iterator was advanced 32262306a36Sopenharmony_ci * during split and completion, we need to rewind iterator to 32362306a36Sopenharmony_ci * it's original position. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_ci bio->bi_status = bio_integrity_process(bio, &bip->bio_iter, 32662306a36Sopenharmony_ci bi->profile->verify_fn); 32762306a36Sopenharmony_ci bio_integrity_free(bio); 32862306a36Sopenharmony_ci bio_endio(bio); 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci/** 33262306a36Sopenharmony_ci * __bio_integrity_endio - Integrity I/O completion function 33362306a36Sopenharmony_ci * @bio: Protected bio 33462306a36Sopenharmony_ci * 33562306a36Sopenharmony_ci * Description: Completion for integrity I/O 33662306a36Sopenharmony_ci * 33762306a36Sopenharmony_ci * Normally I/O completion is done in interrupt context. However, 33862306a36Sopenharmony_ci * verifying I/O integrity is a time-consuming task which must be run 33962306a36Sopenharmony_ci * in process context. This function postpones completion 34062306a36Sopenharmony_ci * accordingly. 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_cibool __bio_integrity_endio(struct bio *bio) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 34562306a36Sopenharmony_ci struct bio_integrity_payload *bip = bio_integrity(bio); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (bio_op(bio) == REQ_OP_READ && !bio->bi_status && 34862306a36Sopenharmony_ci (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->profile->verify_fn) { 34962306a36Sopenharmony_ci INIT_WORK(&bip->bip_work, bio_integrity_verify_fn); 35062306a36Sopenharmony_ci queue_work(kintegrityd_wq, &bip->bip_work); 35162306a36Sopenharmony_ci return false; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci bio_integrity_free(bio); 35562306a36Sopenharmony_ci return true; 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci/** 35962306a36Sopenharmony_ci * bio_integrity_advance - Advance integrity vector 36062306a36Sopenharmony_ci * @bio: bio whose integrity vector to update 36162306a36Sopenharmony_ci * @bytes_done: number of data bytes that have been completed 36262306a36Sopenharmony_ci * 36362306a36Sopenharmony_ci * Description: This function calculates how many integrity bytes the 36462306a36Sopenharmony_ci * number of completed data bytes correspond to and advances the 36562306a36Sopenharmony_ci * integrity vector accordingly. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_civoid bio_integrity_advance(struct bio *bio, unsigned int bytes_done) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct bio_integrity_payload *bip = bio_integrity(bio); 37062306a36Sopenharmony_ci struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 37162306a36Sopenharmony_ci unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci bip->bip_iter.bi_sector += bio_integrity_intervals(bi, bytes_done >> 9); 37462306a36Sopenharmony_ci bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci/** 37862306a36Sopenharmony_ci * bio_integrity_trim - Trim integrity vector 37962306a36Sopenharmony_ci * @bio: bio whose integrity vector to update 38062306a36Sopenharmony_ci * 38162306a36Sopenharmony_ci * Description: Used to trim the integrity vector in a cloned bio. 38262306a36Sopenharmony_ci */ 38362306a36Sopenharmony_civoid bio_integrity_trim(struct bio *bio) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci struct bio_integrity_payload *bip = bio_integrity(bio); 38662306a36Sopenharmony_ci struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio)); 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ciEXPORT_SYMBOL(bio_integrity_trim); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci/** 39362306a36Sopenharmony_ci * bio_integrity_clone - Callback for cloning bios with integrity metadata 39462306a36Sopenharmony_ci * @bio: New bio 39562306a36Sopenharmony_ci * @bio_src: Original bio 39662306a36Sopenharmony_ci * @gfp_mask: Memory allocation mask 39762306a36Sopenharmony_ci * 39862306a36Sopenharmony_ci * Description: Called to allocate a bip when cloning a bio 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ciint bio_integrity_clone(struct bio *bio, struct bio *bio_src, 40162306a36Sopenharmony_ci gfp_t gfp_mask) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct bio_integrity_payload *bip_src = bio_integrity(bio_src); 40462306a36Sopenharmony_ci struct bio_integrity_payload *bip; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci BUG_ON(bip_src == NULL); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt); 40962306a36Sopenharmony_ci if (IS_ERR(bip)) 41062306a36Sopenharmony_ci return PTR_ERR(bip); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci memcpy(bip->bip_vec, bip_src->bip_vec, 41362306a36Sopenharmony_ci bip_src->bip_vcnt * sizeof(struct bio_vec)); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci bip->bip_vcnt = bip_src->bip_vcnt; 41662306a36Sopenharmony_ci bip->bip_iter = bip_src->bip_iter; 41762306a36Sopenharmony_ci bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci return 0; 42062306a36Sopenharmony_ci} 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ciint bioset_integrity_create(struct bio_set *bs, int pool_size) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci if (mempool_initialized(&bs->bio_integrity_pool)) 42562306a36Sopenharmony_ci return 0; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci if (mempool_init_slab_pool(&bs->bio_integrity_pool, 42862306a36Sopenharmony_ci pool_size, bip_slab)) 42962306a36Sopenharmony_ci return -1; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (biovec_init_pool(&bs->bvec_integrity_pool, pool_size)) { 43262306a36Sopenharmony_ci mempool_exit(&bs->bio_integrity_pool); 43362306a36Sopenharmony_ci return -1; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci return 0; 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ciEXPORT_SYMBOL(bioset_integrity_create); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_civoid bioset_integrity_free(struct bio_set *bs) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci mempool_exit(&bs->bio_integrity_pool); 44362306a36Sopenharmony_ci mempool_exit(&bs->bvec_integrity_pool); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_civoid __init bio_integrity_init(void) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci /* 44962306a36Sopenharmony_ci * kintegrityd won't block much but may burn a lot of CPU cycles. 45062306a36Sopenharmony_ci * Make it highpri CPU intensive wq with max concurrency of 1. 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM | 45362306a36Sopenharmony_ci WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1); 45462306a36Sopenharmony_ci if (!kintegrityd_wq) 45562306a36Sopenharmony_ci panic("Failed to create kintegrityd\n"); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci bip_slab = kmem_cache_create("bio_integrity_payload", 45862306a36Sopenharmony_ci sizeof(struct bio_integrity_payload) + 45962306a36Sopenharmony_ci sizeof(struct bio_vec) * BIO_INLINE_VECS, 46062306a36Sopenharmony_ci 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); 46162306a36Sopenharmony_ci} 462