| 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);
|
|
|