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 |