Index: drivers/md/dm-bht.c |
diff --git a/drivers/md/dm-bht.c b/drivers/md/dm-bht.c |
index 5f0308154236fc6ec01170042607ef55db2007cb..0449b58dee27f5b87385fbcc358b71c9b52e3ea4 100644 |
--- a/drivers/md/dm-bht.c |
+++ b/drivers/md/dm-bht.c |
@@ -591,31 +591,6 @@ static int dm_bht_update_hash(struct dm_bht *bht, u8 *known, u8 *computed) |
return 0; |
} |
-/* Check the disk block against the leaf hash. */ |
-static int dm_bht_check_block(struct dm_bht *bht, unsigned int block_index, |
- const void *block) |
-{ |
- unsigned int depth = bht->depth; |
- struct dm_bht_entry *parent = dm_bht_get_entry(bht, depth - 1, |
- block_index); |
- 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(&parent->state) < DM_BHT_ENTRY_READY); |
- |
- node = dm_bht_get_node(bht, parent, depth, block_index); |
- if (dm_bht_compute_hash(bht, 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; |
-} |
- |
/* Walk all entries at level 0 to compute the root digest. |
* 0 on success. |
*/ |
@@ -682,37 +657,39 @@ static int dm_bht_verify_root(struct dm_bht *bht, |
} |
/* dm_bht_verify_path |
- * Verifies the path from block_index to depth=0. Returns 0 on ok. |
+ * Verifies the path. Returns 0 on ok. |
*/ |
-static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index) |
+static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, |
+ const void *block) |
{ |
- unsigned int depth = bht->depth - 1; |
- struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth, block_index); |
- int state = atomic_read(&entry->state); |
+ unsigned int depth = bht->depth; |
+ struct dm_bht_entry *entry; |
+ int state; |
- while (depth > 0 && state != DM_BHT_ENTRY_VERIFIED) { |
+ do { |
u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
- struct dm_bht_entry *parent; |
u8 *node; |
- /* We need to check that this entry matches the expected |
- * hash in the parent->nodes. |
+ /* Need to check that the hash of the current block is accurate |
+ * in its parent. |
*/ |
- parent = dm_bht_get_entry(bht, depth - 1, block_index); |
- state = atomic_read(&parent->state); |
+ entry = dm_bht_get_entry(bht, depth - 1, block_index); |
+ state = atomic_read(&entry->state); |
/* This call is only safe if all nodes along the path |
* are already populated (i.e. READY) via dm_bht_populate. |
*/ |
BUG_ON(state < DM_BHT_ENTRY_READY); |
- node = dm_bht_get_node(bht, parent, depth, block_index); |
+ node = dm_bht_get_node(bht, entry, depth, block_index); |
- if (dm_bht_compute_hash(bht, entry->nodes, digest) || |
+ if (dm_bht_compute_hash(bht, block, digest) || |
dm_bht_compare_hash(bht, digest, node)) |
goto mismatch; |
- entry = parent; |
- depth--; |
- } |
+ /* Keep the containing block of hashes to be verified in the |
+ * next pass. |
+ */ |
+ block = entry->nodes; |
+ } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); |
/* Mark path to leaf as verified. */ |
for (depth++; depth < bht->depth; depth++) { |
@@ -1045,31 +1022,24 @@ EXPORT_SYMBOL(dm_bht_populate); |
int dm_bht_verify_block(struct dm_bht *bht, unsigned int block_index, |
const void *block) |
{ |
- int unverified = 0; |
+ int r = 0; |
/* 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); |
- if (unverified) { |
- DMERR_LIMIT("Failed to verify root: %d", unverified); |
- return unverified; |
+ r = dm_bht_verify_root(bht, dm_bht_compare_hash); |
+ if (r) { |
+ DMERR_LIMIT("Failed to verify root: %d", r); |
+ goto out; |
} |
} |
- /* Now check that the digest supplied matches the leaf hash */ |
- unverified = dm_bht_check_block(bht, block_index, block); |
- if (unverified) { |
- DMERR_LIMIT("Block check failed for %u: %d", block_index, |
- unverified); |
- return unverified; |
- } |
- |
/* Now check levels in between */ |
- unverified = dm_bht_verify_path(bht, block_index); |
- if (unverified) |
- DMERR_LIMIT("Failed to verify intermediary nodes for block: %u (%d)", |
- block_index, unverified); |
- return unverified; |
+ r = dm_bht_verify_path(bht, block_index, block); |
+ if (r) |
+ DMERR_LIMIT("Failed to verify block: %u (%d)", block_index, r); |
+ |
+out: |
+ return r; |
} |
EXPORT_SYMBOL(dm_bht_verify_block); |