@@ -179,7 +179,7 @@ static inline bool fsverity_uses_bitmap(const struct fsverity_info *vi,
int fsverity_read_merkle_tree_block(struct inode *inode,
const struct merkle_tree_params *params,
- u64 pos, unsigned long ra_bytes,
+ int level, u64 pos, unsigned long ra_bytes,
struct fsverity_blockbuf *block);
/*
@@ -43,7 +43,7 @@ static int fsverity_read_merkle_tree(struct inode *inode,
params->block_size - offs_in_block);
err = fsverity_read_merkle_tree_block(inode, &vi->tree_params,
- pos - offs_in_block, ra_bytes, &block);
+ -1, pos - offs_in_block, ra_bytes, &block);
if (err) {
fsverity_err(inode,
"Error %d reading Merkle tree block %llu",
@@ -184,8 +184,8 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi,
else
ra_bytes = 0;
- err = fsverity_read_merkle_tree_block(inode, params, hblock_pos,
- ra_bytes, block);
+ err = fsverity_read_merkle_tree_block(inode, params, level,
+ hblock_pos, ra_bytes, block);
if (err) {
fsverity_err(inode,
"Error %d reading Merkle tree block %llu",
@@ -406,6 +406,8 @@ EXPORT_SYMBOL_GPL(fsverity_invalidate_block);
* fsverity_read_merkle_tree_block() - read Merkle tree block
* @inode: inode to which this Merkle tree blocks belong
* @params: merkle tree parameters
+ * @level: expected level of the block; level 0 are the leaves, -1 means a
+ * streaming read
* @pos: byte position within merkle tree
* @ra_bytes: try to read ahead this many btes
* @block: block to be loaded
@@ -414,7 +416,7 @@ EXPORT_SYMBOL_GPL(fsverity_invalidate_block);
*/
int fsverity_read_merkle_tree_block(struct inode *inode,
const struct merkle_tree_params *params,
- u64 pos, unsigned long ra_bytes,
+ int level, u64 pos, unsigned long ra_bytes,
struct fsverity_blockbuf *block)
{
const struct fsverity_operations *vops = inode->i_sb->s_vop;
@@ -423,9 +425,20 @@ int fsverity_read_merkle_tree_block(struct inode *inode,
unsigned long index;
unsigned int offset_in_page;
- if (fsverity_caches_blocks(inode))
- return vops->read_merkle_tree_block(inode, pos, ra_bytes,
- params->log_blocksize, block);
+ block->offset = pos;
+ block->size = params->block_size;
+
+ if (fsverity_caches_blocks(inode)) {
+ struct fsverity_readmerkle req = {
+ .inode = inode,
+ .level = level,
+ .num_levels = params->num_levels,
+ .log_blocksize = params->log_blocksize,
+ .ra_bytes = ra_bytes,
+ };
+
+ return vops->read_merkle_tree_block(&req, block);
+ }
index = pos >> params->log_blocksize;
page_idx = round_down(index, params->blocks_per_page);
@@ -53,6 +53,26 @@ struct fsverity_blockbuf {
void *context;
};
+/**
+ * struct fsverity_readmerkle - Request to read a Merkle Tree block buffer
+ * @inode: the inode to read
+ * @level: expected level of the block; level 0 are the leaves, -1 means a
+ * streaming read
+ * @num_levels: number of levels in the tree total
+ * @log_blocksize: log2 of the size of the expected block
+ * @ra_bytes: The number of bytes that should be prefetched starting at pos
+ * if the page at @block->offset isn't already cached.
+ * Implementations may ignore this argument; it's only a
+ * performance optimization.
+ */
+struct fsverity_readmerkle {
+ struct inode *inode;
+ unsigned long ra_bytes;
+ int level;
+ int num_levels;
+ u8 log_blocksize;
+};
+
/* Verity operations for filesystems */
struct fsverity_operations {
@@ -139,13 +159,7 @@ struct fsverity_operations {
/**
* Read a Merkle tree block of the given inode.
- * @inode: the inode
- * @pos: byte offset of the block within the Merkle tree
- * @ra_bytes: The number of bytes that should be
- * prefetched starting at @pos if the page at @pos
- * isn't already cached. Implementations may ignore this
- * argument; it's only a performance optimization.
- * @log_blocksize: log2 of the size of the expected block
+ * @req: read request; see struct fsverity_readmerkle
* @block: block buffer for filesystem to point it to the block
*
* This can be called at any time on an open verity file. It may be
@@ -160,9 +174,7 @@ struct fsverity_operations {
*
* Return: 0 on success, -errno on failure
*/
- int (*read_merkle_tree_block)(struct inode *inode,
- u64 pos, unsigned long ra_bytes,
- unsigned int log_blocksize,
+ int (*read_merkle_tree_block)(const struct fsverity_readmerkle *req,
struct fsverity_blockbuf *block);
/**