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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 | 156 | 
| 157 return &level->entries[index]; | 157 return &level->entries[index]; | 
| 158 } | 158 } | 
| 159 | 159 | 
| 160 static inline u8 *dm_bht_get_node(struct dm_bht *bht, | 160 static inline u8 *dm_bht_get_node(struct dm_bht *bht, | 
| 161 struct dm_bht_entry *entry, | 161 struct dm_bht_entry *entry, | 
| 162 unsigned int depth, | 162 unsigned int depth, | 
| 163 unsigned int block_index) | 163 unsigned int block_index) | 
| 164 { | 164 { | 
| 165 unsigned int index = dm_bht_index_at_level(bht, depth, block_index); | 165 unsigned int index = dm_bht_index_at_level(bht, depth, block_index); | 
| 166 struct dm_bht_level *level = dm_bht_get_level(bht, depth); | |
| 167 | |
| 168 BUG_ON(index >= level->count); | |
| 169 | 166 | 
| 170 return dm_bht_node(bht, entry, index % bht->node_count); | 167 return dm_bht_node(bht, entry, index % bht->node_count); | 
| 171 } | 168 } | 
| 172 | 169 | 
| 173 | 170 | 
| 174 /*----------------------------------------------- | 171 /*----------------------------------------------- | 
| 175 * Implementation functions | 172 * Implementation functions | 
| 176 *-----------------------------------------------*/ | 173 *-----------------------------------------------*/ | 
| 177 | 174 | 
| 178 static int dm_bht_initialize_entries(struct dm_bht *bht); | 175 static int dm_bht_initialize_entries(struct dm_bht *bht); | 
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 583 memcpy(known, computed, bht->digest_size); | 580 memcpy(known, computed, bht->digest_size); | 
| 584 #ifdef CONFIG_DM_DEBUG | 581 #ifdef CONFIG_DM_DEBUG | 
| 585 dm_bht_bin_to_hex(computed, hex, bht->digest_size); | 582 dm_bht_bin_to_hex(computed, hex, bht->digest_size); | 
| 586 DMDEBUG("updating with hash: %s", hex); | 583 DMDEBUG("updating with hash: %s", hex); | 
| 587 #endif | 584 #endif | 
| 588 return 0; | 585 return 0; | 
| 589 } | 586 } | 
| 590 | 587 | 
| 591 /* digest length and bht must be checked already */ | 588 /* digest length and bht must be checked already */ | 
| 592 static int dm_bht_check_block(struct dm_bht *bht, unsigned int block_index, | 589 static int dm_bht_check_block(struct dm_bht *bht, unsigned int block_index, | 
| 593 » » » u8 *digest, int *entry_state) | 590 » » » const void *buf, int *entry_state) | 
| 
 
Will Drewry
2011/03/08 20:53:59
nit: might prefer something more meaningful like "
 
 | |
| 594 { | 591 { | 
| 595 » int depth; | 592 » unsigned int depth = bht->depth; | 
| 596 » unsigned int index; | 593 » struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, | 
| 597 » struct dm_bht_entry *entry; | 594 » » » » » » block_index); | 
| 598 | 595 » struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; | 
| 599 » /* The leaves contain the block hashes */ | 596 » u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | 
| 600 » depth = bht->depth - 1; | 597 » u8 *node; | 
| 601 | |
| 602 » /* Index into the bottom level. Each entry in this level contains | |
| 603 » * nodes whose hashes are the direct hashes of one block of data on | |
| 604 » * disk. | |
| 605 » */ | |
| 606 » index = block_index >> bht->node_count_shift; | |
| 607 » entry = &bht->levels[depth].entries[index]; | |
| 608 | 598 | 
| 609 /* This call is only safe if all nodes along the path | 599 /* This call is only safe if all nodes along the path | 
| 610 * are already populated (i.e. READY) via dm_bht_populate. | 600 * are already populated (i.e. READY) via dm_bht_populate. | 
| 611 */ | 601 */ | 
| 612 » BUG_ON(atomic_read(&entry->state) < DM_BHT_ENTRY_READY); | 602 » *entry_state = atomic_read(&parent->state); | 
| 603 » BUG_ON(*entry_state < DM_BHT_ENTRY_READY); | |
| 613 | 604 | 
| 614 » /* Index into the entry data */ | 605 » node = dm_bht_get_node(bht, parent, depth, block_index); | 
| 615 » index = (block_index % bht->node_count) * bht->digest_size; | 606 » if (dm_bht_compute_hash(bht, hash_desc, virt_to_page(buf), digest) || | 
| 616 » if (memcmp(&entry->nodes[index], digest, bht->digest_size)) { | 607 » dm_bht_compare_hash(bht, digest, node)) { | 
| 617 » » DMCRIT("digest mismatch for block %u", block_index); | 608 » » DMERR("failed to verify entry's hash against parent " | 
| 618 » » dm_bht_log_mismatch(bht, &entry->nodes[index], digest); | 609 » » "(d=%u,bi=%u)", depth, block_index); | 
| 619 return DM_BHT_ENTRY_ERROR_MISMATCH; | 610 return DM_BHT_ENTRY_ERROR_MISMATCH; | 
| 620 } | 611 } | 
| 621 return 0; | 612 return 0; | 
| 622 } | 613 } | 
| 623 | 614 | 
| 624 /* Walk all entries at level 0 to compute the root digest. | 615 /* Walk all entries at level 0 to compute the root digest. | 
| 625 * 0 on success. | 616 * 0 on success. | 
| 626 */ | 617 */ | 
| 627 static int dm_bht_compute_root(struct dm_bht *bht, u8 *digest) | 618 static int dm_bht_compute_root(struct dm_bht *bht, u8 *digest) | 
| 628 { | 619 { | 
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1062 * @bht: pointer to a dm_bht_create()d bht | 1053 * @bht: pointer to a dm_bht_create()d bht | 
| 1063 * @block_index:specific block data is expected from | 1054 * @block_index:specific block data is expected from | 
| 1064 * @digest: computed digest for the given block to be checked | 1055 * @digest: computed digest for the given block to be checked | 
| 1065 * @digest_len: length of @digest | 1056 * @digest_len: length of @digest | 
| 1066 * | 1057 * | 
| 1067 * Returns 0 on success, 1 on missing data, and a negative error | 1058 * Returns 0 on success, 1 on missing data, and a negative error | 
| 1068 * code on verification failure. All supporting functions called | 1059 * code on verification failure. All supporting functions called | 
| 1069 * should return similarly. | 1060 * should return similarly. | 
| 1070 */ | 1061 */ | 
| 1071 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, | 1062 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, | 
| 1072 » » » » u8 *digest, unsigned int digest_len) | 1063 » » » const void *buf) | 
| 
 
Will Drewry
2011/03/08 20:53:59
Please update the comments.
 
 | |
| 1073 { | 1064 { | 
| 1074 int unverified = 0; | 1065 int unverified = 0; | 
| 1075 int entry_state = 0; | 1066 int entry_state = 0; | 
| 1076 | 1067 | 
| 1077 /* TODO(wad) do we really need this? */ | |
| 1078 if (digest_len != bht->digest_size) { | |
| 1079 DMERR("invalid digest_len passed to verify_block"); | |
| 1080 return -EINVAL; | |
| 1081 } | |
| 1082 | |
| 1083 /* Make sure that the root has been verified */ | 1068 /* Make sure that the root has been verified */ | 
| 1084 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { | 1069 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { | 
| 1085 unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); | 1070 unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); | 
| 1086 if (unverified) { | 1071 if (unverified) { | 
| 1087 DMERR_LIMIT("Failed to verify root: %d", unverified); | 1072 DMERR_LIMIT("Failed to verify root: %d", unverified); | 
| 1088 return unverified; | 1073 return unverified; | 
| 1089 } | 1074 } | 
| 1090 } | 1075 } | 
| 1091 | 1076 | 
| 1092 /* Now check that the digest supplied matches the leaf hash */ | 1077 /* Now check that the digest supplied matches the leaf hash */ | 
| 1093 » unverified = dm_bht_check_block(bht, block_index, digest, &entry_state); | 1078 » unverified = dm_bht_check_block(bht, block_index, buf, &entry_state); | 
| 1094 if (unverified) { | 1079 if (unverified) { | 
| 1095 DMERR_LIMIT("Block check failed for %u: %d", block_index, | 1080 DMERR_LIMIT("Block check failed for %u: %d", block_index, | 
| 1096 unverified); | 1081 unverified); | 
| 1097 return unverified; | 1082 return unverified; | 
| 1098 } | 1083 } | 
| 1099 | 1084 | 
| 1100 /* If the entry which contains the block hash is marked verified, then | 1085 /* If the entry which contains the block hash is marked verified, then | 
| 1101 * it means that its hash has been check with the parent. In addition, | 1086 * it means that its hash has been check with the parent. In addition, | 
| 1102 * since that is only possible via verify_path, it transitively means | 1087 * since that is only possible via verify_path, it transitively means | 
| 1103 * it is verified to the root of the tree. If the depth is 1, then it | 1088 * it is verified to the root of the tree. If the depth is 1, then it | 
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1271 DMERR("no root digest exists to export"); | 1256 DMERR("no root digest exists to export"); | 
| 1272 if (available > 0) | 1257 if (available > 0) | 
| 1273 *hexdigest = 0; | 1258 *hexdigest = 0; | 
| 1274 return -1; | 1259 return -1; | 
| 1275 } | 1260 } | 
| 1276 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1261 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 
| 1277 return 0; | 1262 return 0; | 
| 1278 } | 1263 } | 
| 1279 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1264 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 
| 1280 | 1265 | 
| OLD | NEW |