Index: dm-bht.c |
diff --git a/dm-bht.c b/dm-bht.c |
index 4c262a54d0cbd35fca49e0a1c690bccd53628bc6..4eb4ee0c906aeb5fe265d72335f921f0e9445346 100644 |
--- a/dm-bht.c |
+++ b/dm-bht.c |
@@ -682,65 +682,48 @@ static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index) |
{ |
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); |
- while (depth > 0) { |
+ while (depth > 0 && state != DM_BHT_ENTRY_VERIFIED) { |
u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
struct dm_bht_entry *parent; |
struct page *page; |
u8 *node; |
- int state; |
- |
- DMDEBUG("verify_path for b=%u on d=%d", block_index, depth); |
- /* TODO(msb,wad): would be nice to avoid two atomic reads */ |
- state = atomic_read(&entry->state); |
- if (state == DM_BHT_ENTRY_VERIFIED) { |
- DMDEBUG("verify_path node %u is verified to root", |
- block_index); |
- depth++; /* avoid an extra cmpxchg */ |
- break; |
- } else if (state <= DM_BHT_ENTRY_ERROR) { |
- DMCRIT("entry(d=%u,b=%u) is in an error state: %d", |
- depth, block_index, state); |
- DMCRIT("verification is not possible"); |
- goto mismatch; |
- } else if (state <= DM_BHT_ENTRY_PENDING) { |
- DMERR("entry not ready for verify: d=%u,b=%u", |
- depth, block_index); |
- goto mismatch; |
- } |
/* We need to check that this entry matches the expected |
* hash in the parent->nodes. |
*/ |
parent = dm_bht_get_entry(bht, depth - 1, block_index); |
+ state = atomic_read(&parent->state); |
/* 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); |
+ BUG_ON(state < DM_BHT_ENTRY_READY); |
node = dm_bht_get_node(bht, parent, depth, block_index); |
page = virt_to_page(entry->nodes); |
if (dm_bht_compute_hash(bht, page, digest) || |
- dm_bht_compare_hash(bht, digest, node)) { |
- DMERR("failed to verify entry's hash against parent " |
- "(d=%u,bi=%u)", depth, block_index); |
+ dm_bht_compare_hash(bht, digest, node)) |
goto mismatch; |
- } |
entry = parent; |
depth--; |
} |
+ |
/* Mark path to leaf as verified. */ |
- for (; depth < bht->depth; depth++) { |
+ for (depth++; depth < bht->depth; depth++) { |
entry = dm_bht_get_entry(bht, depth, block_index); |
atomic_cmpxchg(&entry->state, |
DM_BHT_ENTRY_READY, |
DM_BHT_ENTRY_VERIFIED); |
} |
+ DMDEBUG("verify_path: node %u is verified to root", block_index); |
return 0; |
mismatch: |
+ DMERR("verify_path: failed to verify hash against parent (d=%u,bi=%u)", |
+ depth, block_index); |
return DM_BHT_ENTRY_ERROR_MISMATCH; |
} |