Chromium Code Reviews| 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 |