OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> | 2 * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org> |
3 * | 3 * |
4 * Device-Mapper block hash tree interface. | 4 * Device-Mapper block hash tree interface. |
5 * See Documentation/device-mapper/dm-bht.txt for details. | 5 * See Documentation/device-mapper/dm-bht.txt for details. |
6 * | 6 * |
7 * This file is released under the GPL. | 7 * This file is released under the GPL. |
8 */ | 8 */ |
9 | 9 |
10 #include <asm/atomic.h> | 10 #include <asm/atomic.h> |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 status = -EINVAL; | 234 status = -EINVAL; |
235 goto bad_digest_len; | 235 goto bad_digest_len; |
236 } | 236 } |
237 | 237 |
238 bht->root_digest = (u8 *) kzalloc(bht->digest_size, GFP_KERNEL); | 238 bht->root_digest = (u8 *) kzalloc(bht->digest_size, GFP_KERNEL); |
239 if (!bht->root_digest) { | 239 if (!bht->root_digest) { |
240 DMERR("failed to allocate memory for root digest"); | 240 DMERR("failed to allocate memory for root digest"); |
241 status = -ENOMEM; | 241 status = -ENOMEM; |
242 goto bad_root_digest_alloc; | 242 goto bad_root_digest_alloc; |
243 } | 243 } |
244 /* We use the same defines for root state but just: | |
245 * UNALLOCATED, REQUESTED, and VERIFIED since the workflow is | |
246 * different. | |
247 */ | |
248 atomic_set(&bht->root_state, DM_BHT_ENTRY_UNALLOCATED); | |
249 | 244 |
250 /* Configure the tree */ | 245 /* Configure the tree */ |
251 bht->block_count = block_count; | 246 bht->block_count = block_count; |
252 DMDEBUG("Setting block_count %u", block_count); | 247 DMDEBUG("Setting block_count %u", block_count); |
253 if (block_count == 0) { | 248 if (block_count == 0) { |
254 DMERR("block_count must be non-zero"); | 249 DMERR("block_count must be non-zero"); |
255 status = -EINVAL; | 250 status = -EINVAL; |
256 goto bad_block_count; | 251 goto bad_block_count; |
257 } | 252 } |
258 | 253 |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
526 return -ENOMEM; | 521 return -ENOMEM; |
527 | 522 |
528 | 523 |
529 } | 524 } |
530 | 525 |
531 static int dm_bht_compare_hash(struct dm_bht *bht, u8 *known, u8 *computed) | 526 static int dm_bht_compare_hash(struct dm_bht *bht, u8 *known, u8 *computed) |
532 { | 527 { |
533 return memcmp(known, computed, bht->digest_size); | 528 return memcmp(known, computed, bht->digest_size); |
534 } | 529 } |
535 | 530 |
536 static int dm_bht_update_hash(struct dm_bht *bht, u8 *known, u8 *computed) | |
537 { | |
538 #ifdef CONFIG_DM_DEBUG | |
539 u8 hex[DM_BHT_MAX_DIGEST_SIZE * 2 + 1]; | |
540 #endif | |
541 memcpy(known, computed, bht->digest_size); | |
542 #ifdef CONFIG_DM_DEBUG | |
543 dm_bht_bin_to_hex(computed, hex, bht->digest_size); | |
544 DMDEBUG("updating with hash: %s", hex); | |
545 #endif | |
546 return 0; | |
547 } | |
548 | |
549 /* Walk all entries at level 0 to compute the root digest. | |
550 * 0 on success. | |
551 */ | |
552 static int dm_bht_compute_root(struct dm_bht *bht, u8 *digest) | |
553 { | |
554 struct dm_bht_entry *entry; | |
555 unsigned int count; | |
556 struct scatterlist sg; /* feeds digest() */ | |
557 struct hash_desc *hash_desc; | |
558 hash_desc = &bht->hash_desc[smp_processor_id()]; | |
559 entry = bht->levels[0].entries; | |
560 | |
561 if (crypto_hash_init(hash_desc)) { | |
562 DMCRIT("failed to reinitialize crypto hash (proc:%d)", | |
563 smp_processor_id()); | |
564 return -EINVAL; | |
565 } | |
566 | |
567 /* Point the scatterlist to the entries, then compute the digest */ | |
568 for (count = 0; count < bht->levels[0].count; ++count, ++entry) { | |
569 if (atomic_read(&entry->state) <= DM_BHT_ENTRY_PENDING) { | |
570 DMCRIT("data not ready to compute root: %u", | |
571 count); | |
572 return 1; | |
573 } | |
574 sg_init_table(&sg, 1); | |
575 sg_set_buf(&sg, entry->nodes, PAGE_SIZE); | |
576 if (crypto_hash_update(hash_desc, &sg, PAGE_SIZE)) { | |
577 DMCRIT("Failed to update crypto hash"); | |
578 return -EINVAL; | |
579 } | |
580 } | |
581 | |
582 if (crypto_hash_final(hash_desc, digest)) { | |
583 DMCRIT("Failed to compute final digest"); | |
584 return -EINVAL; | |
585 } | |
586 | |
587 return 0; | |
588 } | |
589 | |
590 static int dm_bht_verify_root(struct dm_bht *bht, | |
591 dm_bht_compare_cb compare_cb) | |
592 { | |
593 int status = 0; | |
594 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | |
595 if (atomic_read(&bht->root_state) == DM_BHT_ENTRY_VERIFIED) | |
596 return 0; | |
597 status = dm_bht_compute_root(bht, digest); | |
598 if (status) { | |
599 DMCRIT("Failed to compute root digest for verification"); | |
600 return status; | |
601 } | |
602 DMDEBUG("root computed"); | |
603 status = compare_cb(bht, bht->root_digest, digest); | |
604 if (status) { | |
605 DMCRIT("invalid root digest: %d", status); | |
606 dm_bht_log_mismatch(bht, bht->root_digest, digest); | |
607 return DM_BHT_ENTRY_ERROR_MISMATCH; | |
608 } | |
609 /* Could do a cmpxchg, but this should be safe. */ | |
610 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED); | |
611 return 0; | |
612 } | |
613 | |
614 /* dm_bht_verify_path | 531 /* dm_bht_verify_path |
615 * Verifies the path. Returns 0 on ok. | 532 * Verifies the path. Returns 0 on ok. |
616 */ | 533 */ |
617 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, | 534 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, |
618 struct page *pg, unsigned int offset) | 535 struct page *pg, unsigned int offset) |
619 { | 536 { |
620 unsigned int depth = bht->depth; | 537 unsigned int depth = bht->depth; |
538 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | |
621 struct dm_bht_entry *entry; | 539 struct dm_bht_entry *entry; |
540 u8 *node; | |
622 int state; | 541 int state; |
623 | 542 |
624 do { | 543 do { |
625 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | |
626 u8 *node; | |
627 | |
628 /* Need to check that the hash of the current block is accurate | 544 /* Need to check that the hash of the current block is accurate |
629 * in its parent. | 545 * in its parent. |
630 */ | 546 */ |
631 entry = dm_bht_get_entry(bht, depth - 1, block_index); | 547 entry = dm_bht_get_entry(bht, depth - 1, block_index); |
632 state = atomic_read(&entry->state); | 548 state = atomic_read(&entry->state); |
633 /* This call is only safe if all nodes along the path | 549 /* This call is only safe if all nodes along the path |
634 * are already populated (i.e. READY) via dm_bht_populate. | 550 * are already populated (i.e. READY) via dm_bht_populate. |
635 */ | 551 */ |
636 BUG_ON(state < DM_BHT_ENTRY_READY); | 552 BUG_ON(state < DM_BHT_ENTRY_READY); |
637 node = dm_bht_get_node(bht, entry, depth, block_index); | 553 node = dm_bht_get_node(bht, entry, depth, block_index); |
638 | 554 |
639 if (dm_bht_compute_hash(bht, pg, offset, digest) || | 555 if (dm_bht_compute_hash(bht, pg, offset, digest) || |
640 dm_bht_compare_hash(bht, digest, node)) | 556 dm_bht_compare_hash(bht, digest, node)) |
641 goto mismatch; | 557 goto mismatch; |
642 | 558 |
643 /* Keep the containing block of hashes to be verified in the | 559 /* Keep the containing block of hashes to be verified in the |
644 * next pass. | 560 * next pass. |
645 */ | 561 */ |
646 pg = virt_to_page(entry->nodes); | 562 pg = virt_to_page(entry->nodes); |
647 offset = 0; | 563 offset = 0; |
648 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); | 564 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); |
649 | 565 |
566 if (depth == 0 && state != DM_BHT_ENTRY_VERIFIED) { | |
567 if (dm_bht_compute_hash(bht, pg, offset, digest) || | |
568 dm_bht_compare_hash(bht, digest, bht->root_digest)) | |
569 goto mismatch; | |
570 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); | |
571 } | |
572 | |
650 /* Mark path to leaf as verified. */ | 573 /* Mark path to leaf as verified. */ |
651 for (depth++; depth < bht->depth; depth++) { | 574 for (depth++; depth < bht->depth; depth++) { |
652 entry = dm_bht_get_entry(bht, depth, block_index); | 575 entry = dm_bht_get_entry(bht, depth, block_index); |
653 /* At this point, entry can only be in VERIFIED or READY state. | 576 /* At this point, entry can only be in VERIFIED or READY state. |
654 * So it is safe to use atomic_set instead of atomic_cmpxchg. | 577 * So it is safe to use atomic_set instead of atomic_cmpxchg. |
655 */ | 578 */ |
656 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); | 579 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); |
657 } | 580 } |
658 | 581 |
659 DMDEBUG("verify_path: node %u is verified to root", block_index); | 582 DMDEBUG("verify_path: node %u is verified to root", block_index); |
660 return 0; | 583 return 0; |
661 | 584 |
662 mismatch: | 585 mismatch: |
663 » DMERR("verify_path: failed to verify hash against parent (d=%u,bi=%u)", | 586 » DMERR_LIMIT("verify_path: failed to verify hash (d=%u,bi=%u)", |
664 » depth, block_index); | 587 » » depth, block_index); |
588 » dm_bht_log_mismatch(bht, node, digest); | |
665 return DM_BHT_ENTRY_ERROR_MISMATCH; | 589 return DM_BHT_ENTRY_ERROR_MISMATCH; |
666 } | 590 } |
667 | 591 |
668 /** | 592 /** |
669 * dm_bht_store_block - sets a given block's hash in the tree | 593 * dm_bht_store_block - sets a given block's hash in the tree |
670 * @bht: pointer to a dm_bht_create()d bht | 594 * @bht: pointer to a dm_bht_create()d bht |
671 * @block_index:numeric index of the block in the tree | 595 * @block_index:numeric index of the block in the tree |
672 * @digest: array of u8s containing the digest of length @bht->digest_size | 596 * @digest: array of u8s containing the digest of length @bht->digest_size |
673 * | 597 * |
674 * Returns 0 on success, >0 when data is pending, and <0 when a IO or other | 598 * Returns 0 on success, >0 when data is pending, and <0 when a IO or other |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
779 * Walks the tree and computes the hashes at each level from the | 703 * Walks the tree and computes the hashes at each level from the |
780 * hashes below. This can only be called once per tree creation | 704 * hashes below. This can only be called once per tree creation |
781 * since it will mark entries verified. Expects dm_bht_populate() to | 705 * since it will mark entries verified. Expects dm_bht_populate() to |
782 * correctly populate the tree from the read_callback_stub. | 706 * correctly populate the tree from the read_callback_stub. |
783 * | 707 * |
784 * This function should not be used when verifying the same tree and | 708 * This function should not be used when verifying the same tree and |
785 * should not be used with multiple simultaneous operators on @bht. | 709 * should not be used with multiple simultaneous operators on @bht. |
786 */ | 710 */ |
787 int dm_bht_compute(struct dm_bht *bht, void *read_cb_ctx) | 711 int dm_bht_compute(struct dm_bht *bht, void *read_cb_ctx) |
788 { | 712 { |
789 » int depth, r; | 713 » int depth, r = 0; |
790 | 714 |
791 for (depth = bht->depth - 2; depth >= 0; depth--) { | 715 for (depth = bht->depth - 2; depth >= 0; depth--) { |
792 struct dm_bht_level *level = dm_bht_get_level(bht, depth); | 716 struct dm_bht_level *level = dm_bht_get_level(bht, depth); |
793 struct dm_bht_level *child_level = level + 1; | 717 struct dm_bht_level *child_level = level + 1; |
794 struct dm_bht_entry *entry = level->entries; | 718 struct dm_bht_entry *entry = level->entries; |
795 struct dm_bht_entry *child = child_level->entries; | 719 struct dm_bht_entry *child = child_level->entries; |
796 unsigned int i, j; | 720 unsigned int i, j; |
797 | 721 |
798 for (i = 0; i < level->count; i++, entry++) { | 722 for (i = 0; i < level->count; i++, entry++) { |
799 unsigned int count = bht->node_count; | 723 unsigned int count = bht->node_count; |
(...skipping 14 matching lines...) Expand all Loading... | |
814 | 738 |
815 r = dm_bht_compute_hash(bht, pg, 0, digest); | 739 r = dm_bht_compute_hash(bht, pg, 0, digest); |
816 if (r) { | 740 if (r) { |
817 DMERR("Failed to update (d=%u,i=%u)", | 741 DMERR("Failed to update (d=%u,i=%u)", |
818 depth, i); | 742 depth, i); |
819 goto out; | 743 goto out; |
820 } | 744 } |
821 } | 745 } |
822 } | 746 } |
823 } | 747 } |
824 » /* Don't forget the root digest! */ | 748 » r = dm_bht_compute_hash(bht, |
825 » DMDEBUG("Calling verify_root with update_hash"); | 749 » » » » virt_to_page(bht->levels[0].entries->nodes), |
826 » r = dm_bht_verify_root(bht, dm_bht_update_hash); | 750 » » » » 0, bht->root_digest); |
751 » if (r) | |
752 » » DMERR("Failed to update root hash"); | |
753 | |
827 out: | 754 out: |
828 return r; | 755 return r; |
829 } | 756 } |
830 EXPORT_SYMBOL(dm_bht_compute); | 757 EXPORT_SYMBOL(dm_bht_compute); |
831 | 758 |
832 /** | 759 /** |
833 * dm_bht_sync - writes the tree in memory to disk | 760 * dm_bht_sync - writes the tree in memory to disk |
834 * @bht: pointer to a dm_bht_create()d bht | 761 * @bht: pointer to a dm_bht_create()d bht |
835 * @write_ctx: callback context for writes issued | 762 * @write_ctx: callback context for writes issued |
836 * | 763 * |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
883 * @bht: pointer to a dm_bht_create()d bht | 810 * @bht: pointer to a dm_bht_create()d bht |
884 * @block_index:specific block data is expected from | 811 * @block_index:specific block data is expected from |
885 * | 812 * |
886 * Callers may wish to call dm_bht_is_populated() when checking an io | 813 * Callers may wish to call dm_bht_is_populated() when checking an io |
887 * for which entries were already pending. | 814 * for which entries were already pending. |
888 */ | 815 */ |
889 bool dm_bht_is_populated(struct dm_bht *bht, unsigned int block_index) | 816 bool dm_bht_is_populated(struct dm_bht *bht, unsigned int block_index) |
890 { | 817 { |
891 unsigned int depth; | 818 unsigned int depth; |
892 | 819 |
893 » if (atomic_read(&bht->root_state) < DM_BHT_ENTRY_READY) | 820 » /* TODO(msb) convert depth to int and avoid ugly cast */ |
894 » » return false; | 821 » for (depth = bht->depth - 1; (int)depth >= 0; depth--) { |
895 | |
896 » for (depth = bht->depth - 1; depth > 0; depth--) { | |
897 struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth, | 822 struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth, |
898 block_index); | 823 block_index); |
899 if (atomic_read(&entry->state) < DM_BHT_ENTRY_READY) | 824 if (atomic_read(&entry->state) < DM_BHT_ENTRY_READY) |
900 return false; | 825 return false; |
901 } | 826 } |
902 | 827 |
903 return true; | 828 return true; |
904 } | 829 } |
905 EXPORT_SYMBOL(dm_bht_is_populated); | 830 EXPORT_SYMBOL(dm_bht_is_populated); |
906 | 831 |
907 /** | 832 /** |
908 * dm_bht_populate - reads entries from disk needed to verify a given block | 833 * dm_bht_populate - reads entries from disk needed to verify a given block |
909 * @bht: pointer to a dm_bht_create()d bht | 834 * @bht: pointer to a dm_bht_create()d bht |
910 * @read_cb_ctx:context used for all read_cb calls on this request | 835 * @read_cb_ctx:context used for all read_cb calls on this request |
911 * @block_index:specific block data is expected from | 836 * @block_index:specific block data is expected from |
912 * | 837 * |
913 * Callers may wish to call dm_bht_populate(0) immediately after initialization | 838 * Returns negative value on error. |
914 * to start loading in all the level[0] entries. | |
915 */ | 839 */ |
916 int dm_bht_populate(struct dm_bht *bht, void *read_cb_ctx, | 840 int dm_bht_populate(struct dm_bht *bht, void *read_cb_ctx, |
917 unsigned int block_index) | 841 unsigned int block_index) |
918 { | 842 { |
919 » unsigned int depth; | 843 » unsigned int depth, entry_index; |
920 » struct dm_bht_level *level; | 844 » int status, populated = 0; |
921 » int populated = 0; /* return value */ | |
922 » unsigned int entry_index = 0; | |
923 » int read_status = 0; | |
924 » int root_state = 0; | |
925 | 845 |
926 » if (block_index >= bht->block_count) { | 846 » BUG_ON(block_index >= bht->block_count); |
927 » » DMERR("Request to populate for invalid block: %u", | 847 |
928 » » block_index); | |
929 » » return -EIO; | |
930 » } | |
931 DMDEBUG("dm_bht_populate(%u)", block_index); | 848 DMDEBUG("dm_bht_populate(%u)", block_index); |
932 | 849 |
933 » /* Load in all of level 0 if the root is unverified */ | 850 » for (depth = 0; depth < bht->depth; ++depth) { |
934 » root_state = atomic_read(&bht->root_state); | 851 » » entry_index = dm_bht_index_at_level(bht, depth, block_index); |
935 » /* TODO(wad) create a separate io object for the root request which | 852 » » status = dm_bht_maybe_read_entry(bht, read_cb_ctx, depth, |
936 » * can continue on and be verified and stop making every request | 853 » » » » » » entry_index); |
937 » * check. | 854 » » if (status < 0) |
938 » */ | 855 » » » goto read_error; |
939 » if (root_state != DM_BHT_ENTRY_VERIFIED) { | 856 |
940 » » DMDEBUG("root data is not yet loaded"); | 857 » » /* Accrue return code flags */ |
941 » » /* If positive, it means some are pending. */ | 858 » » populated |= status; |
942 » » populated = dm_bht_maybe_read_entry(bht, read_cb_ctx, 0, 0); | |
943 » » if (populated < 0) { | |
944 » » » DMCRIT("an error occurred while reading level[0]"); | |
945 » » » /* TODO(wad) define std error codes */ | |
946 » » » return populated; | |
947 » » } | |
948 } | 859 } |
949 | 860 |
950 » for (depth = 1; depth < bht->depth; ++depth) { | 861 » return populated; |
951 » » level = dm_bht_get_level(bht, depth); | |
952 » » entry_index = dm_bht_index_at_level(bht, depth, | |
953 » » » » » » block_index); | |
954 » » DMDEBUG("populate for bi=%u on d=%d ei=%u (max=%u)", | |
955 » » » block_index, depth, entry_index, level->count); | |
956 | 862 |
957 » » /* Except for the root node case, we should only ever need | 863 read_error: |
958 » » * to load one entry along the path. | 864 » DMCRIT("failure reading entry %u depth %u", entry_index, depth); |
959 » » */ | 865 » return status; |
960 » » read_status = dm_bht_maybe_read_entry(bht, read_cb_ctx, | |
961 » » » » » » depth, entry_index); | |
962 » » if (unlikely(read_status < 0)) { | |
963 » » » DMCRIT("failure occurred reading entry %u depth %u", | |
964 » » » entry_index, depth); | |
965 » » » return read_status; | |
966 » » } | |
967 » » /* Accrue return code flags */ | |
968 » » populated |= read_status; | |
969 » } | |
970 | 866 |
971 /* All nodes are ready. The hash for the block_index can be verified */ | |
972 return populated; | |
973 } | 867 } |
974 EXPORT_SYMBOL(dm_bht_populate); | 868 EXPORT_SYMBOL(dm_bht_populate); |
975 | 869 |
976 | 870 |
977 /** | 871 /** |
978 * dm_bht_verify_block - checks that all nodes in the path for @block are valid | 872 * dm_bht_verify_block - checks that all nodes in the path for @block are valid |
979 * @bht: pointer to a dm_bht_create()d bht | 873 * @bht: pointer to a dm_bht_create()d bht |
980 * @block_index:specific block data is expected from | 874 * @block_index:specific block data is expected from |
981 * @block: virtual address of the block data in memory | 875 * @block: virtual address of the block data in memory |
982 * (must be aligned to block size) | 876 * (must be aligned to block size) |
983 * | 877 * |
984 * Returns 0 on success, 1 on missing data, and a negative error | 878 * Returns 0 on success, 1 on missing data, and a negative error |
985 * code on verification failure. All supporting functions called | 879 * code on verification failure. All supporting functions called |
986 * should return similarly. | 880 * should return similarly. |
987 */ | 881 */ |
988 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, | 882 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, |
989 struct page *pg, unsigned int offset) | 883 struct page *pg, unsigned int offset) |
990 { | 884 { |
991 int r = 0; | |
992 | |
993 BUG_ON(offset != 0); | 885 BUG_ON(offset != 0); |
994 | 886 |
995 » /* Make sure that the root has been verified */ | 887 » return dm_bht_verify_path(bht, block_index, pg, offset); |
Paul T
2011/04/26 18:29:54
Can dm_bht_verify_block go away and be replaced to
| |
996 » if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { | |
997 » » r = dm_bht_verify_root(bht, dm_bht_compare_hash); | |
998 » » if (r) { | |
999 » » » DMERR_LIMIT("Failed to verify root: %d", r); | |
1000 » » » goto out; | |
1001 » » } | |
1002 » } | |
1003 | |
1004 » /* Now check levels in between */ | |
1005 » r = dm_bht_verify_path(bht, block_index, pg, offset); | |
1006 » if (r) | |
1007 » » DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r); | |
1008 | |
1009 out: | |
1010 » return r; | |
1011 } | 888 } |
1012 EXPORT_SYMBOL(dm_bht_verify_block); | 889 EXPORT_SYMBOL(dm_bht_verify_block); |
1013 | 890 |
1014 /** | 891 /** |
1015 * dm_bht_destroy - cleans up all memory used by @bht | 892 * dm_bht_destroy - cleans up all memory used by @bht |
1016 * @bht: pointer to a dm_bht_create()d bht | 893 * @bht: pointer to a dm_bht_create()d bht |
1017 * | 894 * |
1018 * Returns 0 on success. Does not free @bht itself. | 895 * Returns 0 on success. Does not free @bht itself. |
1019 */ | 896 */ |
1020 int dm_bht_destroy(struct dm_bht *bht) | 897 int dm_bht_destroy(struct dm_bht *bht) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1112 if (strnlen((char *)hexdigest, bht->digest_size * 2) != | 989 if (strnlen((char *)hexdigest, bht->digest_size * 2) != |
1113 bht->digest_size * 2) { | 990 bht->digest_size * 2) { |
1114 DMERR("root digest length does not match hash algorithm"); | 991 DMERR("root digest length does not match hash algorithm"); |
1115 return -1; | 992 return -1; |
1116 } | 993 } |
1117 dm_bht_hex_to_bin(bht->root_digest, hexdigest, bht->digest_size); | 994 dm_bht_hex_to_bin(bht->root_digest, hexdigest, bht->digest_size); |
1118 #ifdef CONFIG_DM_DEBUG | 995 #ifdef CONFIG_DM_DEBUG |
1119 DMINFO("Set root digest to %s. Parsed as -> ", hexdigest); | 996 DMINFO("Set root digest to %s. Parsed as -> ", hexdigest); |
1120 dm_bht_log_mismatch(bht, bht->root_digest, bht->root_digest); | 997 dm_bht_log_mismatch(bht, bht->root_digest, bht->root_digest); |
1121 #endif | 998 #endif |
1122 /* Mark the root as unallocated to ensure that it transitions to | |
1123 * requested just in case the levels aren't loaded at this point. | |
1124 */ | |
1125 atomic_set(&bht->root_state, DM_BHT_ENTRY_UNALLOCATED); | |
1126 return 0; | 999 return 0; |
1127 } | 1000 } |
1128 EXPORT_SYMBOL(dm_bht_set_root_hexdigest); | 1001 EXPORT_SYMBOL(dm_bht_set_root_hexdigest); |
1129 | 1002 |
1130 /** | 1003 /** |
1131 * dm_bht_root_hexdigest - returns root digest in hex | 1004 * dm_bht_root_hexdigest - returns root digest in hex |
1132 * @bht: pointer to a dm_bht_create()d bht | 1005 * @bht: pointer to a dm_bht_create()d bht |
1133 * @hexdigest: u8 array of size @available | 1006 * @hexdigest: u8 array of size @available |
1134 * @available: must be bht->digest_size * 2 + 1 | 1007 * @available: must be bht->digest_size * 2 + 1 |
1135 */ | 1008 */ |
1136 int dm_bht_root_hexdigest(struct dm_bht *bht, u8 *hexdigest, int available) | 1009 int dm_bht_root_hexdigest(struct dm_bht *bht, u8 *hexdigest, int available) |
1137 { | 1010 { |
1138 if (available < 0 || | 1011 if (available < 0 || |
1139 ((unsigned int) available) < bht->digest_size * 2 + 1) { | 1012 ((unsigned int) available) < bht->digest_size * 2 + 1) { |
1140 DMERR("hexdigest has too few bytes available"); | 1013 DMERR("hexdigest has too few bytes available"); |
1141 return -EINVAL; | 1014 return -EINVAL; |
1142 } | 1015 } |
1143 if (!bht->root_digest) { | 1016 if (!bht->root_digest) { |
1144 DMERR("no root digest exists to export"); | 1017 DMERR("no root digest exists to export"); |
1145 if (available > 0) | 1018 if (available > 0) |
1146 *hexdigest = 0; | 1019 *hexdigest = 0; |
1147 return -1; | 1020 return -1; |
1148 } | 1021 } |
1149 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1022 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); |
1150 return 0; | 1023 return 0; |
1151 } | 1024 } |
1152 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1025 EXPORT_SYMBOL(dm_bht_root_hexdigest); |
OLD | NEW |