/** * bio_integrity_process - Process integrity metadata for a bio * @bio: bio to generate/verify integrity metadata for * @proc_fn: Pointer to the relevant processing function */ static int bio_integrity_process(struct bio *bio, integrity_processing_fn *proc_fn) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); struct blk_integrity_iter iter; struct bvec_iter bviter; struct bio_vec bv; struct bio_integrity_payload *bip = bio_integrity(bio); unsigned int ret = 0; void *prot_buf = page_address(bip->bip_vec->bv_page) + bip->bip_vec->bv_offset; iter.disk_name = bio->bi_bdev->bd_disk->disk_name; iter.interval = bi->interval; iter.seed = bip_get_seed(bip); iter.prot_buf = prot_buf; bio_for_each_segment(bv, bio, bviter) { void *kaddr = kmap_atomic(bv.bv_page); iter.data_buf = kaddr + bv.bv_offset; iter.data_size = bv.bv_len; ret = proc_fn(&iter); if (ret) { kunmap_atomic(kaddr); return ret; } kunmap_atomic(kaddr); }
/** * bio_integrity_generate - Generate integrity metadata for a bio * @bio: bio to generate integrity metadata for * * Description: Generates integrity metadata for a bio by calling the * block device's generation callback function. The bio must have a * bip attached with enough room to accommodate the generated * integrity metadata. */ static void bio_integrity_generate(struct bio *bio) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); struct blk_integrity_exchg bix; struct bio_vec bv; struct bvec_iter iter; sector_t sector = bio->bi_iter.bi_sector; unsigned int sectors, total; void *prot_buf = bio->bi_integrity->bip_buf; total = 0; bix.disk_name = bio->bi_bdev->bd_disk->disk_name; bix.sector_size = bi->sector_size; bio_for_each_segment(bv, bio, iter) { void *kaddr = kmap_atomic(bv.bv_page); bix.data_buf = kaddr + bv.bv_offset; bix.data_size = bv.bv_len; bix.prot_buf = prot_buf; bix.sector = sector; bi->generate_fn(&bix); sectors = bv.bv_len / bi->sector_size; sector += sectors; prot_buf += sectors * bi->tuple_size; total += sectors * bi->tuple_size; BUG_ON(total > bio->bi_integrity->bip_iter.bi_size); kunmap_atomic(kaddr); }
static int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set) { struct bio_integrity_payload *bip = bio->bi_integrity; struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); unsigned int nr_sectors; BUG_ON(bip->bip_buf == NULL); if (bi->tag_size == 0) return -1; nr_sectors = bio_integrity_hw_sectors(bi, DIV_ROUND_UP(len, bi->tag_size)); if (nr_sectors * bi->tuple_size > bip->bip_iter.bi_size) { printk(KERN_ERR "%s: tag too big for bio: %u > %u\n", __func__, nr_sectors * bi->tuple_size, bip->bip_iter.bi_size); return -1; } if (set) bi->set_tag_fn(bip->bip_buf, tag_buf, nr_sectors); else bi->get_tag_fn(bip->bip_buf, tag_buf, nr_sectors); return 0; }
/** * bio_integrity_tag_size - Retrieve integrity tag space * @bio: bio to inspect * * Description: Returns the maximum number of tag bytes that can be * attached to this bio. Filesystems can use this to determine how * much metadata to attach to an I/O. */ unsigned int bio_integrity_tag_size(struct bio *bio) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); BUG_ON(bio->bi_iter.bi_size == 0); return bi->tag_size * (bio->bi_iter.bi_size / bi->sector_size); }
static int bdev_integrity_enabled(struct block_device *bdev, int rw) { struct blk_integrity *bi = bdev_get_integrity(bdev); if (bi == NULL) return 0; if (rw == READ && bi->verify_fn != NULL && (bi->flags & INTEGRITY_FLAG_READ)) return 1; if (rw == WRITE && bi->generate_fn != NULL && (bi->flags & INTEGRITY_FLAG_WRITE)) return 1; return 0; }
/** * bio_integrity_enabled - Check whether integrity can be passed * @bio: bio to check * * Description: Determines whether bio_integrity_prep() can be called * on this bio or not. bio data direction and target device must be * set prior to calling. The functions honors the write_generate and * read_verify flags in sysfs. */ bool bio_integrity_enabled(struct bio *bio) { struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); if (!bio_is_rw(bio)) return false; /* Already protected? */ if (bio_integrity(bio)) return false; if (bi == NULL) return false; if (bio_data_dir(bio) == READ && bi->verify_fn != NULL && (bi->flags & BLK_INTEGRITY_VERIFY)) return true; if (bio_data_dir(bio) == WRITE && bi->generate_fn != NULL && (bi->flags & BLK_INTEGRITY_GENERATE)) return true; return false; }