Index: dm-bht.c |
diff --git a/dm-bht.c b/dm-bht.c |
index 35713de9bdd0b7f20dc8975443faa4f541087c36..c9d1fcac222b5c7994ab1135c67e77a060754f66 100644 |
--- a/dm-bht.c |
+++ b/dm-bht.c |
@@ -163,9 +163,6 @@ static inline u8 *dm_bht_get_node(struct dm_bht *bht, |
unsigned int block_index) |
{ |
unsigned int index = dm_bht_index_at_level(bht, depth, block_index); |
- struct dm_bht_level *level = dm_bht_get_level(bht, depth); |
- |
- BUG_ON(index >= level->count); |
return dm_bht_node(bht, entry, index % bht->node_count); |
} |
@@ -588,34 +585,28 @@ static int dm_bht_update_hash(struct dm_bht *bht, u8 *known, u8 *computed) |
return 0; |
} |
-/* digest length and bht must be checked already */ |
+/* Check the disk block against the leaf hash. */ |
static int dm_bht_check_block(struct dm_bht *bht, unsigned int block_index, |
- u8 *digest, int *entry_state) |
+ const void *block, int *entry_state) |
{ |
- int depth; |
- unsigned int index; |
- struct dm_bht_entry *entry; |
- |
- /* The leaves contain the block hashes */ |
- depth = bht->depth - 1; |
- |
- /* Index into the bottom level. Each entry in this level contains |
- * nodes whose hashes are the direct hashes of one block of data on |
- * disk. |
- */ |
- index = block_index >> bht->node_count_shift; |
- entry = &bht->levels[depth].entries[index]; |
+ unsigned int depth = bht->depth; |
+ struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, |
+ block_index); |
+ struct hash_desc *hash_desc = &bht->hash_desc[smp_processor_id()]; |
+ u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
+ u8 *node; |
/* This call is only safe if all nodes along the path |
* are already populated (i.e. READY) via dm_bht_populate. |
*/ |
- BUG_ON(atomic_read(&entry->state) < DM_BHT_ENTRY_READY); |
- |
- /* Index into the entry data */ |
- index = (block_index % bht->node_count) * bht->digest_size; |
- if (memcmp(&entry->nodes[index], digest, bht->digest_size)) { |
- DMCRIT("digest mismatch for block %u", block_index); |
- dm_bht_log_mismatch(bht, &entry->nodes[index], digest); |
+ *entry_state = atomic_read(&parent->state); |
+ BUG_ON(*entry_state < DM_BHT_ENTRY_READY); |
+ |
+ node = dm_bht_get_node(bht, parent, depth, block_index); |
+ if (dm_bht_compute_hash(bht, hash_desc, virt_to_page(block), digest) || |
+ dm_bht_compare_hash(bht, digest, node)) { |
+ DMERR("failed to verify entry's hash against parent " |
+ "(d=%u,bi=%u)", depth, block_index); |
return DM_BHT_ENTRY_ERROR_MISMATCH; |
} |
return 0; |
@@ -1061,25 +1052,18 @@ EXPORT_SYMBOL(dm_bht_populate); |
* dm_bht_verify_block - checks that all nodes in the path for @block are valid |
* @bht: pointer to a dm_bht_create()d bht |
* @block_index:specific block data is expected from |
- * @digest: computed digest for the given block to be checked |
- * @digest_len: length of @digest |
+ * @block: virtual address of the block data in memory |
* |
* Returns 0 on success, 1 on missing data, and a negative error |
* code on verification failure. All supporting functions called |
* should return similarly. |
*/ |
int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, |
- u8 *digest, unsigned int digest_len) |
+ const void *block) |
{ |
int unverified = 0; |
int entry_state = 0; |
- /* TODO(wad) do we really need this? */ |
- if (digest_len != bht->digest_size) { |
- DMERR("invalid digest_len passed to verify_block"); |
- return -EINVAL; |
- } |
- |
/* Make sure that the root has been verified */ |
if (atomic_read(&bht->root_state) != DM_BHT_ENTRY_VERIFIED) { |
unverified = dm_bht_verify_root(bht, dm_bht_compare_hash); |
@@ -1090,7 +1074,7 @@ int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, |
} |
/* Now check that the digest supplied matches the leaf hash */ |
- unverified = dm_bht_check_block(bht, block_index, digest, &entry_state); |
+ unverified = dm_bht_check_block(bht, block_index, block, &entry_state); |
if (unverified) { |
DMERR_LIMIT("Block check failed for %u: %d", block_index, |
unverified); |