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 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 684 struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth, block_index); | 684 struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth, block_index); |
| 685 | 685 |
| 686 while (depth > 0) { | 686 while (depth > 0) { |
| 687 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | 687 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
| 688 struct dm_bht_entry *parent; | 688 struct dm_bht_entry *parent; |
| 689 struct page *page; | 689 struct page *page; |
| 690 u8 *node; | 690 u8 *node; |
| 691 int state; | 691 int state; |
| 692 | 692 |
| 693 DMDEBUG("verify_path for b=%u on d=%d", block_index, depth); | 693 DMDEBUG("verify_path for b=%u on d=%d", block_index, depth); |
| 694 /* TODO(msb,wad): would be nice to avoid two atomic reads */ | |
|
Paul T
2011/03/23 17:19:28
I'd like to understand this comment better. From w
| |
| 694 state = atomic_read(&entry->state); | 695 state = atomic_read(&entry->state); |
| 695 if (state == DM_BHT_ENTRY_VERIFIED) { | 696 if (state == DM_BHT_ENTRY_VERIFIED) { |
| 696 » » » DMDEBUG("verify_path node %u is verified in parent", | 697 » » » DMDEBUG("verify_path node %u is verified to root", |
| 697 block_index); | 698 block_index); |
| 698 » » » entry = dm_bht_get_entry(bht, --depth, block_index); | 699 » » » depth++; /* avoid an extra cmpxchg */ |
| 699 » » » continue; | 700 » » » break; |
| 700 } else if (state <= DM_BHT_ENTRY_ERROR) { | 701 } else if (state <= DM_BHT_ENTRY_ERROR) { |
| 701 DMCRIT("entry(d=%u,b=%u) is in an error state: %d", | 702 DMCRIT("entry(d=%u,b=%u) is in an error state: %d", |
| 702 depth, block_index, state); | 703 depth, block_index, state); |
| 703 DMCRIT("verification is not possible"); | 704 DMCRIT("verification is not possible"); |
| 704 goto mismatch; | 705 goto mismatch; |
| 705 } else if (state <= DM_BHT_ENTRY_PENDING) { | 706 } else if (state <= DM_BHT_ENTRY_PENDING) { |
| 706 DMERR("entry not ready for verify: d=%u,b=%u", | 707 DMERR("entry not ready for verify: d=%u,b=%u", |
| 707 depth, block_index); | 708 depth, block_index); |
| 708 goto mismatch; | 709 goto mismatch; |
| 709 } | 710 } |
| 710 | 711 |
| 711 /* We need to check that this entry matches the expected | 712 /* We need to check that this entry matches the expected |
| 712 * hash in the parent->nodes. | 713 * hash in the parent->nodes. |
| 713 */ | 714 */ |
| 714 parent = dm_bht_get_entry(bht, depth - 1, block_index); | 715 parent = dm_bht_get_entry(bht, depth - 1, block_index); |
| 715 /* This call is only safe if all nodes along the path | 716 /* This call is only safe if all nodes along the path |
| 716 * are already populated (i.e. READY) via dm_bht_populate. | 717 * are already populated (i.e. READY) via dm_bht_populate. |
| 717 */ | 718 */ |
| 718 BUG_ON(atomic_read(&parent->state) < DM_BHT_ENTRY_READY); | 719 BUG_ON(atomic_read(&parent->state) < DM_BHT_ENTRY_READY); |
| 719 node = dm_bht_get_node(bht, parent, depth, block_index); | 720 node = dm_bht_get_node(bht, parent, depth, block_index); |
| 720 page = virt_to_page(entry->nodes); | 721 page = virt_to_page(entry->nodes); |
| 721 | 722 |
| 722 if (dm_bht_compute_hash(bht, page, digest) || | 723 if (dm_bht_compute_hash(bht, page, digest) || |
| 723 dm_bht_compare_hash(bht, digest, node)) { | 724 dm_bht_compare_hash(bht, digest, node)) { |
| 724 DMERR("failed to verify entry's hash against parent " | 725 DMERR("failed to verify entry's hash against parent " |
| 725 "(d=%u,bi=%u)", depth, block_index); | 726 "(d=%u,bi=%u)", depth, block_index); |
| 726 goto mismatch; | 727 goto mismatch; |
| 727 } | 728 } |
| 728 | 729 |
| 729 atomic_cmpxchg(&entry->state, | |
| 730 DM_BHT_ENTRY_READY, | |
| 731 DM_BHT_ENTRY_VERIFIED); | |
| 732 | |
| 733 entry = parent; | 730 entry = parent; |
| 734 depth--; | 731 depth--; |
| 735 } | 732 } |
| 733 /* Mark path to leaf as verified. */ | |
| 734 for (; depth < bht->depth; depth++) { | |
| 735 entry = dm_bht_get_entry(bht, depth, block_index); | |
| 736 atomic_cmpxchg(&entry->state, | |
| 737 DM_BHT_ENTRY_READY, | |
| 738 DM_BHT_ENTRY_VERIFIED); | |
| 739 } | |
| 736 | 740 |
| 737 return 0; | 741 return 0; |
| 738 | 742 |
| 739 mismatch: | 743 mismatch: |
| 740 return DM_BHT_ENTRY_ERROR_MISMATCH; | 744 return DM_BHT_ENTRY_ERROR_MISMATCH; |
| 741 } | 745 } |
| 742 | 746 |
| 743 /** | 747 /** |
| 744 * dm_bht_store_block - sets a given block's hash in the tree | 748 * dm_bht_store_block - sets a given block's hash in the tree |
| 745 * @bht: pointer to a dm_bht_create()d bht | 749 * @bht: pointer to a dm_bht_create()d bht |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1226 DMERR("no root digest exists to export"); | 1230 DMERR("no root digest exists to export"); |
| 1227 if (available > 0) | 1231 if (available > 0) |
| 1228 *hexdigest = 0; | 1232 *hexdigest = 0; |
| 1229 return -1; | 1233 return -1; |
| 1230 } | 1234 } |
| 1231 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1235 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); |
| 1232 return 0; | 1236 return 0; |
| 1233 } | 1237 } |
| 1234 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1238 EXPORT_SYMBOL(dm_bht_root_hexdigest); |
| 1235 | 1239 |
| OLD | NEW |