| 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 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 | 516 |
| 517 return state; | 517 return state; |
| 518 | 518 |
| 519 nomem: | 519 nomem: |
| 520 DMCRIT("failed to allocate memory for entry->nodes from pool"); | 520 DMCRIT("failed to allocate memory for entry->nodes from pool"); |
| 521 return -ENOMEM; | 521 return -ENOMEM; |
| 522 | 522 |
| 523 | 523 |
| 524 } | 524 } |
| 525 | 525 |
| 526 static int dm_bht_compare_hash(struct dm_bht *bht, u8 *known, u8 *computed) | |
| 527 { | |
| 528 return memcmp(known, computed, bht->digest_size); | |
| 529 } | |
| 530 | |
| 531 /* dm_bht_verify_path | 526 /* dm_bht_verify_path |
| 532 * Verifies the path. Returns 0 on ok. | 527 * Verifies the path. Returns 0 on ok. |
| 533 */ | 528 */ |
| 534 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, | 529 static int dm_bht_verify_path(struct dm_bht *bht, unsigned int block_index, |
| 535 struct page *pg, unsigned int offset) | 530 struct page *pg, unsigned int offset) |
| 536 { | 531 { |
| 537 unsigned int depth = bht->depth; | 532 unsigned int depth = bht->depth; |
| 538 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; | 533 u8 digest[DM_BHT_MAX_DIGEST_SIZE]; |
| 539 struct dm_bht_entry *entry; | 534 struct dm_bht_entry *entry; |
| 540 u8 *node; | 535 u8 *node; |
| 541 int state; | 536 int state; |
| 542 | 537 |
| 543 do { | 538 do { |
| 544 /* Need to check that the hash of the current block is accurate | 539 /* Need to check that the hash of the current block is accurate |
| 545 * in its parent. | 540 * in its parent. |
| 546 */ | 541 */ |
| 547 entry = dm_bht_get_entry(bht, depth - 1, block_index); | 542 entry = dm_bht_get_entry(bht, depth - 1, block_index); |
| 548 state = atomic_read(&entry->state); | 543 state = atomic_read(&entry->state); |
| 549 /* This call is only safe if all nodes along the path | 544 /* This call is only safe if all nodes along the path |
| 550 * are already populated (i.e. READY) via dm_bht_populate. | 545 * are already populated (i.e. READY) via dm_bht_populate. |
| 551 */ | 546 */ |
| 552 BUG_ON(state < DM_BHT_ENTRY_READY); | 547 BUG_ON(state < DM_BHT_ENTRY_READY); |
| 553 node = dm_bht_get_node(bht, entry, depth, block_index); | 548 node = dm_bht_get_node(bht, entry, depth, block_index); |
| 554 | 549 |
| 555 if (dm_bht_compute_hash(bht, pg, offset, digest) || | 550 if (dm_bht_compute_hash(bht, pg, offset, digest) || |
| 556 » » dm_bht_compare_hash(bht, digest, node)) | 551 » » memcmp(digest, node, bht->digest_size)) |
| 557 goto mismatch; | 552 goto mismatch; |
| 558 | 553 |
| 559 /* Keep the containing block of hashes to be verified in the | 554 /* Keep the containing block of hashes to be verified in the |
| 560 * next pass. | 555 * next pass. |
| 561 */ | 556 */ |
| 562 pg = virt_to_page(entry->nodes); | 557 pg = virt_to_page(entry->nodes); |
| 563 offset = 0; | 558 offset = 0; |
| 564 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); | 559 } while (--depth > 0 && state != DM_BHT_ENTRY_VERIFIED); |
| 565 | 560 |
| 566 if (depth == 0 && state != DM_BHT_ENTRY_VERIFIED) { | 561 if (depth == 0 && state != DM_BHT_ENTRY_VERIFIED) { |
| 567 if (dm_bht_compute_hash(bht, pg, offset, digest) || | 562 if (dm_bht_compute_hash(bht, pg, offset, digest) || |
| 568 » » dm_bht_compare_hash(bht, digest, bht->root_digest)) | 563 » » memcmp(digest, bht->root_digest, bht->digest_size)) |
| 569 goto mismatch; | 564 goto mismatch; |
| 570 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); | 565 atomic_set(&entry->state, DM_BHT_ENTRY_VERIFIED); |
| 571 } | 566 } |
| 572 | 567 |
| 573 /* Mark path to leaf as verified. */ | 568 /* Mark path to leaf as verified. */ |
| 574 for (depth++; depth < bht->depth; depth++) { | 569 for (depth++; depth < bht->depth; depth++) { |
| 575 entry = dm_bht_get_entry(bht, depth, block_index); | 570 entry = dm_bht_get_entry(bht, depth, block_index); |
| 576 /* At this point, entry can only be in VERIFIED or READY state. | 571 /* At this point, entry can only be in VERIFIED or READY state. |
| 577 * So it is safe to use atomic_set instead of atomic_cmpxchg. | 572 * So it is safe to use atomic_set instead of atomic_cmpxchg. |
| 578 */ | 573 */ |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 if (!bht->root_digest) { | 1011 if (!bht->root_digest) { |
| 1017 DMERR("no root digest exists to export"); | 1012 DMERR("no root digest exists to export"); |
| 1018 if (available > 0) | 1013 if (available > 0) |
| 1019 *hexdigest = 0; | 1014 *hexdigest = 0; |
| 1020 return -1; | 1015 return -1; |
| 1021 } | 1016 } |
| 1022 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); | 1017 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); |
| 1023 return 0; | 1018 return 0; |
| 1024 } | 1019 } |
| 1025 EXPORT_SYMBOL(dm_bht_root_hexdigest); | 1020 EXPORT_SYMBOL(dm_bht_root_hexdigest); |
| OLD | NEW |