Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: drivers/md/dm-bht.c

Issue 6896044: CHROMIUM: verity: remove special-case logic for the root node (Closed) Base URL: http://git.chromium.org/git/kernel-next.git@chromeos-2.6.38
Patch Set: Fix per review. Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | include/linux/dm-bht.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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);
OLDNEW
« no previous file with comments | « no previous file | include/linux/dm-bht.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698