diff options
Diffstat (limited to 'drivers/md/dm-verity.c')
-rw-r--r-- | drivers/md/dm-verity.c | 62 |
1 files changed, 19 insertions, 43 deletions
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 4b7941db3aff..796007a5e0e1 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c | |||
@@ -73,15 +73,10 @@ struct dm_verity_io { | |||
73 | sector_t block; | 73 | sector_t block; |
74 | unsigned n_blocks; | 74 | unsigned n_blocks; |
75 | 75 | ||
76 | /* saved bio vector */ | 76 | struct bvec_iter iter; |
77 | struct bio_vec *io_vec; | ||
78 | unsigned io_vec_size; | ||
79 | 77 | ||
80 | struct work_struct work; | 78 | struct work_struct work; |
81 | 79 | ||
82 | /* A space for short vectors; longer vectors are allocated separately. */ | ||
83 | struct bio_vec io_vec_inline[DM_VERITY_IO_VEC_INLINE]; | ||
84 | |||
85 | /* | 80 | /* |
86 | * Three variably-size fields follow this struct: | 81 | * Three variably-size fields follow this struct: |
87 | * | 82 | * |
@@ -284,9 +279,10 @@ release_ret_r: | |||
284 | static int verity_verify_io(struct dm_verity_io *io) | 279 | static int verity_verify_io(struct dm_verity_io *io) |
285 | { | 280 | { |
286 | struct dm_verity *v = io->v; | 281 | struct dm_verity *v = io->v; |
282 | struct bio *bio = dm_bio_from_per_bio_data(io, | ||
283 | v->ti->per_bio_data_size); | ||
287 | unsigned b; | 284 | unsigned b; |
288 | int i; | 285 | int i; |
289 | unsigned vector = 0, offset = 0; | ||
290 | 286 | ||
291 | for (b = 0; b < io->n_blocks; b++) { | 287 | for (b = 0; b < io->n_blocks; b++) { |
292 | struct shash_desc *desc; | 288 | struct shash_desc *desc; |
@@ -336,31 +332,22 @@ test_block_hash: | |||
336 | } | 332 | } |
337 | 333 | ||
338 | todo = 1 << v->data_dev_block_bits; | 334 | todo = 1 << v->data_dev_block_bits; |
339 | do { | 335 | while (io->iter.bi_size) { |
340 | struct bio_vec *bv; | ||
341 | u8 *page; | 336 | u8 *page; |
342 | unsigned len; | 337 | struct bio_vec bv = bio_iter_iovec(bio, io->iter); |
343 | 338 | ||
344 | BUG_ON(vector >= io->io_vec_size); | 339 | page = kmap_atomic(bv.bv_page); |
345 | bv = &io->io_vec[vector]; | 340 | r = crypto_shash_update(desc, page + bv.bv_offset, |
346 | page = kmap_atomic(bv->bv_page); | 341 | bv.bv_len); |
347 | len = bv->bv_len - offset; | ||
348 | if (likely(len >= todo)) | ||
349 | len = todo; | ||
350 | r = crypto_shash_update(desc, | ||
351 | page + bv->bv_offset + offset, len); | ||
352 | kunmap_atomic(page); | 342 | kunmap_atomic(page); |
343 | |||
353 | if (r < 0) { | 344 | if (r < 0) { |
354 | DMERR("crypto_shash_update failed: %d", r); | 345 | DMERR("crypto_shash_update failed: %d", r); |
355 | return r; | 346 | return r; |
356 | } | 347 | } |
357 | offset += len; | 348 | |
358 | if (likely(offset == bv->bv_len)) { | 349 | bio_advance_iter(bio, &io->iter, bv.bv_len); |
359 | offset = 0; | 350 | } |
360 | vector++; | ||
361 | } | ||
362 | todo -= len; | ||
363 | } while (todo); | ||
364 | 351 | ||
365 | if (!v->version) { | 352 | if (!v->version) { |
366 | r = crypto_shash_update(desc, v->salt, v->salt_size); | 353 | r = crypto_shash_update(desc, v->salt, v->salt_size); |
@@ -383,8 +370,6 @@ test_block_hash: | |||
383 | return -EIO; | 370 | return -EIO; |
384 | } | 371 | } |
385 | } | 372 | } |
386 | BUG_ON(vector != io->io_vec_size); | ||
387 | BUG_ON(offset); | ||
388 | 373 | ||
389 | return 0; | 374 | return 0; |
390 | } | 375 | } |
@@ -400,10 +385,7 @@ static void verity_finish_io(struct dm_verity_io *io, int error) | |||
400 | bio->bi_end_io = io->orig_bi_end_io; | 385 | bio->bi_end_io = io->orig_bi_end_io; |
401 | bio->bi_private = io->orig_bi_private; | 386 | bio->bi_private = io->orig_bi_private; |
402 | 387 | ||
403 | if (io->io_vec != io->io_vec_inline) | 388 | bio_endio_nodec(bio, error); |
404 | mempool_free(io->io_vec, v->vec_mempool); | ||
405 | |||
406 | bio_endio(bio, error); | ||
407 | } | 389 | } |
408 | 390 | ||
409 | static void verity_work(struct work_struct *w) | 391 | static void verity_work(struct work_struct *w) |
@@ -493,9 +475,9 @@ static int verity_map(struct dm_target *ti, struct bio *bio) | |||
493 | struct dm_verity_io *io; | 475 | struct dm_verity_io *io; |
494 | 476 | ||
495 | bio->bi_bdev = v->data_dev->bdev; | 477 | bio->bi_bdev = v->data_dev->bdev; |
496 | bio->bi_sector = verity_map_sector(v, bio->bi_sector); | 478 | bio->bi_iter.bi_sector = verity_map_sector(v, bio->bi_iter.bi_sector); |
497 | 479 | ||
498 | if (((unsigned)bio->bi_sector | bio_sectors(bio)) & | 480 | if (((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) & |
499 | ((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) { | 481 | ((1 << (v->data_dev_block_bits - SECTOR_SHIFT)) - 1)) { |
500 | DMERR_LIMIT("unaligned io"); | 482 | DMERR_LIMIT("unaligned io"); |
501 | return -EIO; | 483 | return -EIO; |
@@ -514,18 +496,12 @@ static int verity_map(struct dm_target *ti, struct bio *bio) | |||
514 | io->v = v; | 496 | io->v = v; |
515 | io->orig_bi_end_io = bio->bi_end_io; | 497 | io->orig_bi_end_io = bio->bi_end_io; |
516 | io->orig_bi_private = bio->bi_private; | 498 | io->orig_bi_private = bio->bi_private; |
517 | io->block = bio->bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT); | 499 | io->block = bio->bi_iter.bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT); |
518 | io->n_blocks = bio->bi_size >> v->data_dev_block_bits; | 500 | io->n_blocks = bio->bi_iter.bi_size >> v->data_dev_block_bits; |
519 | 501 | ||
520 | bio->bi_end_io = verity_end_io; | 502 | bio->bi_end_io = verity_end_io; |
521 | bio->bi_private = io; | 503 | bio->bi_private = io; |
522 | io->io_vec_size = bio_segments(bio); | 504 | io->iter = bio->bi_iter; |
523 | if (io->io_vec_size < DM_VERITY_IO_VEC_INLINE) | ||
524 | io->io_vec = io->io_vec_inline; | ||
525 | else | ||
526 | io->io_vec = mempool_alloc(v->vec_mempool, GFP_NOIO); | ||
527 | memcpy(io->io_vec, bio_iovec(bio), | ||
528 | io->io_vec_size * sizeof(struct bio_vec)); | ||
529 | 505 | ||
530 | verity_submit_prefetch(v, io); | 506 | verity_submit_prefetch(v, io); |
531 | 507 | ||