| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Originally based on dm-crypt.c, | 2 * Originally based on dm-crypt.c, |
| 3 * Copyright (C) 2003 Christophe Saout <christophe@saout.de> | 3 * Copyright (C) 2003 Christophe Saout <christophe@saout.de> |
| 4 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> | 4 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> |
| 5 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. | 5 * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. |
| 6 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> | 6 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> |
| 7 * All Rights Reserved. | 7 * All Rights Reserved. |
| 8 * | 8 * |
| 9 * This file is released under the GPL. | 9 * This file is released under the GPL. |
| 10 * | 10 * |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 struct verity_stats { | 112 struct verity_stats { |
| 113 unsigned int io_queue; | 113 unsigned int io_queue; |
| 114 unsigned int verify_queue; | 114 unsigned int verify_queue; |
| 115 unsigned int average_requeues; | 115 unsigned int average_requeues; |
| 116 unsigned int total_requeues; | 116 unsigned int total_requeues; |
| 117 unsigned long long total_requests; | 117 unsigned long long total_requests; |
| 118 }; | 118 }; |
| 119 | 119 |
| 120 /* per-requested-bio private data */ | 120 /* per-requested-bio private data */ |
| 121 enum verity_io_flags { | 121 enum verity_io_flags { |
| 122 » VERITY_IOFLAGS_PENDING = 0x1,» /* pending hash read bios */ | 122 » VERITY_IOFLAGS_CLONED = 0x1,» /* original bio has been cloned */ |
| 123 » VERITY_IOFLAGS_CLONED = 0x2,» /* original bio has been cloned */ | |
| 124 }; | 123 }; |
| 125 | 124 |
| 126 struct dm_verity_io { | 125 struct dm_verity_io { |
| 127 struct dm_target *target; | 126 struct dm_target *target; |
| 128 struct bio *bio; | 127 struct bio *bio; |
| 129 struct delayed_work work; | 128 struct delayed_work work; |
| 130 unsigned int flags; | 129 unsigned int flags; |
| 131 | 130 |
| 132 int error; | 131 int error; |
| 133 atomic_t pending; | 132 atomic_t pending; |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 | 590 |
| 592 DMDEBUG("dec pending %p: %d--", io, atomic_read(&io->pending)); | 591 DMDEBUG("dec pending %p: %d--", io, atomic_read(&io->pending)); |
| 593 | 592 |
| 594 if (!atomic_dec_and_test(&io->pending)) | 593 if (!atomic_dec_and_test(&io->pending)) |
| 595 goto done; | 594 goto done; |
| 596 | 595 |
| 597 if (unlikely(io->error)) | 596 if (unlikely(io->error)) |
| 598 goto io_error; | 597 goto io_error; |
| 599 | 598 |
| 600 /* I/Os that were pending may now be ready */ | 599 /* I/Os that were pending may now be ready */ |
| 601 » if ((io->flags & VERITY_IOFLAGS_PENDING) && | 600 » if (verity_is_bht_populated(io)) { |
| 602 » !verity_is_bht_populated(io)) { | |
| 603 » » io->flags &= ~VERITY_IOFLAGS_PENDING; | |
| 604 » » INIT_DELAYED_WORK(&io->work, kverityd_io); | |
| 605 » » queue_delayed_work(vc->io_queue, &io->work, HZ/10); | |
| 606 » » verity_stats_total_requeues_inc(vc); | |
| 607 » » REQTRACE("Block %llu+ is being requeued for io (io:%p)", | |
| 608 » » » ULL(io->block), io); | |
| 609 » } else { | |
| 610 » » io->flags &= ~VERITY_IOFLAGS_PENDING; | |
| 611 verity_stats_io_queue_dec(vc); | 601 verity_stats_io_queue_dec(vc); |
| 612 verity_stats_verify_queue_inc(vc); | 602 verity_stats_verify_queue_inc(vc); |
| 613 INIT_DELAYED_WORK(&io->work, kverityd_verify); | 603 INIT_DELAYED_WORK(&io->work, kverityd_verify); |
| 614 queue_delayed_work(vc->verify_queue, &io->work, 0); | 604 queue_delayed_work(vc->verify_queue, &io->work, 0); |
| 615 REQTRACE("Block %llu+ is being queued for verify (io:%p)", | 605 REQTRACE("Block %llu+ is being queued for verify (io:%p)", |
| 616 ULL(io->block), io); | 606 ULL(io->block), io); |
| 607 } else { |
| 608 INIT_DELAYED_WORK(&io->work, kverityd_io); |
| 609 queue_delayed_work(vc->io_queue, &io->work, HZ/10); |
| 610 verity_stats_total_requeues_inc(vc); |
| 611 REQTRACE("Block %llu+ is being requeued for io (io:%p)", |
| 612 ULL(io->block), io); |
| 617 } | 613 } |
| 618 | 614 |
| 619 done: | 615 done: |
| 620 return; | 616 return; |
| 621 | 617 |
| 622 io_error: | 618 io_error: |
| 623 verity_return_bio_to_caller(io); | 619 verity_return_bio_to_caller(io); |
| 624 } | 620 } |
| 625 | 621 |
| 626 /* Walks the data set and computes the hash of the data read from the | 622 /* Walks the data set and computes the hash of the data read from the |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 */ | 774 */ |
| 779 DMDEBUG("Submitting bht io %p (entry:%p)", io, entry); | 775 DMDEBUG("Submitting bht io %p (entry:%p)", io, entry); |
| 780 generic_make_request(bio); | 776 generic_make_request(bio); |
| 781 return 0; | 777 return 0; |
| 782 } | 778 } |
| 783 | 779 |
| 784 /* Performs the work of loading in any missing bht hashes. */ | 780 /* Performs the work of loading in any missing bht hashes. */ |
| 785 static void kverityd_io_bht_populate(struct dm_verity_io *io) | 781 static void kverityd_io_bht_populate(struct dm_verity_io *io) |
| 786 { | 782 { |
| 787 struct verity_config *vc = io->target->private; | 783 struct verity_config *vc = io->target->private; |
| 788 int populated = 0; | |
| 789 int io_status = 0; | |
| 790 sector_t count; | 784 sector_t count; |
| 791 | 785 |
| 792 /* Submits an io request for each missing block of block hashes. | 786 /* Submits an io request for each missing block of block hashes. |
| 793 * The last one to return will then enqueue this on the | 787 * The last one to return will then enqueue this on the |
| 794 * io workqueue. | 788 * io workqueue. |
| 795 */ | 789 */ |
| 796 REQTRACE("populating %llu starting at block %llu (io:%p)", | 790 REQTRACE("populating %llu starting at block %llu (io:%p)", |
| 797 ULL(io->count), ULL(io->block), io); | 791 ULL(io->count), ULL(io->block), io); |
| 798 for (count = 0; count < io->count; ++count) { | 792 for (count = 0; count < io->count; ++count) { |
| 799 unsigned int block = (unsigned int)(io->block + count); | 793 unsigned int block = (unsigned int)(io->block + count); |
| 794 int populated; |
| 795 |
| 800 /* Check for truncation. */ | 796 /* Check for truncation. */ |
| 801 VERITY_BUG_ON((sector_t)(block) < io->block); | 797 VERITY_BUG_ON((sector_t)(block) < io->block); |
| 802 /* populate for each block */ | 798 /* populate for each block */ |
| 803 DMDEBUG("Calling dm_bht_populate for %u (io:%p)", block, io); | 799 DMDEBUG("Calling dm_bht_populate for %u (io:%p)", block, io); |
| 804 populated = dm_bht_populate(&vc->bht, io, block); | 800 populated = dm_bht_populate(&vc->bht, io, block); |
| 805 if (populated < 0) { | 801 if (populated < 0) { |
| 806 DMCRIT("dm_bht_populate error for block %u (io:%p): %d", | 802 DMCRIT("dm_bht_populate error for block %u (io:%p): %d", |
| 807 block, io, populated); | 803 block, io, populated); |
| 808 /* TODO(wad) support propagating transient errors | 804 /* TODO(wad) support propagating transient errors |
| 809 * cleanly. | 805 * cleanly. |
| 810 */ | 806 */ |
| 811 /* verity_dec_pending will handle the error case. */ | 807 /* verity_dec_pending will handle the error case. */ |
| 812 io->error = -EPERM; | 808 io->error = -EPERM; |
| 813 break; | 809 break; |
| 814 } | 810 } |
| 815 /* Accrue view of all I/O state for the full request */ | |
| 816 io_status |= populated; | |
| 817 } | 811 } |
| 818 REQTRACE("Block %llu+ initiated %d requests (io: %p)", | 812 REQTRACE("Block %llu+ initiated %d requests (io: %p)", |
| 819 ULL(io->block), atomic_read(&io->pending) - 1, io); | 813 ULL(io->block), atomic_read(&io->pending) - 1, io); |
| 820 | 814 |
| 821 if (io_status & DM_BHT_ENTRY_REQUESTED) { | |
| 822 /* If no data is pending another I/O request, this io | |
| 823 * will get bounced on the next queue when the last async call | |
| 824 * returns. | |
| 825 */ | |
| 826 DMDEBUG("io has outstanding requests %p"); | |
| 827 } | |
| 828 | |
| 829 /* Some I/O is pending outside of this request. */ | |
| 830 if (io_status & DM_BHT_ENTRY_PENDING) { | |
| 831 /* PENDING will cause a BHT requeue as delayed work */ | |
| 832 /* TODO(wad) add a callback to dm-bht for pending_cb. Then for | |
| 833 * each entry, the io could be delayed heavily until the end | |
| 834 * read cb requeue them. (entries could be added to the | |
| 835 * stored I/O context but races could be a challenge. | |
| 836 */ | |
| 837 DMDEBUG("io is pending %p"); | |
| 838 io->flags |= VERITY_IOFLAGS_PENDING; | |
| 839 } | |
| 840 | |
| 841 /* If I/O requests were issues on behalf of populate, then the last | 815 /* If I/O requests were issues on behalf of populate, then the last |
| 842 * request will result in a requeue. If all data was pending from | 816 * request will result in a requeue. If all data was pending from |
| 843 * other requests, this will be requeued now. | 817 * other requests, this will be requeued now. |
| 844 */ | 818 */ |
| 845 } | 819 } |
| 846 | 820 |
| 847 /* Asynchronously called upon the completion of I/O issued | 821 /* Asynchronously called upon the completion of I/O issued |
| 848 * from kverityd_src_io_read. verity_dec_pending() acts as | 822 * from kverityd_src_io_read. verity_dec_pending() acts as |
| 849 * the scheduler/flow manager. | 823 * the scheduler/flow manager. |
| 850 */ | 824 */ |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 dm_unregister_target(&verity_target); | 1309 dm_unregister_target(&verity_target); |
| 1336 kmem_cache_destroy(_verity_io_pool); | 1310 kmem_cache_destroy(_verity_io_pool); |
| 1337 } | 1311 } |
| 1338 | 1312 |
| 1339 module_init(dm_verity_init); | 1313 module_init(dm_verity_init); |
| 1340 module_exit(dm_verity_exit); | 1314 module_exit(dm_verity_exit); |
| 1341 | 1315 |
| 1342 MODULE_AUTHOR("The Chromium OS Authors <chromium-os-dev@chromium.org>"); | 1316 MODULE_AUTHOR("The Chromium OS Authors <chromium-os-dev@chromium.org>"); |
| 1343 MODULE_DESCRIPTION(DM_NAME " target for transparent disk integrity checking"); | 1317 MODULE_DESCRIPTION(DM_NAME " target for transparent disk integrity checking"); |
| 1344 MODULE_LICENSE("GPL"); | 1318 MODULE_LICENSE("GPL"); |
| OLD | NEW |