cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bio-integrity.c (12629B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * bio-integrity.c - bio data integrity extensions
      4 *
      5 * Copyright (C) 2007, 2008, 2009 Oracle Corporation
      6 * Written by: Martin K. Petersen <martin.petersen@oracle.com>
      7 */
      8
      9#include <linux/blk-integrity.h>
     10#include <linux/mempool.h>
     11#include <linux/export.h>
     12#include <linux/bio.h>
     13#include <linux/workqueue.h>
     14#include <linux/slab.h>
     15#include "blk.h"
     16
     17static struct kmem_cache *bip_slab;
     18static struct workqueue_struct *kintegrityd_wq;
     19
     20void blk_flush_integrity(void)
     21{
     22	flush_workqueue(kintegrityd_wq);
     23}
     24
     25static void __bio_integrity_free(struct bio_set *bs,
     26				 struct bio_integrity_payload *bip)
     27{
     28	if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
     29		if (bip->bip_vec)
     30			bvec_free(&bs->bvec_integrity_pool, bip->bip_vec,
     31				  bip->bip_max_vcnt);
     32		mempool_free(bip, &bs->bio_integrity_pool);
     33	} else {
     34		kfree(bip);
     35	}
     36}
     37
     38/**
     39 * bio_integrity_alloc - Allocate integrity payload and attach it to bio
     40 * @bio:	bio to attach integrity metadata to
     41 * @gfp_mask:	Memory allocation mask
     42 * @nr_vecs:	Number of integrity metadata scatter-gather elements
     43 *
     44 * Description: This function prepares a bio for attaching integrity
     45 * metadata.  nr_vecs specifies the maximum number of pages containing
     46 * integrity metadata that can be attached.
     47 */
     48struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
     49						  gfp_t gfp_mask,
     50						  unsigned int nr_vecs)
     51{
     52	struct bio_integrity_payload *bip;
     53	struct bio_set *bs = bio->bi_pool;
     54	unsigned inline_vecs;
     55
     56	if (WARN_ON_ONCE(bio_has_crypt_ctx(bio)))
     57		return ERR_PTR(-EOPNOTSUPP);
     58
     59	if (!bs || !mempool_initialized(&bs->bio_integrity_pool)) {
     60		bip = kmalloc(struct_size(bip, bip_inline_vecs, nr_vecs), gfp_mask);
     61		inline_vecs = nr_vecs;
     62	} else {
     63		bip = mempool_alloc(&bs->bio_integrity_pool, gfp_mask);
     64		inline_vecs = BIO_INLINE_VECS;
     65	}
     66
     67	if (unlikely(!bip))
     68		return ERR_PTR(-ENOMEM);
     69
     70	memset(bip, 0, sizeof(*bip));
     71
     72	if (nr_vecs > inline_vecs) {
     73		bip->bip_max_vcnt = nr_vecs;
     74		bip->bip_vec = bvec_alloc(&bs->bvec_integrity_pool,
     75					  &bip->bip_max_vcnt, gfp_mask);
     76		if (!bip->bip_vec)
     77			goto err;
     78	} else {
     79		bip->bip_vec = bip->bip_inline_vecs;
     80		bip->bip_max_vcnt = inline_vecs;
     81	}
     82
     83	bip->bip_bio = bio;
     84	bio->bi_integrity = bip;
     85	bio->bi_opf |= REQ_INTEGRITY;
     86
     87	return bip;
     88err:
     89	__bio_integrity_free(bs, bip);
     90	return ERR_PTR(-ENOMEM);
     91}
     92EXPORT_SYMBOL(bio_integrity_alloc);
     93
     94/**
     95 * bio_integrity_free - Free bio integrity payload
     96 * @bio:	bio containing bip to be freed
     97 *
     98 * Description: Used to free the integrity portion of a bio. Usually
     99 * called from bio_free().
    100 */
    101void bio_integrity_free(struct bio *bio)
    102{
    103	struct bio_integrity_payload *bip = bio_integrity(bio);
    104	struct bio_set *bs = bio->bi_pool;
    105
    106	if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
    107		kfree(bvec_virt(bip->bip_vec));
    108
    109	__bio_integrity_free(bs, bip);
    110	bio->bi_integrity = NULL;
    111	bio->bi_opf &= ~REQ_INTEGRITY;
    112}
    113
    114/**
    115 * bio_integrity_add_page - Attach integrity metadata
    116 * @bio:	bio to update
    117 * @page:	page containing integrity metadata
    118 * @len:	number of bytes of integrity metadata in page
    119 * @offset:	start offset within page
    120 *
    121 * Description: Attach a page containing integrity metadata to bio.
    122 */
    123int bio_integrity_add_page(struct bio *bio, struct page *page,
    124			   unsigned int len, unsigned int offset)
    125{
    126	struct bio_integrity_payload *bip = bio_integrity(bio);
    127	struct bio_vec *iv;
    128
    129	if (bip->bip_vcnt >= bip->bip_max_vcnt) {
    130		printk(KERN_ERR "%s: bip_vec full\n", __func__);
    131		return 0;
    132	}
    133
    134	iv = bip->bip_vec + bip->bip_vcnt;
    135
    136	if (bip->bip_vcnt &&
    137	    bvec_gap_to_prev(bdev_get_queue(bio->bi_bdev),
    138			     &bip->bip_vec[bip->bip_vcnt - 1], offset))
    139		return 0;
    140
    141	iv->bv_page = page;
    142	iv->bv_len = len;
    143	iv->bv_offset = offset;
    144	bip->bip_vcnt++;
    145
    146	return len;
    147}
    148EXPORT_SYMBOL(bio_integrity_add_page);
    149
    150/**
    151 * bio_integrity_process - Process integrity metadata for a bio
    152 * @bio:	bio to generate/verify integrity metadata for
    153 * @proc_iter:  iterator to process
    154 * @proc_fn:	Pointer to the relevant processing function
    155 */
    156static blk_status_t bio_integrity_process(struct bio *bio,
    157		struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn)
    158{
    159	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
    160	struct blk_integrity_iter iter;
    161	struct bvec_iter bviter;
    162	struct bio_vec bv;
    163	struct bio_integrity_payload *bip = bio_integrity(bio);
    164	blk_status_t ret = BLK_STS_OK;
    165
    166	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
    167	iter.interval = 1 << bi->interval_exp;
    168	iter.tuple_size = bi->tuple_size;
    169	iter.seed = proc_iter->bi_sector;
    170	iter.prot_buf = bvec_virt(bip->bip_vec);
    171
    172	__bio_for_each_segment(bv, bio, bviter, *proc_iter) {
    173		void *kaddr = bvec_kmap_local(&bv);
    174
    175		iter.data_buf = kaddr;
    176		iter.data_size = bv.bv_len;
    177		ret = proc_fn(&iter);
    178		kunmap_local(kaddr);
    179
    180		if (ret)
    181			break;
    182
    183	}
    184	return ret;
    185}
    186
    187/**
    188 * bio_integrity_prep - Prepare bio for integrity I/O
    189 * @bio:	bio to prepare
    190 *
    191 * Description:  Checks if the bio already has an integrity payload attached.
    192 * If it does, the payload has been generated by another kernel subsystem,
    193 * and we just pass it through. Otherwise allocates integrity payload.
    194 * The bio must have data direction, target device and start sector set priot
    195 * to calling.  In the WRITE case, integrity metadata will be generated using
    196 * the block device's integrity function.  In the READ case, the buffer
    197 * will be prepared for DMA and a suitable end_io handler set up.
    198 */
    199bool bio_integrity_prep(struct bio *bio)
    200{
    201	struct bio_integrity_payload *bip;
    202	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
    203	void *buf;
    204	unsigned long start, end;
    205	unsigned int len, nr_pages;
    206	unsigned int bytes, offset, i;
    207	unsigned int intervals;
    208	blk_status_t status;
    209
    210	if (!bi)
    211		return true;
    212
    213	if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
    214		return true;
    215
    216	if (!bio_sectors(bio))
    217		return true;
    218
    219	/* Already protected? */
    220	if (bio_integrity(bio))
    221		return true;
    222
    223	if (bio_data_dir(bio) == READ) {
    224		if (!bi->profile->verify_fn ||
    225		    !(bi->flags & BLK_INTEGRITY_VERIFY))
    226			return true;
    227	} else {
    228		if (!bi->profile->generate_fn ||
    229		    !(bi->flags & BLK_INTEGRITY_GENERATE))
    230			return true;
    231	}
    232	intervals = bio_integrity_intervals(bi, bio_sectors(bio));
    233
    234	/* Allocate kernel buffer for protection data */
    235	len = intervals * bi->tuple_size;
    236	buf = kmalloc(len, GFP_NOIO);
    237	status = BLK_STS_RESOURCE;
    238	if (unlikely(buf == NULL)) {
    239		printk(KERN_ERR "could not allocate integrity buffer\n");
    240		goto err_end_io;
    241	}
    242
    243	end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
    244	start = ((unsigned long) buf) >> PAGE_SHIFT;
    245	nr_pages = end - start;
    246
    247	/* Allocate bio integrity payload and integrity vectors */
    248	bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
    249	if (IS_ERR(bip)) {
    250		printk(KERN_ERR "could not allocate data integrity bioset\n");
    251		kfree(buf);
    252		status = BLK_STS_RESOURCE;
    253		goto err_end_io;
    254	}
    255
    256	bip->bip_flags |= BIP_BLOCK_INTEGRITY;
    257	bip->bip_iter.bi_size = len;
    258	bip_set_seed(bip, bio->bi_iter.bi_sector);
    259
    260	if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM)
    261		bip->bip_flags |= BIP_IP_CHECKSUM;
    262
    263	/* Map it */
    264	offset = offset_in_page(buf);
    265	for (i = 0 ; i < nr_pages ; i++) {
    266		int ret;
    267		bytes = PAGE_SIZE - offset;
    268
    269		if (len <= 0)
    270			break;
    271
    272		if (bytes > len)
    273			bytes = len;
    274
    275		ret = bio_integrity_add_page(bio, virt_to_page(buf),
    276					     bytes, offset);
    277
    278		if (ret == 0) {
    279			printk(KERN_ERR "could not attach integrity payload\n");
    280			status = BLK_STS_RESOURCE;
    281			goto err_end_io;
    282		}
    283
    284		if (ret < bytes)
    285			break;
    286
    287		buf += bytes;
    288		len -= bytes;
    289		offset = 0;
    290	}
    291
    292	/* Auto-generate integrity metadata if this is a write */
    293	if (bio_data_dir(bio) == WRITE) {
    294		bio_integrity_process(bio, &bio->bi_iter,
    295				      bi->profile->generate_fn);
    296	} else {
    297		bip->bio_iter = bio->bi_iter;
    298	}
    299	return true;
    300
    301err_end_io:
    302	bio->bi_status = status;
    303	bio_endio(bio);
    304	return false;
    305
    306}
    307EXPORT_SYMBOL(bio_integrity_prep);
    308
    309/**
    310 * bio_integrity_verify_fn - Integrity I/O completion worker
    311 * @work:	Work struct stored in bio to be verified
    312 *
    313 * Description: This workqueue function is called to complete a READ
    314 * request.  The function verifies the transferred integrity metadata
    315 * and then calls the original bio end_io function.
    316 */
    317static void bio_integrity_verify_fn(struct work_struct *work)
    318{
    319	struct bio_integrity_payload *bip =
    320		container_of(work, struct bio_integrity_payload, bip_work);
    321	struct bio *bio = bip->bip_bio;
    322	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
    323
    324	/*
    325	 * At the moment verify is called bio's iterator was advanced
    326	 * during split and completion, we need to rewind iterator to
    327	 * it's original position.
    328	 */
    329	bio->bi_status = bio_integrity_process(bio, &bip->bio_iter,
    330						bi->profile->verify_fn);
    331	bio_integrity_free(bio);
    332	bio_endio(bio);
    333}
    334
    335/**
    336 * __bio_integrity_endio - Integrity I/O completion function
    337 * @bio:	Protected bio
    338 *
    339 * Description: Completion for integrity I/O
    340 *
    341 * Normally I/O completion is done in interrupt context.  However,
    342 * verifying I/O integrity is a time-consuming task which must be run
    343 * in process context.	This function postpones completion
    344 * accordingly.
    345 */
    346bool __bio_integrity_endio(struct bio *bio)
    347{
    348	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
    349	struct bio_integrity_payload *bip = bio_integrity(bio);
    350
    351	if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
    352	    (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->profile->verify_fn) {
    353		INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
    354		queue_work(kintegrityd_wq, &bip->bip_work);
    355		return false;
    356	}
    357
    358	bio_integrity_free(bio);
    359	return true;
    360}
    361
    362/**
    363 * bio_integrity_advance - Advance integrity vector
    364 * @bio:	bio whose integrity vector to update
    365 * @bytes_done:	number of data bytes that have been completed
    366 *
    367 * Description: This function calculates how many integrity bytes the
    368 * number of completed data bytes correspond to and advances the
    369 * integrity vector accordingly.
    370 */
    371void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
    372{
    373	struct bio_integrity_payload *bip = bio_integrity(bio);
    374	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
    375	unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
    376
    377	bip->bip_iter.bi_sector += bio_integrity_intervals(bi, bytes_done >> 9);
    378	bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
    379}
    380
    381/**
    382 * bio_integrity_trim - Trim integrity vector
    383 * @bio:	bio whose integrity vector to update
    384 *
    385 * Description: Used to trim the integrity vector in a cloned bio.
    386 */
    387void bio_integrity_trim(struct bio *bio)
    388{
    389	struct bio_integrity_payload *bip = bio_integrity(bio);
    390	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
    391
    392	bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio));
    393}
    394EXPORT_SYMBOL(bio_integrity_trim);
    395
    396/**
    397 * bio_integrity_clone - Callback for cloning bios with integrity metadata
    398 * @bio:	New bio
    399 * @bio_src:	Original bio
    400 * @gfp_mask:	Memory allocation mask
    401 *
    402 * Description:	Called to allocate a bip when cloning a bio
    403 */
    404int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
    405			gfp_t gfp_mask)
    406{
    407	struct bio_integrity_payload *bip_src = bio_integrity(bio_src);
    408	struct bio_integrity_payload *bip;
    409
    410	BUG_ON(bip_src == NULL);
    411
    412	bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
    413	if (IS_ERR(bip))
    414		return PTR_ERR(bip);
    415
    416	memcpy(bip->bip_vec, bip_src->bip_vec,
    417	       bip_src->bip_vcnt * sizeof(struct bio_vec));
    418
    419	bip->bip_vcnt = bip_src->bip_vcnt;
    420	bip->bip_iter = bip_src->bip_iter;
    421
    422	return 0;
    423}
    424
    425int bioset_integrity_create(struct bio_set *bs, int pool_size)
    426{
    427	if (mempool_initialized(&bs->bio_integrity_pool))
    428		return 0;
    429
    430	if (mempool_init_slab_pool(&bs->bio_integrity_pool,
    431				   pool_size, bip_slab))
    432		return -1;
    433
    434	if (biovec_init_pool(&bs->bvec_integrity_pool, pool_size)) {
    435		mempool_exit(&bs->bio_integrity_pool);
    436		return -1;
    437	}
    438
    439	return 0;
    440}
    441EXPORT_SYMBOL(bioset_integrity_create);
    442
    443void bioset_integrity_free(struct bio_set *bs)
    444{
    445	mempool_exit(&bs->bio_integrity_pool);
    446	mempool_exit(&bs->bvec_integrity_pool);
    447}
    448
    449void __init bio_integrity_init(void)
    450{
    451	/*
    452	 * kintegrityd won't block much but may burn a lot of CPU cycles.
    453	 * Make it highpri CPU intensive wq with max concurrency of 1.
    454	 */
    455	kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM |
    456					 WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
    457	if (!kintegrityd_wq)
    458		panic("Failed to create kintegrityd\n");
    459
    460	bip_slab = kmem_cache_create("bio_integrity_payload",
    461				     sizeof(struct bio_integrity_payload) +
    462				     sizeof(struct bio_vec) * BIO_INLINE_VECS,
    463				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
    464}