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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 return leaf >> dm_bht_get_level_shift(bht, depth); | 148 return leaf >> dm_bht_get_level_shift(bht, depth); |
| 149 } | 149 } |
| 150 | 150 |
| 151 static __always_inline u8 *dm_bht_node(struct dm_bht *bht, | 151 static __always_inline u8 *dm_bht_node(struct dm_bht *bht, |
| 152 struct dm_bht_entry *entry, | 152 struct dm_bht_entry *entry, |
| 153 unsigned int node_index) | 153 unsigned int node_index) |
| 154 { | 154 { |
| 155 return &entry->nodes[node_index * bht->digest_size]; | 155 return &entry->nodes[node_index * bht->digest_size]; |
| 156 } | 156 } |
| 157 | 157 |
| 158 static inline struct dm_bht_entry *dm_bht_get_entry(struct dm_bht *bht, | |
| 159 unsigned int depth, | |
| 160 unsigned int block_index) | |
| 161 { | |
| 162 unsigned int index = dm_bht_index_at_level(bht, depth, block_index); | |
| 163 struct dm_bht_level *level = dm_bht_get_level(bht, depth); | |
| 164 | |
|
Will Drewry
2010/11/29 17:13:13
I'd like to bring back the BUG_ON(index >= level->
Mandeep Singh Baines
2010/11/29 20:20:38
Fixed.
| |
| 165 return &level->entries[index]; | |
| 166 } | |
| 167 | |
| 168 static inline u8 *dm_bht_get_node(struct dm_bht *bht, | |
| 169 struct dm_bht_entry *parent, | |
| 170 unsigned int depth, | |
| 171 unsigned int block_index) | |
| 172 { | |
| 173 unsigned int index = dm_bht_index_at_level(bht, depth, block_index); | |
| 174 | |
|
Will Drewry
2010/11/29 17:13:13
Same here!
Mandeep Singh Baines
2010/11/29 20:20:38
Fixed.
| |
| 175 return dm_bht_node(bht, parent, index % bht->node_count); | |
| 176 } | |
| 177 | |
| 158 | 178 |
| 159 /*----------------------------------------------- | 179 /*----------------------------------------------- |
| 160 * Implementation functions | 180 * Implementation functions |
| 161 *-----------------------------------------------*/ | 181 *-----------------------------------------------*/ |
| 162 | 182 |
| 163 static int dm_bht_initialize_entries(struct dm_bht *bht); | 183 static int dm_bht_initialize_entries(struct dm_bht *bht); |
| 164 | 184 |
| 165 static int dm_bht_read_callback_stub(void *ctx, sector_t start, u8 *dst, | 185 static int dm_bht_read_callback_stub(void *ctx, sector_t start, u8 *dst, |
| 166 sector_t count, | 186 sector_t count, |
| 167 struct dm_bht_entry *entry); | 187 struct dm_bht_entry *entry); |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED); | 707 atomic_set(&bht->root_state, DM_BHT_ENTRY_VERIFIED); |
| 688 return 0; | 708 return 0; |
| 689 } | 709 } |
| 690 | 710 |
| 691 /* dm_bht_verify_path | 711 /* dm_bht_verify_path |
| 692 * Verifies the path from block_index to depth=0. Returns 0 on ok. | 712 * Verifies the path from block_index to depth=0. Returns 0 on ok. |
| 693 */ | 713 */ |
| 694 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, | 714 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, |
| 695 dm_bht_compare_cb compare_cb) | 715 dm_bht_compare_cb compare_cb) |
| 696 { | 716 { |
| 697 » unsigned int depth = bht->depth; | 717 » unsigned int depth = bht->depth - 1; |
| 698 » struct dm_bht_level *level; | 718 » struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth, block_index); |
| 699 » struct dm_bht_entry *entry; | 719 » struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; |
| 700 » struct dm_bht_entry *parent = NULL; | |
| 701 » u8 *node; | |
| 702 » unsigned int node_index; | |
| 703 » unsigned int entry_index; | |
| 704 » unsigned int parent_index = 0; /* for logging */ | |
| 705 » struct hash_desc *hash_desc; | |
| 706 » int state; | |
| 707 » int ret = 0; | |
| 708 | 720 |
| 709 » hash_desc = &bht->hash_desc[smp_processor_id()]; | 721 » while (depth > 0) { |
| 710 » while (depth-- > 0) { | 722 » » struct dm_bht_entry *parent; |
|
Will Drewry
2010/11/29 17:13:13
In the past, I used to avoid setting up scoped var
Mandeep Singh Baines
2010/11/29 20:20:38
http://stackoverflow.com/questions/982963/is-there
| |
| 711 » » level = dm_bht_get_level(bht, depth); | 723 » » u8 *node; |
| 712 » » entry_index = dm_bht_index_at_level(bht, depth, block_index); | 724 » » int state; |
| 713 » » DMDEBUG("verify_path for bi=%u on d=%d ei=%u (max=%u)", | |
| 714 » » » block_index, depth, entry_index, level->count); | |
| 715 » » BUG_ON(entry_index >= level->count); | |
| 716 » » entry = &level->entries[entry_index]; | |
| 717 | 725 |
| 718 » » /* Catch any existing errors */ | 726 » » DMDEBUG("verify_path for bi=%u on d=%d", block_index, depth); |
| 727 | |
| 719 state = atomic_read(&entry->state); | 728 state = atomic_read(&entry->state); |
| 720 » » if (state <= DM_BHT_ENTRY_ERROR) { | 729 » » if (state == DM_BHT_ENTRY_VERIFIED) { |
| 721 » » » DMCRIT("entry(d=%u,idx=%u) is in an error state: %d", | 730 » » » DMDEBUG("verify_path node %u is verified in parent", |
| 722 » » » depth, entry_index, state); | 731 » » » » block_index); |
| 732 » » » break; | |
|
Will Drewry
2010/11/29 17:13:13
Why is this a break and not a continue now? Just
Mandeep Singh Baines
2010/11/29 20:20:38
Fixed.
| |
| 733 » » } else if (state <= DM_BHT_ENTRY_ERROR) { | |
| 734 » » » DMCRIT("entry(d=%u,b=%u) is in an error state: %d", | |
| 735 » » » depth, block_index, state); | |
| 723 DMCRIT("verification is not possible"); | 736 DMCRIT("verification is not possible"); |
| 724 » » » ret = 1; | 737 » » » return 1; |
| 725 » » » break; | |
| 726 } else if (state <= DM_BHT_ENTRY_PENDING) { | 738 } else if (state <= DM_BHT_ENTRY_PENDING) { |
| 727 » » » DMERR("entry not ready for verify: d=%u,e=%u", | 739 » » » DMERR("entry not ready for verify: d=%u,b=%u", |
| 728 » » » depth, entry_index); | 740 » » » depth, block_index); |
| 729 » » » ret = 1; | 741 » » » return 1; |
| 730 » » » break; | |
| 731 } | 742 } |
| 732 | 743 |
| 733 /* At depth 0, we're at the page underneath the root node and | 744 /* At depth 0, we're at the page underneath the root node and |
| 734 * leave its validation to a separate path. | 745 * leave its validation to a separate path. |
| 735 */ | 746 */ |
| 736 if (depth == 0) | 747 if (depth == 0) |
| 737 break; | 748 break; |
| 738 | 749 |
| 739 /* Grab the parent entry where the current entry hash is. */ | |
| 740 parent_index = dm_bht_index_at_level(bht, depth - 1, | |
| 741 block_index); | |
| 742 level = dm_bht_get_level(bht, depth - 1); | |
| 743 BUG_ON(parent_index >= level->count); | |
| 744 parent = &level->entries[parent_index]; | |
| 745 | |
| 746 /* Because we are one level down, the node_index into the | |
| 747 * the parent's node list modulo the number of nodes. | |
| 748 */ | |
| 749 node_index = entry_index % bht->node_count; | |
| 750 | |
| 751 /* If the nodes in entry have already been checked against the | |
| 752 * parent, then we're done. | |
| 753 */ | |
| 754 if (state == DM_BHT_ENTRY_VERIFIED) { | |
| 755 DMDEBUG("verify_path node %u is verified in parent %u", | |
| 756 node_index, parent_index); | |
| 757 /* If this entry has been checked, move along. */ | |
| 758 continue; | |
| 759 } | |
| 760 | |
| 761 /* We need to check that this entry matches the expected | 750 /* We need to check that this entry matches the expected |
| 762 * hash in the parent->nodes. | 751 * hash in the parent->nodes. |
| 763 */ | 752 */ |
| 764 » » node = dm_bht_node(bht, parent, node_index); | 753 » » parent = dm_bht_get_entry(bht, depth - 1, block_index); |
|
Will Drewry
2010/11/29 17:13:13
So I just noticed a problem with the last change I
Mandeep Singh Baines
2010/11/29 20:20:38
Fixed per discussion over chat.
| |
| 765 » » DMDEBUG("verify_path: node is not verified in parent " | 754 » » node = dm_bht_get_node(bht, parent, depth, block_index); |
| 766 » » "(d=%u,ei=%u,p=%u,pnode=%u)", | |
| 767 » » depth, entry_index, parent_index, node_index); | |
| 768 | 755 |
| 769 if (dm_bht_compute_and_compare(bht, hash_desc, | 756 if (dm_bht_compute_and_compare(bht, hash_desc, |
| 770 virt_to_page(entry->nodes), | 757 virt_to_page(entry->nodes), |
| 771 node, compare_cb)) { | 758 node, compare_cb)) { |
| 772 DMERR("failed to verify entry's hash against parent " | 759 DMERR("failed to verify entry's hash against parent " |
| 773 » » » "(d=%u,ei=%u,p=%u,pnode=%u)", | 760 » » » "(d=%u,bi=%u)", depth, block_index); |
| 774 » » » depth, entry_index, parent_index, node_index); | 761 » » » return DM_BHT_ENTRY_ERROR_MISMATCH; |
| 775 » » » ret = DM_BHT_ENTRY_ERROR_MISMATCH; | |
| 776 » » » break; | |
| 777 } | 762 } |
| 778 | 763 |
| 779 /* Instead of keeping a bitmap of which children have been | |
| 780 * checked, this data is kept in the child state. If full | |
| 781 * reverifies have been set, then no intermediate entry/node is | |
| 782 * ever marked as verified. | |
| 783 */ | |
| 784 if (bht->verify_mode != DM_BHT_FULL_REVERIFY) | 764 if (bht->verify_mode != DM_BHT_FULL_REVERIFY) |
| 785 atomic_cmpxchg(&entry->state, | 765 atomic_cmpxchg(&entry->state, |
| 786 DM_BHT_ENTRY_READY, | 766 DM_BHT_ENTRY_READY, |
| 787 DM_BHT_ENTRY_VERIFIED); | 767 DM_BHT_ENTRY_VERIFIED); |
| 768 | |
| 769 entry = parent; | |
| 770 depth--; | |
| 788 } | 771 } |
| 789 » return ret; | 772 |
| 773 » return 0; | |
| 790 } | 774 } |
| 791 | 775 |
| 792 /** | 776 /** |
| 793 * dm_bht_store_block - sets a given block's hash in the tree | 777 * dm_bht_store_block - sets a given block's hash in the tree |
| 794 * @bht: pointer to a dm_bht_create()d bht | 778 * @bht: pointer to a dm_bht_create()d bht |
| 795 * @block_index:numeric index of the block in the tree | 779 * @block_index:numeric index of the block in the tree |
| 796 * @digest: array of u8s containing the digest of length @bht->digest_size | 780 * @digest: array of u8s containing the digest of length @bht->digest_size |
| 797 * | 781 * |
| 798 * Returns 0 on success, >0 when data is pending, and <0 when a IO or other | 782 * Returns 0 on success, >0 when data is pending, and <0 when a IO or other |
| 799 * error has occurred. | 783 * error has occurred. |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1302 DMERR("no root digest exists to export"); | 1286 DMERR("no root digest exists to export"); |
| 1303 if (available > 0) | 1287 if (available > 0) |
| 1304 *hexdigest = 0; | 1288 *hexdigest = 0; |
| 1305 return -1; | 1289 return -1; |
| 1306 } | 1290 } |
| 1307 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1291 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); |
| 1308 return 0; | 1292 return 0; |
| 1309 } | 1293 } |
| 1310 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1294 EXPORT_SYMBOL(dm_bht_root_hexdigest); |
| 1311 | 1295 |
| OLD | NEW |