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 |