| 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 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 memcpy(known, computed, bht->digest_size); | 580 memcpy(known, computed, bht->digest_size); |
| 581 #ifdef CONFIG_DM_DEBUG | 581 #ifdef CONFIG_DM_DEBUG |
| 582 dm_bht_bin_to_hex(computed, hex, bht->digest_size); | 582 dm_bht_bin_to_hex(computed, hex, bht->digest_size); |
| 583 DMDEBUG("updating with hash: %s", hex); | 583 DMDEBUG("updating with hash: %s", hex); |
| 584 #endif | 584 #endif |
| 585 return 0; | 585 return 0; |
| 586 } | 586 } |
| 587 | 587 |
| 588 /* Check the disk block against the leaf hash. */ | 588 /* Check the disk block against the leaf hash. */ |
| 589 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, |
| 590 » » » const void *block, int *entry_state) | 590 » » » const void *block) |
| 591 { | 591 { |
| 592 unsigned int depth = bht->depth; | 592 unsigned int depth = bht->depth; |
| 593 struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, | 593 struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, |
| 594 block_index); | 594 block_index); |
| 595 struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; | 595 struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; |
| 596 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | 596 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
| 597 u8 *node; | 597 u8 *node; |
| 598 | 598 |
| 599 /* This call is only safe if all nodes along the path | 599 /* This call is only safe if all nodes along the path |
| 600 * are already populated (i.e. READY) via dm_bht_populate. | 600 * are already populated (i.e. READY) via dm_bht_populate. |
| 601 */ | 601 */ |
| 602 » *entry_state = atomic_read(&parent->state); | 602 » BUG_ON(atomic_read(&parent->state) < DM_BHT_ENTRY_READY); |
| 603 » BUG_ON(*entry_state < DM_BHT_ENTRY_READY); | |
| 604 | 603 |
| 605 node = dm_bht_get_node(bht, parent, depth, block_index); | 604 node = dm_bht_get_node(bht, parent, depth, block_index); |
| 606 if (dm_bht_compute_hash(bht, hash_desc, virt_to_page(block), digest) || | 605 if (dm_bht_compute_hash(bht, hash_desc, virt_to_page(block), digest) || |
| 607 dm_bht_compare_hash(bht, digest, node)) { | 606 dm_bht_compare_hash(bht, digest, node)) { |
| 608 DMERR("failed to verify entry's hash against parent " | 607 DMERR("failed to verify entry's hash against parent " |
| 609 "(d=%u,bi=%u)", depth, block_index); | 608 "(d=%u,bi=%u)", depth, block_index); |
| 610 return DM_BHT_ENTRY_ERROR_MISMATCH; | 609 return DM_BHT_ENTRY_ERROR_MISMATCH; |
| 611 } | 610 } |
| 612 return 0; | 611 return 0; |
| 613 } | 612 } |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 * @block: virtual address of the block data in memory | 1054 * @block: virtual address of the block data in memory |
| 1056 * | 1055 * |
| 1057 * Returns 0 on success, 1 on missing data, and a negative error | 1056 * Returns 0 on success, 1 on missing data, and a negative error |
| 1058 * code on verification failure. All supporting functions called | 1057 * code on verification failure. All supporting functions called |
| 1059 * should return similarly. | 1058 * should return similarly. |
| 1060 */ | 1059 */ |
| 1061 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, | 1060 int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, |
| 1062 const void *block) | 1061 const void *block) |
| 1063 { | 1062 { |
| 1064 int unverified = 0; | 1063 int unverified = 0; |
| 1065 int entry_state = 0; | |
| 1066 | 1064 |
| 1067 /* Make sure that the root has been verified */ | 1065 /* Make sure that the root has been verified */ |
| 1068 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { | 1066 if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { |
| 1069 unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); | 1067 unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); |
| 1070 if (unverified) { | 1068 if (unverified) { |
| 1071 DMERR_LIMIT("Failed to verify root: %d", unverified); | 1069 DMERR_LIMIT("Failed to verify root: %d", unverified); |
| 1072 return unverified; | 1070 return unverified; |
| 1073 } | 1071 } |
| 1074 } | 1072 } |
| 1075 | 1073 |
| 1076 /* Now check that the digest supplied matches the leaf hash */ | 1074 /* Now check that the digest supplied matches the leaf hash */ |
| 1077 » unverified = dm_bht_check_block(bht, block_index, block, &entry_state); | 1075 » unverified = dm_bht_check_block(bht, block_index, block); |
| 1078 if (unverified) { | 1076 if (unverified) { |
| 1079 DMERR_LIMIT("Block check failed for %u: %d", block_index, | 1077 DMERR_LIMIT("Block check failed for %u: %d", block_index, |
| 1080 unverified); | 1078 unverified); |
| 1081 return unverified; | 1079 return unverified; |
| 1082 } | 1080 } |
| 1083 | 1081 |
| 1084 /* If the entry which contains the block hash is marked verified, then | |
| 1085 * it means that its hash has been check with the parent. In addition, | |
| 1086 * since that is only possible via verify_path, it transitively means | |
| 1087 * it is verified to the root of the tree. If the depth is 1, then it | |
| 1088 * means the entry was verified during root verification. | |
| 1089 */ | |
| 1090 if (entry_state == DM_BHT_ENTRY_VERIFIED || bht->depth == 1) | |
| 1091 return unverified; | |
| 1092 | |
| 1093 /* Now check levels in between */ | 1082 /* Now check levels in between */ |
| 1094 unverified = dm_bht_verify_path(bht, block_index); | 1083 unverified = dm_bht_verify_path(bht, block_index); |
| 1095 if (unverified) | 1084 if (unverified) |
| 1096 DMERR_LIMIT("Failed to verify intermediary nodes for block: %u (
%d)", | 1085 DMERR_LIMIT("Failed to verify intermediary nodes for block: %u (
%d)", |
| 1097 block_index, unverified); | 1086 block_index, unverified); |
| 1098 return unverified; | 1087 return unverified; |
| 1099 } | 1088 } |
| 1100 EXPORT_SYMBOL(dm_bht_verify_block); | 1089 EXPORT_SYMBOL(dm_bht_verify_block); |
| 1101 | 1090 |
| 1102 /** | 1091 /** |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 DMERR("no root digest exists to export"); | 1244 DMERR("no root digest exists to export"); |
| 1256 if (available > 0) | 1245 if (available > 0) |
| 1257 *hexdigest = 0; | 1246 *hexdigest = 0; |
| 1258 return -1; | 1247 return -1; |
| 1259 } | 1248 } |
| 1260 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1249 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); |
| 1261 return 0; | 1250 return 0; |
| 1262 } | 1251 } |
| 1263 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1252 EXPORT_SYMBOL(dm_bht_root_hexdigest); |
| 1264 | 1253 |
| OLD | NEW |