Project import generated by Copybara.

GitOrigin-RevId: 0acb173e07e155358594d3ce7b5f19e91bb9fec3
diff --git a/fs/verity/Kconfig b/fs/verity/Kconfig
index 24d1b54..88fb251 100644
--- a/fs/verity/Kconfig
+++ b/fs/verity/Kconfig
@@ -3,13 +3,9 @@
 config FS_VERITY
 	bool "FS Verity (read-only file-based authenticity protection)"
 	select CRYPTO
-	# SHA-256 is implied as it's intended to be the default hash algorithm.
+	# SHA-256 is selected as it's intended to be the default hash algorithm.
 	# To avoid bloat, other wanted algorithms must be selected explicitly.
-	# Note that CRYPTO_SHA256 denotes the generic C implementation, but
-	# some architectures provided optimized implementations of the same
-	# algorithm that may be used instead. In this case, CRYPTO_SHA256 may
-	# be omitted even if SHA-256 is being used.
-	imply CRYPTO_SHA256
+	select CRYPTO_SHA256
 	help
 	  This option enables fs-verity.  fs-verity is the dm-verity
 	  mechanism implemented at the file level.  On supported
diff --git a/fs/verity/Makefile b/fs/verity/Makefile
index 435559a..570e913 100644
--- a/fs/verity/Makefile
+++ b/fs/verity/Makefile
@@ -5,7 +5,6 @@
 			   init.o \
 			   measure.o \
 			   open.o \
-			   read_metadata.o \
 			   verify.o
 
 obj-$(CONFIG_FS_VERITY_BUILTIN_SIGNATURES) += signature.o
diff --git a/fs/verity/enable.c b/fs/verity/enable.c
index d988e8c..eabc6ac 100644
--- a/fs/verity/enable.c
+++ b/fs/verity/enable.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Ioctl to enable verity on a file
+ * fs/verity/enable.c: ioctl to enable verity on a file
  *
  * Copyright 2019 Google LLC
  */
@@ -8,48 +8,18 @@
 #include "fsverity_private.h"
 
 #include <crypto/hash.h>
-#include <linux/backing-dev.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/sched/signal.h>
 #include <linux/uaccess.h>
 
-/*
- * Read a file data page for Merkle tree construction.  Do aggressive readahead,
- * since we're sequentially reading the entire file.
- */
-static struct page *read_file_data_page(struct file *filp, pgoff_t index,
-					struct file_ra_state *ra,
-					unsigned long remaining_pages)
-{
-	struct page *page;
-
-	page = find_get_page_flags(filp->f_mapping, index, FGP_ACCESSED);
-	if (!page || !PageUptodate(page)) {
-		if (page)
-			put_page(page);
-		else
-			page_cache_sync_readahead(filp->f_mapping, ra, filp,
-						  index, remaining_pages);
-		page = read_mapping_page(filp->f_mapping, index, NULL);
-		if (IS_ERR(page))
-			return page;
-	}
-	if (PageReadahead(page))
-		page_cache_async_readahead(filp->f_mapping, ra, filp, page,
-					   index, remaining_pages);
-	return page;
-}
-
-static int build_merkle_tree_level(struct file *filp, unsigned int level,
+static int build_merkle_tree_level(struct inode *inode, unsigned int level,
 				   u64 num_blocks_to_hash,
 				   const struct merkle_tree_params *params,
 				   u8 *pending_hashes,
 				   struct ahash_request *req)
 {
-	struct inode *inode = file_inode(filp);
 	const struct fsverity_operations *vops = inode->i_sb->s_vop;
-	struct file_ra_state ra = { 0 };
 	unsigned int pending_size = 0;
 	u64 dst_block_num;
 	u64 i;
@@ -66,8 +36,6 @@ static int build_merkle_tree_level(struct file *filp, unsigned int level,
 		dst_block_num = 0; /* unused */
 	}
 
-	file_ra_state_init(&ra, filp->f_mapping);
-
 	for (i = 0; i < num_blocks_to_hash; i++) {
 		struct page *src_page;
 
@@ -77,8 +45,7 @@ static int build_merkle_tree_level(struct file *filp, unsigned int level,
 
 		if (level == 0) {
 			/* Leaf: hashing a data block */
-			src_page = read_file_data_page(filp, i, &ra,
-						       num_blocks_to_hash - i);
+			src_page = read_mapping_page(inode->i_mapping, i, NULL);
 			if (IS_ERR(src_page)) {
 				err = PTR_ERR(src_page);
 				fsverity_err(inode,
@@ -87,14 +54,9 @@ static int build_merkle_tree_level(struct file *filp, unsigned int level,
 				return err;
 			}
 		} else {
-			unsigned long num_ra_pages =
-				min_t(unsigned long, num_blocks_to_hash - i,
-				      inode->i_sb->s_bdi->io_pages);
-
 			/* Non-leaf: hashing hash block from level below */
 			src_page = vops->read_merkle_tree_page(inode,
-					params->level_start[level - 1] + i,
-					num_ra_pages);
+					params->level_start[level - 1] + i);
 			if (IS_ERR(src_page)) {
 				err = PTR_ERR(src_page);
 				fsverity_err(inode,
@@ -141,18 +103,17 @@ static int build_merkle_tree_level(struct file *filp, unsigned int level,
 }
 
 /*
- * Build the Merkle tree for the given file using the given parameters, and
+ * Build the Merkle tree for the given inode using the given parameters, and
  * return the root hash in @root_hash.
  *
  * The tree is written to a filesystem-specific location as determined by the
  * ->write_merkle_tree_block() method.  However, the blocks that comprise the
  * tree are the same for all filesystems.
  */
-static int build_merkle_tree(struct file *filp,
+static int build_merkle_tree(struct inode *inode,
 			     const struct merkle_tree_params *params,
 			     u8 *root_hash)
 {
-	struct inode *inode = file_inode(filp);
 	u8 *pending_hashes;
 	struct ahash_request *req;
 	u64 blocks;
@@ -165,11 +126,9 @@ static int build_merkle_tree(struct file *filp,
 		return 0;
 	}
 
-	/* This allocation never fails, since it's mempool-backed. */
-	req = fsverity_alloc_hash_request(params->hash_alg, GFP_KERNEL);
-
 	pending_hashes = kmalloc(params->block_size, GFP_KERNEL);
-	if (!pending_hashes)
+	req = ahash_request_alloc(params->hash_alg->tfm, GFP_KERNEL);
+	if (!pending_hashes || !req)
 		goto out;
 
 	/*
@@ -177,10 +136,10 @@ static int build_merkle_tree(struct file *filp,
 	 * (level 0) and ascending to the root node (level 'num_levels - 1').
 	 * Then at the end (level 'num_levels'), calculate the root hash.
 	 */
-	blocks = ((u64)inode->i_size + params->block_size - 1) >>
+	blocks = (inode->i_size + params->block_size - 1) >>
 		 params->log_blocksize;
 	for (level = 0; level <= params->num_levels; level++) {
-		err = build_merkle_tree_level(filp, level, blocks, params,
+		err = build_merkle_tree_level(inode, level, blocks, params,
 					      pending_hashes, req);
 		if (err)
 			goto out;
@@ -191,7 +150,7 @@ static int build_merkle_tree(struct file *filp,
 	err = 0;
 out:
 	kfree(pending_hashes);
-	fsverity_free_hash_request(params->hash_alg, req);
+	ahash_request_free(req);
 	return err;
 }
 
@@ -216,7 +175,8 @@ static int enable_verity(struct file *filp,
 
 	/* Get the salt if the user provided one */
 	if (arg->salt_size &&
-	    copy_from_user(desc->salt, u64_to_user_ptr(arg->salt_ptr),
+	    copy_from_user(desc->salt,
+			   (const u8 __user *)(uintptr_t)arg->salt_ptr,
 			   arg->salt_size)) {
 		err = -EFAULT;
 		goto out;
@@ -225,7 +185,8 @@ static int enable_verity(struct file *filp,
 
 	/* Get the signature if the user provided one */
 	if (arg->sig_size &&
-	    copy_from_user(desc->signature, u64_to_user_ptr(arg->sig_ptr),
+	    copy_from_user(desc->signature,
+			   (const u8 __user *)(uintptr_t)arg->sig_ptr,
 			   arg->sig_size)) {
 		err = -EFAULT;
 		goto out;
@@ -266,7 +227,7 @@ static int enable_verity(struct file *filp,
 	 */
 	pr_debug("Building Merkle tree...\n");
 	BUILD_BUG_ON(sizeof(desc->root_hash) < FS_VERITY_MAX_DIGEST_SIZE);
-	err = build_merkle_tree(filp, &params, desc->root_hash);
+	err = build_merkle_tree(inode, &params, desc->root_hash);
 	if (err) {
 		fsverity_err(inode, "Error %d building Merkle tree", err);
 		goto rollback;
@@ -329,8 +290,6 @@ static int enable_verity(struct file *filp,
 
 /**
  * fsverity_ioctl_enable() - enable verity on a file
- * @filp: file to enable verity on
- * @uarg: user pointer to fsverity_enable_arg
  *
  * Enable fs-verity on a file.  See the "FS_IOC_ENABLE_VERITY" section of
  * Documentation/filesystems/fsverity.rst for the documentation.
@@ -398,9 +357,9 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
 	 * Some pages of the file may have been evicted from pagecache after
 	 * being used in the Merkle tree construction, then read into pagecache
 	 * again by another process reading from the file concurrently.  Since
-	 * these pages didn't undergo verification against the file digest which
-	 * fs-verity now claims to be enforcing, we have to wipe the pagecache
-	 * to ensure that all future reads are verified.
+	 * these pages didn't undergo verification against the file measurement
+	 * which fs-verity now claims to be enforcing, we have to wipe the
+	 * pagecache to ensure that all future reads are verified.
 	 */
 	filemap_write_and_wait(inode->i_mapping);
 	invalidate_inode_pages2(inode->i_mapping);
diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h
index a275cad..e74c79b 100644
--- a/fs/verity/fsverity_private.h
+++ b/fs/verity/fsverity_private.h
@@ -16,7 +16,6 @@
 
 #include <crypto/sha.h>
 #include <linux/fsverity.h>
-#include <linux/mempool.h>
 
 struct ahash_request;
 
@@ -38,12 +37,11 @@ struct fsverity_hash_alg {
 	const char *name;	  /* crypto API name, e.g. sha256 */
 	unsigned int digest_size; /* digest size in bytes, e.g. 32 for SHA-256 */
 	unsigned int block_size;  /* block size in bytes, e.g. 64 for SHA-256 */
-	mempool_t req_pool;	  /* mempool with a preallocated hash request */
 };
 
 /* Merkle tree parameters: hash algorithm, initial hash state, and topology */
 struct merkle_tree_params {
-	struct fsverity_hash_alg *hash_alg; /* the hash algorithm */
+	const struct fsverity_hash_alg *hash_alg; /* the hash algorithm */
 	const u8 *hashstate;		/* initial hash state or NULL */
 	unsigned int digest_size;	/* same as hash_alg->digest_size */
 	unsigned int block_size;	/* size of data and tree blocks */
@@ -52,7 +50,6 @@ struct merkle_tree_params {
 	unsigned int log_arity;		/* log2(hashes_per_block) */
 	unsigned int num_levels;	/* number of levels in Merkle tree */
 	u64 tree_size;			/* Merkle tree size in bytes */
-	unsigned long level0_blocks;	/* number of blocks in tree level 0 */
 
 	/*
 	 * Starting block index for each tree level, ordered from leaf level (0)
@@ -61,50 +58,76 @@ struct merkle_tree_params {
 	u64 level_start[FS_VERITY_MAX_LEVELS];
 };
 
-/*
+/**
  * fsverity_info - cached verity metadata for an inode
  *
  * When a verity file is first opened, an instance of this struct is allocated
  * and stored in ->i_verity_info; it remains until the inode is evicted.  It
  * caches information about the Merkle tree that's needed to efficiently verify
- * data read from the file.  It also caches the file digest.  The Merkle tree
- * pages themselves are not cached here, but the filesystem may cache them.
+ * data read from the file.  It also caches the file measurement.  The Merkle
+ * tree pages themselves are not cached here, but the filesystem may cache them.
  */
 struct fsverity_info {
 	struct merkle_tree_params tree_params;
 	u8 root_hash[FS_VERITY_MAX_DIGEST_SIZE];
-	u8 file_digest[FS_VERITY_MAX_DIGEST_SIZE];
+	u8 measurement[FS_VERITY_MAX_DIGEST_SIZE];
 	const struct inode *inode;
 };
 
+/*
+ * Merkle tree properties.  The file measurement is the hash of this structure
+ * excluding the signature and with the sig_size field set to 0.
+ */
+struct fsverity_descriptor {
+	__u8 version;		/* must be 1 */
+	__u8 hash_algorithm;	/* Merkle tree hash algorithm */
+	__u8 log_blocksize;	/* log2 of size of data and tree blocks */
+	__u8 salt_size;		/* size of salt in bytes; 0 if none */
+	__le32 sig_size;	/* size of signature in bytes; 0 if none */
+	__le64 data_size;	/* size of file the Merkle tree is built over */
+	__u8 root_hash[64];	/* Merkle tree root hash */
+	__u8 salt[32];		/* salt prepended to each hashed block */
+	__u8 __reserved[144];	/* must be 0's */
+	__u8 signature[];	/* optional PKCS#7 signature */
+};
+
 /* Arbitrary limit to bound the kmalloc() size.  Can be changed. */
 #define FS_VERITY_MAX_DESCRIPTOR_SIZE	16384
 
 #define FS_VERITY_MAX_SIGNATURE_SIZE	(FS_VERITY_MAX_DESCRIPTOR_SIZE - \
 					 sizeof(struct fsverity_descriptor))
 
+/*
+ * Format in which verity file measurements are signed.  This is the same as
+ * 'struct fsverity_digest', except here some magic bytes are prepended to
+ * provide some context about what is being signed in case the same key is used
+ * for non-fsverity purposes, and here the fields have fixed endianness.
+ */
+struct fsverity_signed_digest {
+	char magic[8];			/* must be "FSVerity" */
+	__le16 digest_algorithm;
+	__le16 digest_size;
+	__u8 digest[];
+};
+
 /* hash_algs.c */
 
 extern struct fsverity_hash_alg fsverity_hash_algs[];
 
-struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
-						unsigned int num);
-struct ahash_request *fsverity_alloc_hash_request(struct fsverity_hash_alg *alg,
-						  gfp_t gfp_flags);
-void fsverity_free_hash_request(struct fsverity_hash_alg *alg,
-				struct ahash_request *req);
-const u8 *fsverity_prepare_hash_state(struct fsverity_hash_alg *alg,
+const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
+						      unsigned int num);
+const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg,
 				      const u8 *salt, size_t salt_size);
 int fsverity_hash_page(const struct merkle_tree_params *params,
 		       const struct inode *inode,
 		       struct ahash_request *req, struct page *page, u8 *out);
-int fsverity_hash_buffer(struct fsverity_hash_alg *alg,
+int fsverity_hash_buffer(const struct fsverity_hash_alg *alg,
 			 const void *data, size_t size, u8 *out);
 void __init fsverity_check_hash_algs(void);
 
 /* init.c */
 
-void __printf(3, 4) __cold
+extern void __printf(3, 4) __cold
 fsverity_msg(const struct inode *inode, const char *level,
 	     const char *fmt, ...);
 
@@ -122,17 +145,12 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
 				     const u8 *salt, size_t salt_size);
 
 struct fsverity_info *fsverity_create_info(const struct inode *inode,
-					   struct fsverity_descriptor *desc,
-					   size_t desc_size);
+					   void *desc, size_t desc_size);
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi);
 
 void fsverity_free_info(struct fsverity_info *vi);
 
-int fsverity_get_descriptor(struct inode *inode,
-			    struct fsverity_descriptor **desc_ret,
-			    size_t *desc_size_ret);
-
 int __init fsverity_init_info_cache(void);
 void __init fsverity_exit_info_cache(void);
 
@@ -140,13 +158,15 @@ void __init fsverity_exit_info_cache(void);
 
 #ifdef CONFIG_FS_VERITY_BUILTIN_SIGNATURES
 int fsverity_verify_signature(const struct fsverity_info *vi,
-			      const u8 *signature, size_t sig_size);
+			      const struct fsverity_descriptor *desc,
+			      size_t desc_size);
 
 int __init fsverity_init_signature(void);
 #else /* !CONFIG_FS_VERITY_BUILTIN_SIGNATURES */
 static inline int
 fsverity_verify_signature(const struct fsverity_info *vi,
-			  const u8 *signature, size_t sig_size)
+			  const struct fsverity_descriptor *desc,
+			  size_t desc_size)
 {
 	return 0;
 }
diff --git a/fs/verity/hash_algs.c b/fs/verity/hash_algs.c
index 71d0fcc..31e6d7d 100644
--- a/fs/verity/hash_algs.c
+++ b/fs/verity/hash_algs.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * fs-verity hash algorithms
+ * fs/verity/hash_algs.c: fs-verity hash algorithms
  *
  * Copyright 2019 Google LLC
  */
@@ -24,8 +24,6 @@ struct fsverity_hash_alg fsverity_hash_algs[] = {
 	},
 };
 
-static DEFINE_MUTEX(fsverity_hash_alg_init_mutex);
-
 /**
  * fsverity_get_hash_alg() - validate and prepare a hash algorithm
  * @inode: optional inode for logging purposes
@@ -38,8 +36,8 @@ static DEFINE_MUTEX(fsverity_hash_alg_init_mutex);
  *
  * Return: pointer to the hash alg on success, else an ERR_PTR()
  */
-struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
-						unsigned int num)
+const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
+						      unsigned int num)
 {
 	struct fsverity_hash_alg *alg;
 	struct crypto_ahash *tfm;
@@ -52,15 +50,10 @@ struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
 	}
 	alg = &fsverity_hash_algs[num];
 
-	/* pairs with smp_store_release() below */
-	if (likely(smp_load_acquire(&alg->tfm) != NULL))
+	/* pairs with cmpxchg() below */
+	tfm = READ_ONCE(alg->tfm);
+	if (likely(tfm != NULL))
 		return alg;
-
-	mutex_lock(&fsverity_hash_alg_init_mutex);
-
-	if (alg->tfm != NULL)
-		goto out_unlock;
-
 	/*
 	 * Using the shash API would make things a bit simpler, but the ahash
 	 * API is preferable as it allows the use of crypto accelerators.
@@ -71,14 +64,12 @@ struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
 			fsverity_warn(inode,
 				      "Missing crypto API support for hash algorithm \"%s\"",
 				      alg->name);
-			alg = ERR_PTR(-ENOPKG);
-			goto out_unlock;
+			return ERR_PTR(-ENOPKG);
 		}
 		fsverity_err(inode,
 			     "Error allocating hash algorithm \"%s\": %ld",
 			     alg->name, PTR_ERR(tfm));
-		alg = ERR_CAST(tfm);
-		goto out_unlock;
+		return ERR_CAST(tfm);
 	}
 
 	err = -EINVAL;
@@ -87,61 +78,18 @@ struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
 	if (WARN_ON(alg->block_size != crypto_ahash_blocksize(tfm)))
 		goto err_free_tfm;
 
-	err = mempool_init_kmalloc_pool(&alg->req_pool, 1,
-					sizeof(struct ahash_request) +
-					crypto_ahash_reqsize(tfm));
-	if (err)
-		goto err_free_tfm;
-
 	pr_info("%s using implementation \"%s\"\n",
 		alg->name, crypto_ahash_driver_name(tfm));
 
-	/* pairs with smp_load_acquire() above */
-	smp_store_release(&alg->tfm, tfm);
-	goto out_unlock;
+	/* pairs with READ_ONCE() above */
+	if (cmpxchg(&alg->tfm, NULL, tfm) != NULL)
+		crypto_free_ahash(tfm);
+
+	return alg;
 
 err_free_tfm:
 	crypto_free_ahash(tfm);
-	alg = ERR_PTR(err);
-out_unlock:
-	mutex_unlock(&fsverity_hash_alg_init_mutex);
-	return alg;
-}
-
-/**
- * fsverity_alloc_hash_request() - allocate a hash request object
- * @alg: the hash algorithm for which to allocate the request
- * @gfp_flags: memory allocation flags
- *
- * This is mempool-backed, so this never fails if __GFP_DIRECT_RECLAIM is set in
- * @gfp_flags.  However, in that case this might need to wait for all
- * previously-allocated requests to be freed.  So to avoid deadlocks, callers
- * must never need multiple requests at a time to make forward progress.
- *
- * Return: the request object on success; NULL on failure (but see above)
- */
-struct ahash_request *fsverity_alloc_hash_request(struct fsverity_hash_alg *alg,
-						  gfp_t gfp_flags)
-{
-	struct ahash_request *req = mempool_alloc(&alg->req_pool, gfp_flags);
-
-	if (req)
-		ahash_request_set_tfm(req, alg->tfm);
-	return req;
-}
-
-/**
- * fsverity_free_hash_request() - free a hash request object
- * @alg: the hash algorithm
- * @req: the hash request object to free
- */
-void fsverity_free_hash_request(struct fsverity_hash_alg *alg,
-				struct ahash_request *req)
-{
-	if (req) {
-		ahash_request_zero(req);
-		mempool_free(req, &alg->req_pool);
-	}
+	return ERR_PTR(err);
 }
 
 /**
@@ -153,7 +101,7 @@ void fsverity_free_hash_request(struct fsverity_hash_alg *alg,
  * Return: NULL if the salt is empty, otherwise the kmalloc()'ed precomputed
  *	   initial hash state on success or an ERR_PTR() on failure.
  */
-const u8 *fsverity_prepare_hash_state(struct fsverity_hash_alg *alg,
+const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg,
 				      const u8 *salt, size_t salt_size)
 {
 	u8 *hashstate = NULL;
@@ -171,8 +119,11 @@ const u8 *fsverity_prepare_hash_state(struct fsverity_hash_alg *alg,
 	if (!hashstate)
 		return ERR_PTR(-ENOMEM);
 
-	/* This allocation never fails, since it's mempool-backed. */
-	req = fsverity_alloc_hash_request(alg, GFP_KERNEL);
+	req = ahash_request_alloc(alg->tfm, GFP_KERNEL);
+	if (!req) {
+		err = -ENOMEM;
+		goto err_free;
+	}
 
 	/*
 	 * Zero-pad the salt to the next multiple of the input size of the hash
@@ -207,7 +158,7 @@ const u8 *fsverity_prepare_hash_state(struct fsverity_hash_alg *alg,
 	if (err)
 		goto err_free;
 out:
-	fsverity_free_hash_request(alg, req);
+	ahash_request_free(req);
 	kfree(padded_salt);
 	return hashstate;
 
@@ -278,7 +229,7 @@ int fsverity_hash_page(const struct merkle_tree_params *params,
  *
  * Return: 0 on success, -errno on failure
  */
-int fsverity_hash_buffer(struct fsverity_hash_alg *alg,
+int fsverity_hash_buffer(const struct fsverity_hash_alg *alg,
 			 const void *data, size_t size, u8 *out)
 {
 	struct ahash_request *req;
@@ -286,8 +237,9 @@ int fsverity_hash_buffer(struct fsverity_hash_alg *alg,
 	DECLARE_CRYPTO_WAIT(wait);
 	int err;
 
-	/* This allocation never fails, since it's mempool-backed. */
-	req = fsverity_alloc_hash_request(alg, GFP_KERNEL);
+	req = ahash_request_alloc(alg->tfm, GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
 
 	sg_init_one(&sg, data, size);
 	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP |
@@ -297,7 +249,7 @@ int fsverity_hash_buffer(struct fsverity_hash_alg *alg,
 
 	err = crypto_wait_req(crypto_ahash_digest(req), &wait);
 
-	fsverity_free_hash_request(alg, req);
+	ahash_request_free(req);
 	return err;
 }
 
diff --git a/fs/verity/init.c b/fs/verity/init.c
index c98b701..94c104e 100644
--- a/fs/verity/init.c
+++ b/fs/verity/init.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * fs-verity module initialization and logging
+ * fs/verity/init.c: fs-verity module initialization and logging
  *
  * Copyright 2019 Google LLC
  */
diff --git a/fs/verity/measure.c b/fs/verity/measure.c
index f0d7b30..05049b6 100644
--- a/fs/verity/measure.c
+++ b/fs/verity/measure.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Ioctl to get a verity file's digest
+ * fs/verity/measure.c: ioctl to get a verity file's measurement
  *
  * Copyright 2019 Google LLC
  */
@@ -10,12 +10,10 @@
 #include <linux/uaccess.h>
 
 /**
- * fsverity_ioctl_measure() - get a verity file's digest
- * @filp: file to get digest of
- * @_uarg: user pointer to fsverity_digest
+ * fsverity_ioctl_measure() - get a verity file's measurement
  *
- * Retrieve the file digest that the kernel is enforcing for reads from a verity
- * file.  See the "FS_IOC_MEASURE_VERITY" section of
+ * Retrieve the file measurement that the kernel is enforcing for reads from a
+ * verity file.  See the "FS_IOC_MEASURE_VERITY" section of
  * Documentation/filesystems/fsverity.rst for the documentation.
  *
  * Return: 0 on success, -errno on failure
@@ -51,7 +49,7 @@ int fsverity_ioctl_measure(struct file *filp, void __user *_uarg)
 	if (copy_to_user(uarg, &arg, sizeof(arg)))
 		return -EFAULT;
 
-	if (copy_to_user(uarg->digest, vi->file_digest, hash_alg->digest_size))
+	if (copy_to_user(uarg->digest, vi->measurement, hash_alg->digest_size))
 		return -EFAULT;
 
 	return 0;
diff --git a/fs/verity/open.c b/fs/verity/open.c
index 92df87f..63d1004 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Opening fs-verity files
+ * fs/verity/open.c: opening fs-verity files
  *
  * Copyright 2019 Google LLC
  */
@@ -31,7 +31,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
 				     unsigned int log_blocksize,
 				     const u8 *salt, size_t salt_size)
 {
-	struct fsverity_hash_alg *hash_alg;
+	const struct fsverity_hash_alg *hash_alg;
 	int err;
 	u64 blocks;
 	u64 offset;
@@ -89,7 +89,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
 	 */
 
 	/* Compute number of levels and the number of blocks in each level */
-	blocks = ((u64)inode->i_size + params->block_size - 1) >> log_blocksize;
+	blocks = (inode->i_size + params->block_size - 1) >> log_blocksize;
 	pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks);
 	while (blocks > 1) {
 		if (params->num_levels >= FS_VERITY_MAX_LEVELS) {
@@ -102,7 +102,6 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
 		/* temporarily using level_start[] to store blocks in level */
 		params->level_start[params->num_levels++] = blocks;
 	}
-	params->level0_blocks = params->level_start[0];
 
 	/* Compute the starting block of each level */
 	offset = 0;
@@ -124,35 +123,63 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
 }
 
 /*
- * Compute the file digest by hashing the fsverity_descriptor excluding the
+ * Compute the file measurement by hashing the fsverity_descriptor excluding the
  * signature and with the sig_size field set to 0.
  */
-static int compute_file_digest(struct fsverity_hash_alg *hash_alg,
-			       struct fsverity_descriptor *desc,
-			       u8 *file_digest)
+static int compute_file_measurement(const struct fsverity_hash_alg *hash_alg,
+				    struct fsverity_descriptor *desc,
+				    u8 *measurement)
 {
 	__le32 sig_size = desc->sig_size;
 	int err;
 
 	desc->sig_size = 0;
-	err = fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), file_digest);
+	err = fsverity_hash_buffer(hash_alg, desc, sizeof(*desc), measurement);
 	desc->sig_size = sig_size;
 
 	return err;
 }
 
 /*
- * Create a new fsverity_info from the given fsverity_descriptor (with optional
- * appended signature), and check the signature if present.  The
- * fsverity_descriptor must have already undergone basic validation.
+ * Validate the given fsverity_descriptor and create a new fsverity_info from
+ * it.  The signature (if present) is also checked.
  */
 struct fsverity_info *fsverity_create_info(const struct inode *inode,
-					   struct fsverity_descriptor *desc,
-					   size_t desc_size)
+					   void *_desc, size_t desc_size)
 {
+	struct fsverity_descriptor *desc = _desc;
 	struct fsverity_info *vi;
 	int err;
 
+	if (desc_size < sizeof(*desc)) {
+		fsverity_err(inode, "Unrecognized descriptor size: %zu bytes",
+			     desc_size);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (desc->version != 1) {
+		fsverity_err(inode, "Unrecognized descriptor version: %u",
+			     desc->version);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) {
+		fsverity_err(inode, "Reserved bits set in descriptor");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (desc->salt_size > sizeof(desc->salt)) {
+		fsverity_err(inode, "Invalid salt_size: %u", desc->salt_size);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (le64_to_cpu(desc->data_size) != inode->i_size) {
+		fsverity_err(inode,
+			     "Wrong data_size: %llu (desc) != %lld (inode)",
+			     le64_to_cpu(desc->data_size), inode->i_size);
+		return ERR_PTR(-EINVAL);
+	}
+
 	vi = kmem_cache_zalloc(fsverity_info_cachep, GFP_KERNEL);
 	if (!vi)
 		return ERR_PTR(-ENOMEM);
@@ -171,18 +198,17 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 	memcpy(vi->root_hash, desc->root_hash, vi->tree_params.digest_size);
 
-	err = compute_file_digest(vi->tree_params.hash_alg, desc,
-				  vi->file_digest);
+	err = compute_file_measurement(vi->tree_params.hash_alg, desc,
+				       vi->measurement);
 	if (err) {
-		fsverity_err(inode, "Error %d computing file digest", err);
+		fsverity_err(inode, "Error %d computing file measurement", err);
 		goto out;
 	}
-	pr_debug("Computed file digest: %s:%*phN\n",
+	pr_debug("Computed file measurement: %s:%*phN\n",
 		 vi->tree_params.hash_alg->name,
-		 vi->tree_params.digest_size, vi->file_digest);
+		 vi->tree_params.digest_size, vi->measurement);
 
-	err = fsverity_verify_signature(vi, desc->signature,
-					le32_to_cpu(desc->sig_size));
+	err = fsverity_verify_signature(vi, desc, desc_size);
 out:
 	if (err) {
 		fsverity_free_info(vi);
@@ -194,20 +220,11 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
 	/*
-	 * Multiple tasks may race to set ->i_verity_info, so use
-	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
-	 * RELEASE barrier so that other tasks can ACQUIRE it.
+	 * Multiple processes may race to set ->i_verity_info, so use cmpxchg.
+	 * This pairs with the READ_ONCE() in fsverity_get_info().
 	 */
-	if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) {
-		/* Lost the race, so free the fsverity_info we allocated. */
+	if (cmpxchg(&inode->i_verity_info, NULL, vi) != NULL)
 		fsverity_free_info(vi);
-		/*
-		 * Afterwards, the caller may access ->i_verity_info directly,
-		 * so make sure to ACQUIRE the winning fsverity_info.
-		 */
-		(void)fsverity_get_info(inode);
-	}
 }
 
 void fsverity_free_info(struct fsverity_info *vi)
@@ -218,57 +235,15 @@ void fsverity_free_info(struct fsverity_info *vi)
 	kmem_cache_free(fsverity_info_cachep, vi);
 }
 
-static bool validate_fsverity_descriptor(struct inode *inode,
-					 const struct fsverity_descriptor *desc,
-					 size_t desc_size)
+/* Ensure the inode has an ->i_verity_info */
+static int ensure_verity_info(struct inode *inode)
 {
-	if (desc_size < sizeof(*desc)) {
-		fsverity_err(inode, "Unrecognized descriptor size: %zu bytes",
-			     desc_size);
-		return false;
-	}
-
-	if (desc->version != 1) {
-		fsverity_err(inode, "Unrecognized descriptor version: %u",
-			     desc->version);
-		return false;
-	}
-
-	if (memchr_inv(desc->__reserved, 0, sizeof(desc->__reserved))) {
-		fsverity_err(inode, "Reserved bits set in descriptor");
-		return false;
-	}
-
-	if (desc->salt_size > sizeof(desc->salt)) {
-		fsverity_err(inode, "Invalid salt_size: %u", desc->salt_size);
-		return false;
-	}
-
-	if (le64_to_cpu(desc->data_size) != inode->i_size) {
-		fsverity_err(inode,
-			     "Wrong data_size: %llu (desc) != %lld (inode)",
-			     le64_to_cpu(desc->data_size), inode->i_size);
-		return false;
-	}
-
-	if (le32_to_cpu(desc->sig_size) > desc_size - sizeof(*desc)) {
-		fsverity_err(inode, "Signature overflows verity descriptor");
-		return false;
-	}
-
-	return true;
-}
-
-/*
- * Read the inode's fsverity_descriptor (with optional appended signature) from
- * the filesystem, and do basic validation of it.
- */
-int fsverity_get_descriptor(struct inode *inode,
-			    struct fsverity_descriptor **desc_ret,
-			    size_t *desc_size_ret)
-{
-	int res;
+	struct fsverity_info *vi = fsverity_get_info(inode);
 	struct fsverity_descriptor *desc;
+	int res;
+
+	if (vi)
+		return 0;
 
 	res = inode->i_sb->s_vop->get_verity_descriptor(inode, NULL, 0);
 	if (res < 0) {
@@ -287,46 +262,20 @@ int fsverity_get_descriptor(struct inode *inode,
 	res = inode->i_sb->s_vop->get_verity_descriptor(inode, desc, res);
 	if (res < 0) {
 		fsverity_err(inode, "Error %d reading verity descriptor", res);
-		kfree(desc);
-		return res;
+		goto out_free_desc;
 	}
 
-	if (!validate_fsverity_descriptor(inode, desc, res)) {
-		kfree(desc);
-		return -EINVAL;
-	}
-
-	*desc_ret = desc;
-	*desc_size_ret = res;
-	return 0;
-}
-
-/* Ensure the inode has an ->i_verity_info */
-static int ensure_verity_info(struct inode *inode)
-{
-	struct fsverity_info *vi = fsverity_get_info(inode);
-	struct fsverity_descriptor *desc;
-	size_t desc_size;
-	int err;
-
-	if (vi)
-		return 0;
-
-	err = fsverity_get_descriptor(inode, &desc, &desc_size);
-	if (err)
-		return err;
-
-	vi = fsverity_create_info(inode, desc, desc_size);
+	vi = fsverity_create_info(inode, desc, res);
 	if (IS_ERR(vi)) {
-		err = PTR_ERR(vi);
+		res = PTR_ERR(vi);
 		goto out_free_desc;
 	}
 
 	fsverity_set_info(inode, vi);
-	err = 0;
+	res = 0;
 out_free_desc:
 	kfree(desc);
-	return err;
+	return res;
 }
 
 /**
@@ -380,7 +329,6 @@ EXPORT_SYMBOL_GPL(fsverity_prepare_setattr);
 
 /**
  * fsverity_cleanup_inode() - free the inode's verity info, if present
- * @inode: an inode being evicted
  *
  * Filesystems must call this on inode eviction to free ->i_verity_info.
  */
@@ -395,7 +343,7 @@ int __init fsverity_init_info_cache(void)
 {
 	fsverity_info_cachep = KMEM_CACHE_USERCOPY(fsverity_info,
 						   SLAB_RECLAIM_ACCOUNT,
-						   file_digest);
+						   measurement);
 	if (!fsverity_info_cachep)
 		return -ENOMEM;
 	return 0;
diff --git a/fs/verity/read_metadata.c b/fs/verity/read_metadata.c
deleted file mode 100644
index 7e2d0c7..0000000
--- a/fs/verity/read_metadata.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Ioctl to read verity metadata
- *
- * Copyright 2021 Google LLC
- */
-
-#include "fsverity_private.h"
-
-#include <linux/backing-dev.h>
-#include <linux/highmem.h>
-#include <linux/sched/signal.h>
-#include <linux/uaccess.h>
-
-static int fsverity_read_merkle_tree(struct inode *inode,
-				     const struct fsverity_info *vi,
-				     void __user *buf, u64 offset, int length)
-{
-	const struct fsverity_operations *vops = inode->i_sb->s_vop;
-	u64 end_offset;
-	unsigned int offs_in_page;
-	pgoff_t index, last_index;
-	int retval = 0;
-	int err = 0;
-
-	end_offset = min(offset + length, vi->tree_params.tree_size);
-	if (offset >= end_offset)
-		return 0;
-	offs_in_page = offset_in_page(offset);
-	last_index = (end_offset - 1) >> PAGE_SHIFT;
-
-	/*
-	 * Iterate through each Merkle tree page in the requested range and copy
-	 * the requested portion to userspace.  Note that the Merkle tree block
-	 * size isn't important here, as we are returning a byte stream; i.e.,
-	 * we can just work with pages even if the tree block size != PAGE_SIZE.
-	 */
-	for (index = offset >> PAGE_SHIFT; index <= last_index; index++) {
-		unsigned long num_ra_pages =
-			min_t(unsigned long, last_index - index + 1,
-			      inode->i_sb->s_bdi->io_pages);
-		unsigned int bytes_to_copy = min_t(u64, end_offset - offset,
-						   PAGE_SIZE - offs_in_page);
-		struct page *page;
-		const void *virt;
-
-		page = vops->read_merkle_tree_page(inode, index, num_ra_pages);
-		if (IS_ERR(page)) {
-			err = PTR_ERR(page);
-			fsverity_err(inode,
-				     "Error %d reading Merkle tree page %lu",
-				     err, index);
-			break;
-		}
-
-		virt = kmap(page);
-		if (copy_to_user(buf, virt + offs_in_page, bytes_to_copy)) {
-			kunmap(page);
-			put_page(page);
-			err = -EFAULT;
-			break;
-		}
-		kunmap(page);
-		put_page(page);
-
-		retval += bytes_to_copy;
-		buf += bytes_to_copy;
-		offset += bytes_to_copy;
-
-		if (fatal_signal_pending(current))  {
-			err = -EINTR;
-			break;
-		}
-		cond_resched();
-		offs_in_page = 0;
-	}
-	return retval ? retval : err;
-}
-
-/* Copy the requested portion of the buffer to userspace. */
-static int fsverity_read_buffer(void __user *dst, u64 offset, int length,
-				const void *src, size_t src_length)
-{
-	if (offset >= src_length)
-		return 0;
-	src += offset;
-	src_length -= offset;
-
-	length = min_t(size_t, length, src_length);
-
-	if (copy_to_user(dst, src, length))
-		return -EFAULT;
-
-	return length;
-}
-
-static int fsverity_read_descriptor(struct inode *inode,
-				    void __user *buf, u64 offset, int length)
-{
-	struct fsverity_descriptor *desc;
-	size_t desc_size;
-	int res;
-
-	res = fsverity_get_descriptor(inode, &desc, &desc_size);
-	if (res)
-		return res;
-
-	/* don't include the signature */
-	desc_size = offsetof(struct fsverity_descriptor, signature);
-	desc->sig_size = 0;
-
-	res = fsverity_read_buffer(buf, offset, length, desc, desc_size);
-
-	kfree(desc);
-	return res;
-}
-
-static int fsverity_read_signature(struct inode *inode,
-				   void __user *buf, u64 offset, int length)
-{
-	struct fsverity_descriptor *desc;
-	size_t desc_size;
-	int res;
-
-	res = fsverity_get_descriptor(inode, &desc, &desc_size);
-	if (res)
-		return res;
-
-	if (desc->sig_size == 0) {
-		res = -ENODATA;
-		goto out;
-	}
-
-	/*
-	 * Include only the signature.  Note that fsverity_get_descriptor()
-	 * already verified that sig_size is in-bounds.
-	 */
-	res = fsverity_read_buffer(buf, offset, length, desc->signature,
-				   le32_to_cpu(desc->sig_size));
-out:
-	kfree(desc);
-	return res;
-}
-
-/**
- * fsverity_ioctl_read_metadata() - read verity metadata from a file
- * @filp: file to read the metadata from
- * @uarg: user pointer to fsverity_read_metadata_arg
- *
- * Return: length read on success, 0 on EOF, -errno on failure
- */
-int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg)
-{
-	struct inode *inode = file_inode(filp);
-	const struct fsverity_info *vi;
-	struct fsverity_read_metadata_arg arg;
-	int length;
-	void __user *buf;
-
-	vi = fsverity_get_info(inode);
-	if (!vi)
-		return -ENODATA; /* not a verity file */
-	/*
-	 * Note that we don't have to explicitly check that the file is open for
-	 * reading, since verity files can only be opened for reading.
-	 */
-
-	if (copy_from_user(&arg, uarg, sizeof(arg)))
-		return -EFAULT;
-
-	if (arg.__reserved)
-		return -EINVAL;
-
-	/* offset + length must not overflow. */
-	if (arg.offset + arg.length < arg.offset)
-		return -EINVAL;
-
-	/* Ensure that the return value will fit in INT_MAX. */
-	length = min_t(u64, arg.length, INT_MAX);
-
-	buf = u64_to_user_ptr(arg.buf_ptr);
-
-	switch (arg.metadata_type) {
-	case FS_VERITY_METADATA_TYPE_MERKLE_TREE:
-		return fsverity_read_merkle_tree(inode, vi, buf, arg.offset,
-						 length);
-	case FS_VERITY_METADATA_TYPE_DESCRIPTOR:
-		return fsverity_read_descriptor(inode, buf, arg.offset, length);
-	case FS_VERITY_METADATA_TYPE_SIGNATURE:
-		return fsverity_read_signature(inode, buf, arg.offset, length);
-	default:
-		return -EINVAL;
-	}
-}
-EXPORT_SYMBOL_GPL(fsverity_ioctl_read_metadata);
diff --git a/fs/verity/signature.c b/fs/verity/signature.c
index e33f6c4..c8b2552 100644
--- a/fs/verity/signature.c
+++ b/fs/verity/signature.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Verification of builtin signatures
+ * fs/verity/signature.c: verification of builtin signatures
  *
  * Copyright 2019 Google LLC
  */
@@ -28,50 +28,22 @@ static struct key *fsverity_keyring;
 
 /**
  * fsverity_verify_signature() - check a verity file's signature
- * @vi: the file's fsverity_info
- * @signature: the file's built-in signature
- * @sig_size: size of signature in bytes, or 0 if no signature
  *
- * If the file includes a signature of its fs-verity file digest, verify it
- * against the certificates in the fs-verity keyring.
+ * If the file's fs-verity descriptor includes a signature of the file
+ * measurement, verify it against the certificates in the fs-verity keyring.
  *
  * Return: 0 on success (signature valid or not required); -errno on failure
  */
 int fsverity_verify_signature(const struct fsverity_info *vi,
-			      const u8 *signature, size_t sig_size)
+			      const struct fsverity_descriptor *desc,
+			      size_t desc_size)
 {
-	unsigned int digest_algorithm =
-		vi->tree_params.hash_alg - fsverity_hash_algs;
-
-	return __fsverity_verify_signature(vi->inode, signature, sig_size,
-					   vi->file_digest, digest_algorithm);
-}
-
-/**
- * __fsverity_verify_signature() - check a verity file's signature
- * @inode: the file's inode
- * @signature: the file's signature
- * @sig_size: size of @signature. Can be 0 if there is no signature
- * @file_digest: the file's digest
- * @digest_algorithm: the digest algorithm used
- *
- * Takes the file's digest and optional signature and verifies the signature
- * against the digest and the fs-verity keyring if appropriate
- *
- * Return: 0 on success (signature valid or not required); -errno on failure
- */
-int __fsverity_verify_signature(const struct inode *inode, const u8 *signature,
-				size_t sig_size, const u8 *file_digest,
-				unsigned int digest_algorithm)
-{
-	struct fsverity_formatted_digest *d;
-	struct fsverity_hash_alg *hash_alg = fsverity_get_hash_alg(inode,
-							digest_algorithm);
+	const struct inode *inode = vi->inode;
+	const struct fsverity_hash_alg *hash_alg = vi->tree_params.hash_alg;
+	const u32 sig_size = le32_to_cpu(desc->sig_size);
+	struct fsverity_signed_digest *d;
 	int err;
 
-	if (IS_ERR(hash_alg))
-		return PTR_ERR(hash_alg);
-
 	if (sig_size == 0) {
 		if (fsverity_require_signatures) {
 			fsverity_err(inode,
@@ -81,16 +53,22 @@ int __fsverity_verify_signature(const struct inode *inode, const u8 *signature,
 		return 0;
 	}
 
+	if (sig_size > desc_size - sizeof(*desc)) {
+		fsverity_err(inode, "Signature overflows verity descriptor");
+		return -EBADMSG;
+	}
+
 	d = kzalloc(sizeof(*d) + hash_alg->digest_size, GFP_KERNEL);
 	if (!d)
 		return -ENOMEM;
 	memcpy(d->magic, "FSVerity", 8);
 	d->digest_algorithm = cpu_to_le16(hash_alg - fsverity_hash_algs);
 	d->digest_size = cpu_to_le16(hash_alg->digest_size);
-	memcpy(d->digest, file_digest, hash_alg->digest_size);
+	memcpy(d->digest, vi->measurement, hash_alg->digest_size);
 
 	err = verify_pkcs7_signature(d, sizeof(*d) + hash_alg->digest_size,
-				     signature, sig_size, fsverity_keyring,
+				     desc->signature, sig_size,
+				     fsverity_keyring,
 				     VERIFYING_UNSPECIFIED_SIGNATURE,
 				     NULL, NULL);
 	kfree(d);
@@ -109,11 +87,10 @@ int __fsverity_verify_signature(const struct inode *inode, const u8 *signature,
 		return err;
 	}
 
-	pr_debug("Valid signature for file digest %s:%*phN\n",
-		 hash_alg->name, hash_alg->digest_size, file_digest);
+	pr_debug("Valid signature for file measurement %s:%*phN\n",
+		 hash_alg->name, hash_alg->digest_size, vi->measurement);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(__fsverity_verify_signature);
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *fsverity_sysctl_header;
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index 0adb970..3e8f2de 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Data verification functions, i.e. hooks for ->readpages()
+ * fs/verity/verify.c: data verification functions, i.e. hooks for ->readpages()
  *
  * Copyright 2019 Google LLC
  */
@@ -84,8 +84,7 @@ static inline int cmp_hashes(const struct fsverity_info *vi,
  * Return: true if the page is valid, else false.
  */
 static bool verify_page(struct inode *inode, const struct fsverity_info *vi,
-			struct ahash_request *req, struct page *data_page,
-			unsigned long level0_ra_pages)
+			struct ahash_request *req, struct page *data_page)
 {
 	const struct merkle_tree_params *params = &vi->tree_params;
 	const unsigned int hsize = params->digest_size;
@@ -118,8 +117,8 @@ static bool verify_page(struct inode *inode, const struct fsverity_info *vi,
 		pr_debug_ratelimited("Level %d: hindex=%lu, hoffset=%u\n",
 				     level, hindex, hoffset);
 
-		hpage = inode->i_sb->s_vop->read_merkle_tree_page(inode, hindex,
-				level == 0 ? level0_ra_pages : 0);
+		hpage = inode->i_sb->s_vop->read_merkle_tree_page(inode,
+								  hindex);
 		if (IS_ERR(hpage)) {
 			err = PTR_ERR(hpage);
 			fsverity_err(inode,
@@ -179,7 +178,6 @@ static bool verify_page(struct inode *inode, const struct fsverity_info *vi,
 
 /**
  * fsverity_verify_page() - verify a data page
- * @page: the page to verity
  *
  * Verify a page that has just been read from a verity file.  The page must be a
  * pagecache page that is still locked and not yet uptodate.
@@ -193,12 +191,13 @@ bool fsverity_verify_page(struct page *page)
 	struct ahash_request *req;
 	bool valid;
 
-	/* This allocation never fails, since it's mempool-backed. */
-	req = fsverity_alloc_hash_request(vi->tree_params.hash_alg, GFP_NOFS);
+	req = ahash_request_alloc(vi->tree_params.hash_alg->tfm, GFP_NOFS);
+	if (unlikely(!req))
+		return false;
 
-	valid = verify_page(inode, vi, req, page, 0);
+	valid = verify_page(inode, vi, req, page);
 
-	fsverity_free_hash_request(vi->tree_params.hash_alg, req);
+	ahash_request_free(req);
 
 	return valid;
 }
@@ -207,7 +206,6 @@ EXPORT_SYMBOL_GPL(fsverity_verify_page);
 #ifdef CONFIG_BLOCK
 /**
  * fsverity_verify_bio() - verify a 'read' bio that has just completed
- * @bio: the bio to verify
  *
  * Verify a set of pages that have just been read from a verity file.  The pages
  * must be pagecache pages that are still locked and not yet uptodate.  Pages
@@ -224,49 +222,31 @@ void fsverity_verify_bio(struct bio *bio)
 {
 	struct inode *inode = bio_first_page_all(bio)->mapping->host;
 	const struct fsverity_info *vi = inode->i_verity_info;
-	const struct merkle_tree_params *params = &vi->tree_params;
 	struct ahash_request *req;
 	struct bio_vec *bv;
 	struct bvec_iter_all iter_all;
-	unsigned long max_ra_pages = 0;
 
-	/* This allocation never fails, since it's mempool-backed. */
-	req = fsverity_alloc_hash_request(params->hash_alg, GFP_NOFS);
-
-	if (bio->bi_opf & REQ_RAHEAD) {
-		/*
-		 * If this bio is for data readahead, then we also do readahead
-		 * of the first (largest) level of the Merkle tree.  Namely,
-		 * when a Merkle tree page is read, we also try to piggy-back on
-		 * some additional pages -- up to 1/4 the number of data pages.
-		 *
-		 * This improves sequential read performance, as it greatly
-		 * reduces the number of I/O requests made to the Merkle tree.
-		 */
+	req = ahash_request_alloc(vi->tree_params.hash_alg->tfm, GFP_NOFS);
+	if (unlikely(!req)) {
 		bio_for_each_segment_all(bv, bio, iter_all)
-			max_ra_pages++;
-		max_ra_pages /= 4;
+			SetPageError(bv->bv_page);
+		return;
 	}
 
 	bio_for_each_segment_all(bv, bio, iter_all) {
 		struct page *page = bv->bv_page;
-		unsigned long level0_index = page->index >> params->log_arity;
-		unsigned long level0_ra_pages =
-			min(max_ra_pages, params->level0_blocks - level0_index);
 
-		if (!PageError(page) &&
-		    !verify_page(inode, vi, req, page, level0_ra_pages))
+		if (!PageError(page) && !verify_page(inode, vi, req, page))
 			SetPageError(page);
 	}
 
-	fsverity_free_hash_request(params->hash_alg, req);
+	ahash_request_free(req);
 }
 EXPORT_SYMBOL_GPL(fsverity_verify_bio);
 #endif /* CONFIG_BLOCK */
 
 /**
  * fsverity_enqueue_verify_work() - enqueue work on the fs-verity workqueue
- * @work: the work to enqueue
  *
  * Enqueue verification work for asynchronous processing.
  */