Skip to content

Commit c899437

Browse files
committed
Merge tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt
Pull fsverity updates from Eric Biggers: - Optimize fs-verity sequential read performance by implementing readahead of Merkle tree pages. This allows the Merkle tree to be read in larger chunks. - Optimize FS_IOC_ENABLE_VERITY performance in the uncached case by implementing readahead of data pages. - Allocate the hash requests from a mempool in order to eliminate the possibility of allocation failures during I/O. * tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: fs-verity: use u64_to_user_ptr() fs-verity: use mempool for hash requests fs-verity: implement readahead of Merkle tree pages fs-verity: implement readahead for FS_IOC_ENABLE_VERITY
2 parents f0d8744 + da3a3da commit c899437

File tree

10 files changed

+273
-67
lines changed

10 files changed

+273
-67
lines changed

fs/ext4/verity.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,55 @@ static int ext4_get_verity_descriptor(struct inode *inode, void *buf,
342342
return desc_size;
343343
}
344344

345+
/*
346+
* Prefetch some pages from the file's Merkle tree.
347+
*
348+
* This is basically a stripped-down version of __do_page_cache_readahead()
349+
* which works on pages past i_size.
350+
*/
351+
static void ext4_merkle_tree_readahead(struct address_space *mapping,
352+
pgoff_t start_index, unsigned long count)
353+
{
354+
LIST_HEAD(pages);
355+
unsigned int nr_pages = 0;
356+
struct page *page;
357+
pgoff_t index;
358+
struct blk_plug plug;
359+
360+
for (index = start_index; index < start_index + count; index++) {
361+
page = xa_load(&mapping->i_pages, index);
362+
if (!page || xa_is_value(page)) {
363+
page = __page_cache_alloc(readahead_gfp_mask(mapping));
364+
if (!page)
365+
break;
366+
page->index = index;
367+
list_add(&page->lru, &pages);
368+
nr_pages++;
369+
}
370+
}
371+
blk_start_plug(&plug);
372+
ext4_mpage_readpages(mapping, &pages, NULL, nr_pages, true);
373+
blk_finish_plug(&plug);
374+
}
375+
345376
static struct page *ext4_read_merkle_tree_page(struct inode *inode,
346-
pgoff_t index)
377+
pgoff_t index,
378+
unsigned long num_ra_pages)
347379
{
380+
struct page *page;
381+
348382
index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
349383

350-
return read_mapping_page(inode->i_mapping, index, NULL);
384+
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
385+
if (!page || !PageUptodate(page)) {
386+
if (page)
387+
put_page(page);
388+
else if (num_ra_pages > 1)
389+
ext4_merkle_tree_readahead(inode->i_mapping, index,
390+
num_ra_pages);
391+
page = read_mapping_page(inode->i_mapping, index, NULL);
392+
}
393+
return page;
351394
}
352395

353396
static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf,

fs/f2fs/data.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1881,7 +1881,7 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
18811881
* use ->readpage() or do the necessary surgery to decouple ->readpages()
18821882
* from read-ahead.
18831883
*/
1884-
static int f2fs_mpage_readpages(struct address_space *mapping,
1884+
int f2fs_mpage_readpages(struct address_space *mapping,
18851885
struct list_head *pages, struct page *page,
18861886
unsigned nr_pages, bool is_readahead)
18871887
{

fs/f2fs/f2fs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3229,6 +3229,9 @@ int f2fs_reserve_new_block(struct dnode_of_data *dn);
32293229
int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index);
32303230
int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from);
32313231
int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index);
3232+
int f2fs_mpage_readpages(struct address_space *mapping,
3233+
struct list_head *pages, struct page *page,
3234+
unsigned nr_pages, bool is_readahead);
32323235
struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
32333236
int op_flags, bool for_write);
32343237
struct page *f2fs_find_data_page(struct inode *inode, pgoff_t index);

fs/f2fs/verity.c

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,55 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
222222
return size;
223223
}
224224

225+
/*
226+
* Prefetch some pages from the file's Merkle tree.
227+
*
228+
* This is basically a stripped-down version of __do_page_cache_readahead()
229+
* which works on pages past i_size.
230+
*/
231+
static void f2fs_merkle_tree_readahead(struct address_space *mapping,
232+
pgoff_t start_index, unsigned long count)
233+
{
234+
LIST_HEAD(pages);
235+
unsigned int nr_pages = 0;
236+
struct page *page;
237+
pgoff_t index;
238+
struct blk_plug plug;
239+
240+
for (index = start_index; index < start_index + count; index++) {
241+
page = xa_load(&mapping->i_pages, index);
242+
if (!page || xa_is_value(page)) {
243+
page = __page_cache_alloc(readahead_gfp_mask(mapping));
244+
if (!page)
245+
break;
246+
page->index = index;
247+
list_add(&page->lru, &pages);
248+
nr_pages++;
249+
}
250+
}
251+
blk_start_plug(&plug);
252+
f2fs_mpage_readpages(mapping, &pages, NULL, nr_pages, true);
253+
blk_finish_plug(&plug);
254+
}
255+
225256
static struct page *f2fs_read_merkle_tree_page(struct inode *inode,
226-
pgoff_t index)
257+
pgoff_t index,
258+
unsigned long num_ra_pages)
227259
{
260+
struct page *page;
261+
228262
index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT;
229263

230-
return read_mapping_page(inode->i_mapping, index, NULL);
264+
page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
265+
if (!page || !PageUptodate(page)) {
266+
if (page)
267+
put_page(page);
268+
else if (num_ra_pages > 1)
269+
f2fs_merkle_tree_readahead(inode->i_mapping, index,
270+
num_ra_pages);
271+
page = read_mapping_page(inode->i_mapping, index, NULL);
272+
}
273+
return page;
231274
}
232275

233276
static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf,

fs/verity/enable.c

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,48 @@
88
#include "fsverity_private.h"
99

1010
#include <crypto/hash.h>
11+
#include <linux/backing-dev.h>
1112
#include <linux/mount.h>
1213
#include <linux/pagemap.h>
1314
#include <linux/sched/signal.h>
1415
#include <linux/uaccess.h>
1516

16-
static int build_merkle_tree_level(struct inode *inode, unsigned int level,
17+
/*
18+
* Read a file data page for Merkle tree construction. Do aggressive readahead,
19+
* since we're sequentially reading the entire file.
20+
*/
21+
static struct page *read_file_data_page(struct file *filp, pgoff_t index,
22+
struct file_ra_state *ra,
23+
unsigned long remaining_pages)
24+
{
25+
struct page *page;
26+
27+
page = find_get_page_flags(filp->f_mapping, index, FGP_ACCESSED);
28+
if (!page || !PageUptodate(page)) {
29+
if (page)
30+
put_page(page);
31+
else
32+
page_cache_sync_readahead(filp->f_mapping, ra, filp,
33+
index, remaining_pages);
34+
page = read_mapping_page(filp->f_mapping, index, NULL);
35+
if (IS_ERR(page))
36+
return page;
37+
}
38+
if (PageReadahead(page))
39+
page_cache_async_readahead(filp->f_mapping, ra, filp, page,
40+
index, remaining_pages);
41+
return page;
42+
}
43+
44+
static int build_merkle_tree_level(struct file *filp, unsigned int level,
1745
u64 num_blocks_to_hash,
1846
const struct merkle_tree_params *params,
1947
u8 *pending_hashes,
2048
struct ahash_request *req)
2149
{
50+
struct inode *inode = file_inode(filp);
2251
const struct fsverity_operations *vops = inode->i_sb->s_vop;
52+
struct file_ra_state ra = { 0 };
2353
unsigned int pending_size = 0;
2454
u64 dst_block_num;
2555
u64 i;
@@ -36,6 +66,8 @@ static int build_merkle_tree_level(struct inode *inode, unsigned int level,
3666
dst_block_num = 0; /* unused */
3767
}
3868

69+
file_ra_state_init(&ra, filp->f_mapping);
70+
3971
for (i = 0; i < num_blocks_to_hash; i++) {
4072
struct page *src_page;
4173

@@ -45,7 +77,8 @@ static int build_merkle_tree_level(struct inode *inode, unsigned int level,
4577

4678
if (level == 0) {
4779
/* Leaf: hashing a data block */
48-
src_page = read_mapping_page(inode->i_mapping, i, NULL);
80+
src_page = read_file_data_page(filp, i, &ra,
81+
num_blocks_to_hash - i);
4982
if (IS_ERR(src_page)) {
5083
err = PTR_ERR(src_page);
5184
fsverity_err(inode,
@@ -54,9 +87,14 @@ static int build_merkle_tree_level(struct inode *inode, unsigned int level,
5487
return err;
5588
}
5689
} else {
90+
unsigned long num_ra_pages =
91+
min_t(unsigned long, num_blocks_to_hash - i,
92+
inode->i_sb->s_bdi->io_pages);
93+
5794
/* Non-leaf: hashing hash block from level below */
5895
src_page = vops->read_merkle_tree_page(inode,
59-
params->level_start[level - 1] + i);
96+
params->level_start[level - 1] + i,
97+
num_ra_pages);
6098
if (IS_ERR(src_page)) {
6199
err = PTR_ERR(src_page);
62100
fsverity_err(inode,
@@ -103,17 +141,18 @@ static int build_merkle_tree_level(struct inode *inode, unsigned int level,
103141
}
104142

105143
/*
106-
* Build the Merkle tree for the given inode using the given parameters, and
144+
* Build the Merkle tree for the given file using the given parameters, and
107145
* return the root hash in @root_hash.
108146
*
109147
* The tree is written to a filesystem-specific location as determined by the
110148
* ->write_merkle_tree_block() method. However, the blocks that comprise the
111149
* tree are the same for all filesystems.
112150
*/
113-
static int build_merkle_tree(struct inode *inode,
151+
static int build_merkle_tree(struct file *filp,
114152
const struct merkle_tree_params *params,
115153
u8 *root_hash)
116154
{
155+
struct inode *inode = file_inode(filp);
117156
u8 *pending_hashes;
118157
struct ahash_request *req;
119158
u64 blocks;
@@ -126,9 +165,11 @@ static int build_merkle_tree(struct inode *inode,
126165
return 0;
127166
}
128167

168+
/* This allocation never fails, since it's mempool-backed. */
169+
req = fsverity_alloc_hash_request(params->hash_alg, GFP_KERNEL);
170+
129171
pending_hashes = kmalloc(params->block_size, GFP_KERNEL);
130-
req = ahash_request_alloc(params->hash_alg->tfm, GFP_KERNEL);
131-
if (!pending_hashes || !req)
172+
if (!pending_hashes)
132173
goto out;
133174

134175
/*
@@ -139,7 +180,7 @@ static int build_merkle_tree(struct inode *inode,
139180
blocks = (inode->i_size + params->block_size - 1) >>
140181
params->log_blocksize;
141182
for (level = 0; level <= params->num_levels; level++) {
142-
err = build_merkle_tree_level(inode, level, blocks, params,
183+
err = build_merkle_tree_level(filp, level, blocks, params,
143184
pending_hashes, req);
144185
if (err)
145186
goto out;
@@ -150,7 +191,7 @@ static int build_merkle_tree(struct inode *inode,
150191
err = 0;
151192
out:
152193
kfree(pending_hashes);
153-
ahash_request_free(req);
194+
fsverity_free_hash_request(params->hash_alg, req);
154195
return err;
155196
}
156197

@@ -175,8 +216,7 @@ static int enable_verity(struct file *filp,
175216

176217
/* Get the salt if the user provided one */
177218
if (arg->salt_size &&
178-
copy_from_user(desc->salt,
179-
(const u8 __user *)(uintptr_t)arg->salt_ptr,
219+
copy_from_user(desc->salt, u64_to_user_ptr(arg->salt_ptr),
180220
arg->salt_size)) {
181221
err = -EFAULT;
182222
goto out;
@@ -185,8 +225,7 @@ static int enable_verity(struct file *filp,
185225

186226
/* Get the signature if the user provided one */
187227
if (arg->sig_size &&
188-
copy_from_user(desc->signature,
189-
(const u8 __user *)(uintptr_t)arg->sig_ptr,
228+
copy_from_user(desc->signature, u64_to_user_ptr(arg->sig_ptr),
190229
arg->sig_size)) {
191230
err = -EFAULT;
192231
goto out;
@@ -227,7 +266,7 @@ static int enable_verity(struct file *filp,
227266
*/
228267
pr_debug("Building Merkle tree...\n");
229268
BUILD_BUG_ON(sizeof(desc->root_hash) < FS_VERITY_MAX_DIGEST_SIZE);
230-
err = build_merkle_tree(inode, &params, desc->root_hash);
269+
err = build_merkle_tree(filp, &params, desc->root_hash);
231270
if (err) {
232271
fsverity_err(inode, "Error %d building Merkle tree", err);
233272
goto rollback;

fs/verity/fsverity_private.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <crypto/sha.h>
1818
#include <linux/fsverity.h>
19+
#include <linux/mempool.h>
1920

2021
struct ahash_request;
2122

@@ -37,11 +38,12 @@ struct fsverity_hash_alg {
3738
const char *name; /* crypto API name, e.g. sha256 */
3839
unsigned int digest_size; /* digest size in bytes, e.g. 32 for SHA-256 */
3940
unsigned int block_size; /* block size in bytes, e.g. 64 for SHA-256 */
41+
mempool_t req_pool; /* mempool with a preallocated hash request */
4042
};
4143

4244
/* Merkle tree parameters: hash algorithm, initial hash state, and topology */
4345
struct merkle_tree_params {
44-
const struct fsverity_hash_alg *hash_alg; /* the hash algorithm */
46+
struct fsverity_hash_alg *hash_alg; /* the hash algorithm */
4547
const u8 *hashstate; /* initial hash state or NULL */
4648
unsigned int digest_size; /* same as hash_alg->digest_size */
4749
unsigned int block_size; /* size of data and tree blocks */
@@ -50,6 +52,7 @@ struct merkle_tree_params {
5052
unsigned int log_arity; /* log2(hashes_per_block) */
5153
unsigned int num_levels; /* number of levels in Merkle tree */
5254
u64 tree_size; /* Merkle tree size in bytes */
55+
unsigned long level0_blocks; /* number of blocks in tree level 0 */
5356

5457
/*
5558
* Starting block index for each tree level, ordered from leaf level (0)
@@ -114,14 +117,18 @@ struct fsverity_signed_digest {
114117

115118
extern struct fsverity_hash_alg fsverity_hash_algs[];
116119

117-
const struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
118-
unsigned int num);
119-
const u8 *fsverity_prepare_hash_state(const struct fsverity_hash_alg *alg,
120+
struct fsverity_hash_alg *fsverity_get_hash_alg(const struct inode *inode,
121+
unsigned int num);
122+
struct ahash_request *fsverity_alloc_hash_request(struct fsverity_hash_alg *alg,
123+
gfp_t gfp_flags);
124+
void fsverity_free_hash_request(struct fsverity_hash_alg *alg,
125+
struct ahash_request *req);
126+
const u8 *fsverity_prepare_hash_state(struct fsverity_hash_alg *alg,
120127
const u8 *salt, size_t salt_size);
121128
int fsverity_hash_page(const struct merkle_tree_params *params,
122129
const struct inode *inode,
123130
struct ahash_request *req, struct page *page, u8 *out);
124-
int fsverity_hash_buffer(const struct fsverity_hash_alg *alg,
131+
int fsverity_hash_buffer(struct fsverity_hash_alg *alg,
125132
const void *data, size_t size, u8 *out);
126133
void __init fsverity_check_hash_algs(void);
127134

0 commit comments

Comments
 (0)