Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(465)

Side by Side Diff: drivers/md/dm-bht.c

Issue 6821076: CHROMIUM: verity: change maybe_read_entries to maybe_read_entry (Closed) Base URL: http://git.chromium.org/git/kernel-next.git@chromeos-2.6.38
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 } 307 }
308 308
309 /* Setup callback stubs */ 309 /* Setup callback stubs */
310 bht->read_cb = &dm_bht_read_callback_stub; 310 bht->read_cb = &dm_bht_read_callback_stub;
311 bht->write_cb = &dm_bht_write_callback_stub; 311 bht->write_cb = &dm_bht_write_callback_stub;
312 312
313 status = dm_bht_initialize_entries(bht); 313 status = dm_bht_initialize_entries(bht);
314 if (status) 314 if (status)
315 goto bad_entries_alloc; 315 goto bad_entries_alloc;
316 316
317 /* We compute depth such that there is only be 1 block at level 0. */
318 BUG_ON(bht->levels[0].count != 1);
319
317 return 0; 320 return 0;
318 321
319 bad_entries_alloc: 322 bad_entries_alloc:
320 while (bht->depth-- > 0) 323 while (bht->depth-- > 0)
321 kfree(bht->levels[bht->depth].entries); 324 kfree(bht->levels[bht->depth].entries);
322 kfree(bht->levels); 325 kfree(bht->levels);
323 bad_node_count: 326 bad_node_count:
324 bad_level_alloc: 327 bad_level_alloc:
325 bad_block_count: 328 bad_block_count:
326 kfree(bht->root_digest); 329 kfree(bht->root_digest);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 { 466 {
464 if (status) { 467 if (status) {
465 DMCRIT("an I/O error occurred while writing entry"); 468 DMCRIT("an I/O error occurred while writing entry");
466 atomic_set(&entry->state, DM_BHT_ENTRY_ERROR_IO); 469 atomic_set(&entry->state, DM_BHT_ENTRY_ERROR_IO);
467 /* entry->nodes will be freed later */ 470 /* entry->nodes will be freed later */
468 return; 471 return;
469 } 472 }
470 } 473 }
471 EXPORT_SYMBOL(dm_bht_write_completed); 474 EXPORT_SYMBOL(dm_bht_write_completed);
472 475
476 /* dm_bht_maybe_read_entry
477 * Attempts to atomically acquire an entry, allocate any needed
478 * memory, and issues the I/O callback to load the hash from disk.
479 * Return value is negative on error. When positive, it is the state
480 * value.
481 */
482 static int dm_bht_maybe_read_entry(struct dm_bht *bht, void *ctx,
483 unsigned int depth, unsigned int index)
484 {
485 struct dm_bht_level *level = &bht->levels[depth];
486 struct dm_bht_entry *entry = &level->entries[index];
487 sector_t current_sector = level->sector + to_sector(index * PAGE_SIZE);
488 struct page *node_page;
489 int state;
473 490
474 /* dm_bht_maybe_read_entries
475 * Attempts to atomically acquire each entry, allocated any needed
476 * memory, and issues I/O callbacks to load the hashes from disk.
477 * Returns 0 if all entries are loaded and verified. On error, the
478 * return value is negative. When positive, it is the state values
479 * ORd.
480 */
481 static int dm_bht_maybe_read_entries(struct dm_bht *bht, void *ctx,
482 unsigned int depth, unsigned int index,
483 unsigned int count, bool until_exist)
484 {
485 struct dm_bht_level *level;
486 struct dm_bht_entry *entry, *last_entry;
487 sector_t current_sector;
488 int state = 0;
489 int status = 0;
490 struct page *node_page = NULL;
491 BUG_ON(depth >= bht->depth); 491 BUG_ON(depth >= bht->depth);
492 492
493 level = &bht->levels[depth];
494 if (count > level->count - index) {
495 DMERR("dm_bht_maybe_read_entries(d=%u,ei=%u,count=%u): "
496 "index+count exceeds available entries %u",
497 depth, index, count, level->count);
498 return -EINVAL;
499 }
500 /* XXX: hardcoding PAGE_SIZE means that a perfectly valid image 493 /* XXX: hardcoding PAGE_SIZE means that a perfectly valid image
501 * on one system may not work on a different kernel. 494 * on one system may not work on a different kernel.
502 * TODO(wad) abstract PAGE_SIZE with a bht->entry_size or 495 * TODO(wad) abstract PAGE_SIZE with a bht->entry_size or
503 * at least a define and ensure bht->entry_size is 496 * at least a define and ensure bht->entry_size is
504 * sector aligned at least. 497 * sector aligned at least.
505 */ 498 */
506 current_sector = level->sector + to_sector(index * PAGE_SIZE);
507 for (entry = &level->entries[index], last_entry = entry + count;
508 entry < last_entry;
509 ++entry, current_sector += to_sector(PAGE_SIZE)) {
510 /* If the entry's state is UNALLOCATED, then we'll claim it
511 * for allocation and loading.
512 */
513 state = atomic_cmpxchg(&entry->state,
514 DM_BHT_ENTRY_UNALLOCATED,
515 DM_BHT_ENTRY_PENDING);
516 DMDEBUG("dm_bht_maybe_read_entries(d=%u,ei=%u,count=%u): "
517 "ei=%lu, state=%d",
518 depth, index, count,
519 (unsigned long)(entry - level->entries), state);
520 if (state <= DM_BHT_ENTRY_ERROR) {
521 DMCRIT("entry %u is in an error state", index);
522 return state;
523 }
524 499
525 » » /* Currently, the verified state is unused. */ 500 » /* If the entry's state is UNALLOCATED, then we'll claim it
526 » » if (state == DM_BHT_ENTRY_VERIFIED) { 501 » * for allocation and loading.
527 » » » if (until_exist) 502 » */
528 » » » » return 0; 503 » state = atomic_cmpxchg(&entry->state,
529 » » » /* Makes 0 == verified. Is that ideal? */ 504 » » » DM_BHT_ENTRY_UNALLOCATED,
530 » » » continue; 505 » » » DM_BHT_ENTRY_PENDING);
531 » » } 506 » DMDEBUG("dm_bht_maybe_read_entry(d=%u,ei=%u): ei=%lu, state=%d",
507 » » depth, index, (unsigned long)(entry - level->entries), state);
532 508
533 » » if (state != DM_BHT_ENTRY_UNALLOCATED) { 509 » if (state != DM_BHT_ENTRY_UNALLOCATED)
534 » » » /* PENDING, READY, ... */ 510 » » goto out;
535 » » » if (until_exist)
536 » » » » return state;
537 » » » status |= state;
538 » » » continue;
539 » » }
540 » » /* Current entry is claimed for allocation and loading */
541 » » node_page = (struct page *) mempool_alloc(bht->entry_pool,
542 » » » » » » » GFP_NOIO);
543 » » if (!node_page) {
544 » » » DMCRIT("failed to allocate memory for "
545 » » » "entry->nodes from pool");
546 » » » return -ENOMEM;
547 » » }
548 » » /* dm-bht guarantees page-aligned memory for callbacks. */
549 » » entry->nodes = page_address(node_page);
550 » » /* Let the caller know that not all the data is yet available */
551 » » status |= DM_BHT_ENTRY_REQUESTED;
552 » » /* Issue the read callback */
553 » » /* TODO(wad) error check callback here too */
554 » » DMDEBUG("dm_bht_maybe_read_entries(d=%u,ei=%u,count=%u): "
555 » » » "reading %lu",
556 » » » depth, index, count,
557 » » » (unsigned long)(entry - level->entries));
558 » » bht->read_cb(ctx, /* external context */
559 » » » current_sector, /* starting sector */
560 » » » entry->nodes, /* destination */
561 » » » to_sector(PAGE_SIZE),
562 » » » entry); /* io context */
563 511
564 » } 512 » state = DM_BHT_ENTRY_REQUESTED;
565 » /* Should only be 0 if all entries were verified and not just ready */ 513
566 » return status; 514 » /* Current entry is claimed for allocation and loading */
515 » node_page = (struct page *) mempool_alloc(bht->entry_pool, GFP_NOIO);
516 » if (!node_page)
517 » » goto nomem;
518 » /* dm-bht guarantees page-aligned memory for callbacks. */
519 » entry->nodes = page_address(node_page);
520
521 » /* TODO(wad) error check callback here too */
522 » DMDEBUG("dm_bht_maybe_read_entry(d=%u,ei=%u): reading %lu",
523 » » depth, index, (unsigned long)(entry - level->entries));
524 » bht->read_cb(ctx, current_sector, entry->nodes,
525 » » to_sector(PAGE_SIZE), entry);
526
527 out:
528 » if (state <= DM_BHT_ENTRY_ERROR)
529 » » DMCRIT("entry %u is in an error state", index);
530
531 » return state;
532
533 nomem:
534 » DMCRIT("failed to allocate memory for entry->nodes from pool");
535 » return -ENOMEM;
536
537
567 } 538 }
568 539
569 static int dm_bht_compare_hash(struct dm_bht *bht, u8 *known, u8 *computed) 540 static int dm_bht_compare_hash(struct dm_bht *bht, u8 *known, u8 *computed)
570 { 541 {
571 return memcmp(known, computed, bht->digest_size); 542 return memcmp(known, computed, bht->digest_size);
572 } 543 }
573 544
574 static int dm_bht_update_hash(struct dm_bht *bht, u8 *known, u8 *computed) 545 static int dm_bht_update_hash(struct dm_bht *bht, u8 *known, u8 *computed)
575 { 546 {
576 #ifdef CONFIG_DM_DEBUG 547 #ifdef CONFIG_DM_DEBUG
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 { 796 {
826 int depth, r; 797 int depth, r;
827 798
828 for (depth = bht->depth - 2; depth >= 0; depth--) { 799 for (depth = bht->depth - 2; depth >= 0; depth--) {
829 struct dm_bht_level *level = dm_bht_get_level(bht, depth); 800 struct dm_bht_level *level = dm_bht_get_level(bht, depth);
830 struct dm_bht_level *child_level = level + 1; 801 struct dm_bht_level *child_level = level + 1;
831 struct dm_bht_entry *entry = level->entries; 802 struct dm_bht_entry *entry = level->entries;
832 struct dm_bht_entry *child = child_level->entries; 803 struct dm_bht_entry *child = child_level->entries;
833 unsigned int i, j; 804 unsigned int i, j;
834 805
835 r = dm_bht_maybe_read_entries(bht, read_cb_ctx, depth,
836 0, level->count, true);
837 if (r < 0) {
838 DMCRIT("an error occurred while reading entry");
839 goto out;
840 }
841
842 for (i = 0; i < level->count; i++, entry++) { 806 for (i = 0; i < level->count; i++, entry++) {
843 unsigned int count = bht->node_count; 807 unsigned int count = bht->node_count;
808
809 r = dm_bht_maybe_read_entry(bht, read_cb_ctx, depth, i);
810 if (r < 0) {
811 DMCRIT("an error occurred while reading entry");
812 goto out;
813 }
814
844 if (i == (level->count - 1)) 815 if (i == (level->count - 1))
845 count = child_level->count % bht->node_count; 816 count = child_level->count % bht->node_count;
846 if (count == 0) 817 if (count == 0)
847 count = bht->node_count; 818 count = bht->node_count;
848 for (j = 0; j < count; j++, child++) { 819 for (j = 0; j < count; j++, child++) {
849 u8 *block = child->nodes; 820 u8 *block = child->nodes;
850 u8 *digest = dm_bht_node(bht, entry, j); 821 u8 *digest = dm_bht_node(bht, entry, j);
851 822
852 r = dm_bht_compute_hash(bht, block, digest); 823 r = dm_bht_compute_hash(bht, block, digest);
853 if (r) { 824 if (r) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 940
970 /* Load in all of level 0 if the root is unverified */ 941 /* Load in all of level 0 if the root is unverified */
971 root_state = atomic_read(&bht->root_state); 942 root_state = atomic_read(&bht->root_state);
972 /* TODO(wad) create a separate io object for the root request which 943 /* TODO(wad) create a separate io object for the root request which
973 * can continue on and be verified and stop making every request 944 * can continue on and be verified and stop making every request
974 * check. 945 * check.
975 */ 946 */
976 if (root_state != DM_BHT_ENTRY_VERIFIED) { 947 if (root_state != DM_BHT_ENTRY_VERIFIED) {
977 DMDEBUG("root data is not yet loaded"); 948 DMDEBUG("root data is not yet loaded");
978 /* If positive, it means some are pending. */ 949 /* If positive, it means some are pending. */
979 » » populated = dm_bht_maybe_read_entries(bht, read_cb_ctx, 0, 0, 950 » » populated = dm_bht_maybe_read_entry(bht, read_cb_ctx, 0, 0);
980 » » » » » » bht->levels[0].count,
981 » » » » » » true);
982 if (populated < 0) { 951 if (populated < 0) {
983 DMCRIT("an error occurred while reading level[0]"); 952 DMCRIT("an error occurred while reading level[0]");
984 /* TODO(wad) define std error codes */ 953 /* TODO(wad) define std error codes */
985 return populated; 954 return populated;
986 } 955 }
987 } 956 }
988 957
989 for (depth = 1; depth < bht->depth; ++depth) { 958 for (depth = 1; depth < bht->depth; ++depth) {
990 level = dm_bht_get_level(bht, depth); 959 level = dm_bht_get_level(bht, depth);
991 entry_index = dm_bht_index_at_level(bht, depth, 960 entry_index = dm_bht_index_at_level(bht, depth,
992 block_index); 961 block_index);
993 DMDEBUG("populate for bi=%u on d=%d ei=%u (max=%u)", 962 DMDEBUG("populate for bi=%u on d=%d ei=%u (max=%u)",
994 block_index, depth, entry_index, level->count); 963 block_index, depth, entry_index, level->count);
995 964
996 /* Except for the root node case, we should only ever need 965 /* Except for the root node case, we should only ever need
997 * to load one entry along the path. 966 * to load one entry along the path.
998 */ 967 */
999 » » read_status = dm_bht_maybe_read_entries(bht, read_cb_ctx, 968 » » read_status = dm_bht_maybe_read_entry(bht, read_cb_ctx,
1000 » » » » » » » depth, entry_index, 969 » » » » » » depth, entry_index);
1001 » » » » » » » 1, false);
1002 if (unlikely(read_status < 0)) { 970 if (unlikely(read_status < 0)) {
1003 DMCRIT("failure occurred reading entry %u depth %u", 971 DMCRIT("failure occurred reading entry %u depth %u",
1004 entry_index, depth); 972 entry_index, depth);
1005 return read_status; 973 return read_status;
1006 } 974 }
1007 /* Accrue return code flags */ 975 /* Accrue return code flags */
1008 populated |= read_status; 976 populated |= read_status;
1009 } 977 }
1010 978
1011 /* All nodes are ready. The hash for the block_index can be verified */ 979 /* All nodes are ready. The hash for the block_index can be verified */
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 if (!bht->root_digest) { 1149 if (!bht->root_digest) {
1182 DMERR("no root digest exists to export"); 1150 DMERR("no root digest exists to export");
1183 if (available > 0) 1151 if (available > 0)
1184 *hexdigest = 0; 1152 *hexdigest = 0;
1185 return -1; 1153 return -1;
1186 } 1154 }
1187 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size); 1155 dm_bht_bin_to_hex(bht->root_digest, hexdigest, bht->digest_size);
1188 return 0; 1156 return 0;
1189 } 1157 }
1190 EXPORT_SYMBOL(dm_bht_root_hexdigest); 1158 EXPORT_SYMBOL(dm_bht_root_hexdigest);
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698