@@ -180,7 +180,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",
@@ -185,8 +185,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",
@@ -403,6 +403,8 @@ void __init fsverity_init_workqueue(void)
* 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
@@ -411,7 +413,7 @@ void __init fsverity_init_workqueue(void)
*/
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;
@@ -420,10 +422,20 @@ int fsverity_read_merkle_tree_block(struct inode *inode,
unsigned long index;
unsigned int offset_in_page;
+ 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,
+ };
+
block->verified = false;
- return vops->read_merkle_tree_block(inode, pos, ra_bytes,
- params->log_blocksize, block);
+ return vops->read_merkle_tree_block(&req, block);
}
index = pos >> params->log_blocksize;
@@ -55,6 +55,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 {
@@ -141,13 +161,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
@@ -162,9 +176,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);
/**