verity: remove write callback from user-space

Remove the write callback abstraction as it is no longer needed.

BUG=chromium-os:19952
TEST=Ran unit tests from dm-verity.git.
     Ran platform_DMVerityCorruption and platform_DMVerityBitCorruption.
TESTED_ON=Alex

Change-Id: I111c1a5d6a21b1da594a24c94c36af71fca2f816
Reviewed-on: http://gerrit.chromium.org/gerrit/7102
Reviewed-by: Mandeep Singh Baines <msb@chromium.org>
Tested-by: Mandeep Singh Baines <msb@chromium.org>
diff --git a/dm-bht-userspace.c b/dm-bht-userspace.c
index e495fd5..247245d 100644
--- a/dm-bht-userspace.c
+++ b/dm-bht-userspace.c
@@ -53,23 +53,33 @@
 	return 0;
 }
 
+void dm_bht_set_buffer(struct dm_bht *bht, void *buffer) {
+	int depth;
+
+	for (depth = 0; depth < bht->depth; ++depth) {
+		struct dm_bht_level *level = dm_bht_get_level(bht, depth);
+		struct dm_bht_entry *entry_end = level->entries + level->count;
+		struct dm_bht_entry *entry;
+
+		for (entry = level->entries; entry < entry_end; ++entry) {
+			entry->nodes = buffer;
+			memset(buffer, 0, PAGE_SIZE);
+			buffer += PAGE_SIZE;
+		}
+	}
+}
+
 /**
  * dm_bht_compute - computes and updates all non-block-level hashes in a tree
  * @bht:	pointer to a dm_bht_create()d bht
- * @read_cb_ctx:opaque read_cb context for all I/O on this call
  *
  * Returns 0 on success, >0 when data is pending, and <0 when a IO or other
  * error has occurred.
  *
  * Walks the tree and computes the hashes at each level from the
- * hashes below. This can only be called once per tree creation
- * since it will mark entries verified. Expects dm_bht_populate() to
- * correctly populate the tree from the read_callback_stub.
- *
- * This function should not be used when verifying the same tree and
- * should not be used with multiple simultaneous operators on @bht.
+ * hashes below.
  */
-int dm_bht_compute(struct dm_bht *bht, void *read_cb_ctx)
+int dm_bht_compute(struct dm_bht *bht)
 {
 	int depth, r = 0;
 
@@ -82,15 +92,7 @@
 
 		for (i = 0; i < level->count; i++, entry++) {
 			unsigned int count = bht->node_count;
-			struct page *pg;
 
-			pg = alloc_page(GFP_NOIO);
-			if (!pg) {
-				DMCRIT("an error occurred while reading entry");
-				goto out;
-			}
-
-			entry->nodes = page_address(pg);
 			memset(entry->nodes, 0, PAGE_SIZE);
 			atomic_set(&entry->state, DM_BHT_ENTRY_READY);
 
@@ -122,126 +124,25 @@
 }
 
 /**
- * dm_bht_sync - writes the tree in memory to disk
- * @bht:	pointer to a dm_bht_create()d bht
- * @write_ctx:	callback context for writes issued
- *
- * Since all entry nodes are PAGE_SIZE, the data will be pre-aligned and
- * padded.
- */
-int dm_bht_sync(struct dm_bht *bht, void *write_cb_ctx)
-{
-	int depth;
-	int ret = 0;
-	int state;
-	sector_t sector;
-	struct dm_bht_level *level;
-	struct dm_bht_entry *entry;
-	struct dm_bht_entry *entry_end;
-
-	for (depth = 0; depth < bht->depth; ++depth) {
-		level = dm_bht_get_level(bht, depth);
-		entry_end = level->entries + level->count;
-		sector = level->sector;
-		for (entry = level->entries; entry < entry_end; ++entry) {
-			state = atomic_read(&entry->state);
-			if (state <= DM_BHT_ENTRY_PENDING) {
-				DMERR("At depth %d, entry %lu is not ready",
-				      depth,
-				      (unsigned long)(entry - level->entries));
-				return state;
-			}
-			ret = bht->write_cb(write_cb_ctx,
-					    sector,
-					    entry->nodes,
-					    to_sector(PAGE_SIZE),
-					    entry);
-			if (ret) {
-				DMCRIT("an error occurred writing entry %lu",
-				      (unsigned long)(entry - level->entries));
-				return ret;
-			}
-			sector += to_sector(PAGE_SIZE);
-		}
-	}
-
-	return 0;
-}
-
-/**
  * dm_bht_store_block - sets a given block's hash in the tree
  * @bht:	pointer to a dm_bht_create()d bht
  * @block:	numeric index of the block in the tree
- * @digest:	array of u8s containing the digest of length @bht->digest_size
+ * @block_data:	array of u8s containing the block of data to hash
  *
- * Returns 0 on success, >0 when data is pending, and <0 when a IO or other
- * error has occurred.
+ * Returns 0 on success.
  *
  * If the containing entry in the tree is unallocated, it will allocate memory
- * and mark the entry as ready.  All other block entries will be 0s.  This
- * function is not safe for simultaneous use when verifying data and should not
- * be used if the @bht is being accessed by any other functions in any other
- * threads/processes.
+ * and mark the entry as ready.  All other block entries will be 0s.
  *
- * It is expected that virt_to_page will work on |block_data|.
+ * It is up to the users of the update interface to ensure the entry data is
+ * fully populated prior to use. The number of updated entries is NOT tracked.
  */
 int dm_bht_store_block(struct dm_bht *bht, unsigned int block,
 		       u8 *block_data)
 {
-	int depth;
-	unsigned int index;
-	unsigned int node_index;
-	struct dm_bht_entry *entry;
-	struct dm_bht_level *level;
-	int state;
-	struct page *node_page = NULL;
+	int depth = bht->depth;
+	struct dm_bht_entry *entry = dm_bht_get_entry(bht, depth - 1, block);
+	u8 *node = dm_bht_get_node(bht, entry, depth, block);
 
-	/* Look at the last level of nodes above the leaves (data blocks) */
-	depth = bht->depth - 1;
-
-	/* Index into the level */
-	level = dm_bht_get_level(bht, depth);
-	index = dm_bht_index_at_level(bht, depth, block);
-	/* Grab the node index into the current entry by getting the
-	 * index at the leaf-level.
-	 */
-	node_index = dm_bht_index_at_level(bht, depth + 1, block) %
-		     bht->node_count;
-	entry = &level->entries[index];
-
-	DMDEBUG("Storing block %u in d=%d,ei=%u,ni=%u,s=%d",
-		block, depth, index, node_index,
-		atomic_read(&entry->state));
-
-	state = atomic_cmpxchg(&entry->state,
-			       DM_BHT_ENTRY_UNALLOCATED,
-			       DM_BHT_ENTRY_PENDING);
-	/* !!! Note. It is up to the users of the update interface to
-	 *     ensure the entry data is fully populated prior to use.
-	 *     The number of updated entries is NOT tracked.
-	 */
-	if (state == DM_BHT_ENTRY_UNALLOCATED) {
-		node_page = alloc_page(GFP_KERNEL);
-		if (!node_page) {
-			atomic_set(&entry->state, DM_BHT_ENTRY_ERROR);
-			return -ENOMEM;
-		}
-		entry->nodes = page_address(node_page);
-		memset(entry->nodes, 0, PAGE_SIZE);
-		/* TODO(wad) could expose this to the caller to that they
-		 * can transition from unallocated to ready manually.
-		 */
-		atomic_set(&entry->state, DM_BHT_ENTRY_READY);
-	} else if (state <= DM_BHT_ENTRY_ERROR) {
-		DMCRIT("leaf entry for block %u is invalid",
-		      block);
-		return state;
-	} else if (state == DM_BHT_ENTRY_PENDING) {
-		DMERR("leaf data is pending for block %u", block);
-		return 1;
-	}
-
-	dm_bht_compute_hash(bht, virt_to_page(block_data), 0,
-			    dm_bht_node(bht, entry, node_index));
-	return 0;
+	return dm_bht_compute_hash(bht, virt_to_page(block_data), 0, node);
 }
diff --git a/dm-bht.h b/dm-bht.h
index e34b101..2387c66 100644
--- a/dm-bht.h
+++ b/dm-bht.h
@@ -135,8 +135,8 @@
  * should not be directly used for verification. (It should be repopulated.)
  * In addition, these functions aren't meant to be called in parallel.
  */
-int dm_bht_compute(struct dm_bht *bht, void *read_cb_ctx);
-int dm_bht_sync(struct dm_bht *bht, void *write_cb_ctx);
+int dm_bht_compute(struct dm_bht *bht);
+void dm_bht_set_buffer(struct dm_bht *bht, void *buffer);
 int dm_bht_store_block(struct dm_bht *bht, unsigned int block,
 		       u8 *block_data);
 int dm_bht_zeroread_callback(void *ctx, sector_t start, u8 *dst, sector_t count,
diff --git a/dm-bht_unittest.cc b/dm-bht_unittest.cc
index 59d22d2..3871a38 100644
--- a/dm-bht_unittest.cc
+++ b/dm-bht_unittest.cc
@@ -38,19 +38,34 @@
 // Simple test to help valgrind/tcmalloc catch bad mem management
 TEST(DmBht, CreateZeroPopulateDestroy) {
   struct dm_bht bht;
+  sector_t sectors;
   // This should fail.
-  unsigned int blocks = 16384;
+  unsigned int blocks, total_blocks = 16384;
   u8 *data = (u8 *)my_memalign(PAGE_SIZE, PAGE_SIZE);
+  void * hash_data;
+
+  blocks = total_blocks;
 
   // Store all the block hashes of blocks of 0.
   memset(reinterpret_cast<void *>(data), 0, sizeof(data));
   EXPECT_EQ(0, dm_bht_create(&bht, blocks, "sha256"));
   dm_bht_set_read_cb(&bht, dm_bht_zeroread_callback);
+  sectors = dm_bht_sectors(&bht);
+  hash_data = new u8[to_bytes(sectors)];
+  dm_bht_set_buffer(&bht, hash_data);
+
   do {
     EXPECT_EQ(dm_bht_store_block(&bht, blocks - 1, data), 0);
   } while (--blocks > 0);
-  EXPECT_EQ(0, dm_bht_compute(&bht, NULL));
+  // Load the tree from the pre-populated hash data
+  for (blocks = 0; blocks < total_blocks; blocks += bht.node_count)
+    EXPECT_GE(dm_bht_populate(&bht,
+			      reinterpret_cast<void *>(this),
+			      blocks),
+	      0);
+  EXPECT_EQ(0, dm_bht_compute(&bht));
   EXPECT_EQ(0, dm_bht_destroy(&bht));
+  free(hash_data);
   free(data);
 }
 
@@ -59,14 +74,6 @@
   void SetUp() {
   }
 
-  int Write(sector_t start, u8 *src, sector_t count) {
-    EXPECT_LT(start, sectors_);
-    EXPECT_EQ(to_bytes(count), PAGE_SIZE);
-    u8 *dst = &hash_data_[to_bytes(start)];
-    memcpy(dst, src, to_bytes(count));
-    return 0;
-  }
-
   int Read(sector_t start, u8 *dst, sector_t count) {
     EXPECT_LT(start, sectors_);
     EXPECT_EQ(to_bytes(count), PAGE_SIZE);
@@ -75,17 +82,6 @@
     return 0;
   }
 
-  static int WriteCallback(void *mbht_instance,
-                           sector_t start,
-                           u8 *src,
-                           sector_t count,
-                           struct dm_bht_entry *entry) {
-    MemoryBhtTest *mbht = reinterpret_cast<MemoryBhtTest *>(mbht_instance);
-    mbht->Write(start, src, count);
-    dm_bht_write_completed(entry, 0);
-    return 0;
-  }
-
   static int ReadCallback(void *mbht_instance,
                           sector_t start,
                           u8 *dst,
@@ -99,52 +95,57 @@
 
  protected:
   // Creates a new dm_bht and sets it in the existing MemoryBht.
-  void NewBht(const unsigned int total_blocks,
-              const char *digest_algorithm,
-              const char *salt) {
-    bht_.reset(new dm_bht());
-    EXPECT_EQ(0, dm_bht_create(bht_.get(), total_blocks, digest_algorithm));
-    if (hash_data_.get() == NULL) {
-      sectors_ = dm_bht_sectors(bht_.get());
-      hash_data_.reset(new u8[to_bytes(sectors_)]);
-    }
-    dm_bht_set_write_cb(bht_.get(), MemoryBhtTest::WriteCallback);
-    dm_bht_set_read_cb(bht_.get(), MemoryBhtTest::ReadCallback);
-    if (salt)
-      dm_bht_set_salt(bht_.get(), salt);
-  }
-  void SetupBht(const unsigned int total_blocks,
-                const char *digest_algorithm,
-                const char *salt) {
-    NewBht(total_blocks, digest_algorithm, salt);
-
+  void SetupHash(const unsigned int total_blocks,
+		 const char *digest_algorithm,
+		 const char *salt,
+		 void *hash_data) {
+    struct dm_bht bht;
     u8 *data = (u8 *)my_memalign(PAGE_SIZE, PAGE_SIZE);
 
     memset(data, 0, PAGE_SIZE);
 
+    EXPECT_EQ(0, dm_bht_create(&bht, total_blocks, digest_algorithm));
+    if (salt)
+      dm_bht_set_salt(&bht, salt);
+    dm_bht_set_buffer(&bht, hash_data);
+
     unsigned int blocks = total_blocks;
     do {
-      EXPECT_EQ(dm_bht_store_block(bht_.get(), blocks - 1, data), 0);
+      EXPECT_EQ(dm_bht_store_block(&bht, blocks - 1, data), 0);
     } while (--blocks > 0);
 
-    dm_bht_set_read_cb(bht_.get(), dm_bht_zeroread_callback);
-    EXPECT_EQ(0, dm_bht_compute(bht_.get(), NULL));
-    EXPECT_EQ(0, dm_bht_sync(bht_.get(), reinterpret_cast<void *>(this)));
-    u8 digest[1024];
-    dm_bht_root_hexdigest(bht_.get(), digest, sizeof(digest));
-    LOG(INFO) << "MemoryBhtTest root is " << digest;
-    EXPECT_EQ(0, dm_bht_destroy(bht_.get()));
-    // bht is now dead and mbht_ is a prepared hash image
+    EXPECT_EQ(0, dm_bht_compute(&bht));
 
-    NewBht(total_blocks, digest_algorithm, salt);
+    u8 digest[1024];
+    dm_bht_root_hexdigest(&bht, digest, sizeof(digest));
+    LOG(INFO) << "MemoryBhtTest root is " << digest;
+
+    free(data);
+  }
+  void SetupBht(const unsigned int total_blocks,
+                const char *digest_algorithm,
+                const char *salt) {
+    bht_.reset(new dm_bht());
+
+    EXPECT_EQ(0, dm_bht_create(bht_.get(), total_blocks, digest_algorithm));
+       if (hash_data_.get() == NULL) {
+      sectors_ = dm_bht_sectors(bht_.get());
+      hash_data_.reset(new u8[to_bytes(sectors_)]);
+    }
+
+    if (salt)
+      dm_bht_set_salt(bht_.get(), salt);
+
+    SetupHash(total_blocks, digest_algorithm, salt, &hash_data_[0]);
+    dm_bht_set_read_cb(bht_.get(), MemoryBhtTest::ReadCallback);
 
     // Load the tree from the pre-populated hash data
+    unsigned int blocks;
     for (blocks = 0; blocks < total_blocks; blocks += bht_->node_count)
       EXPECT_GE(dm_bht_populate(bht_.get(),
                                 reinterpret_cast<void *>(this),
                                 blocks),
                 0);
-    free(data);
   }
 
   scoped_ptr<struct dm_bht> bht_;
diff --git a/file_hasher.cc b/file_hasher.cc
index e3b9edd..c9bda99 100644
--- a/file_hasher.cc
+++ b/file_hasher.cc
@@ -78,15 +78,19 @@
     LOG(ERROR) << "Could not create the BH tree";
     return false;
   }
+
+  sectors_ = dm_bht_sectors(&tree_);
+  hash_data_ = new u8[to_bytes(sectors_)];
+
   dm_bht_set_write_cb(&tree_, FileHasher::WriteCallback);
   // No reading is needed.
   dm_bht_set_read_cb(&tree_, dm_bht_zeroread_callback);
-
+  dm_bht_set_buffer(&tree_, hash_data_);
   return true;
 }
 
 bool FileHasher::Store() {
-        return !dm_bht_sync(&tree_, reinterpret_cast<void *>(destination_));
+  return destination_->WriteAt(to_bytes(sectors_), hash_data_, 0);
 }
 
 bool FileHasher::Hash() {
@@ -105,7 +109,7 @@
     }
     ++block;
   }
-  return !dm_bht_compute(&tree_, reinterpret_cast<void *>(destination_));
+  return !dm_bht_compute(&tree_);
 }
 
 void FileHasher::PrintTable(bool colocated) {
diff --git a/file_hasher.h b/file_hasher.h
index 142be69..007c434 100644
--- a/file_hasher.h
+++ b/file_hasher.h
@@ -25,7 +25,6 @@
                  block_limit_(0),
                  alg_(NULL) { }
   // TODO(wad) add initialized_ variable to check.
-  virtual ~FileHasher() { dm_bht_destroy(&tree_); }
   virtual bool Initialize(simple_file::File *source,
                           simple_file::File *destination,
                           unsigned int blocks,
@@ -52,7 +51,9 @@
   unsigned int block_limit_;
   const char *alg_;
   const char *salt_;
+  u8 *hash_data_;
   struct dm_bht tree_;
+  sector_t sectors_;
 };
 
 }  // namespace verity