1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * fs/ext4/verity.c: fs-verity support for ext4
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2019 Google LLC
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun * Implementation of fsverity_operations for ext4.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * ext4 stores the verity metadata (Merkle tree and fsverity_descriptor) past
12*4882a593Smuzhiyun * the end of the file, starting at the first 64K boundary beyond i_size. This
13*4882a593Smuzhiyun * approach works because (a) verity files are readonly, and (b) pages fully
14*4882a593Smuzhiyun * beyond i_size aren't visible to userspace but can be read/written internally
15*4882a593Smuzhiyun * by ext4 with only some relatively small changes to ext4. This approach
16*4882a593Smuzhiyun * avoids having to depend on the EA_INODE feature and on rearchitecturing
17*4882a593Smuzhiyun * ext4's xattr support to support paging multi-gigabyte xattrs into memory, and
18*4882a593Smuzhiyun * to support encrypting xattrs. Note that the verity metadata *must* be
19*4882a593Smuzhiyun * encrypted when the file is, since it contains hashes of the plaintext data.
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * Using a 64K boundary rather than a 4K one keeps things ready for
22*4882a593Smuzhiyun * architectures with 64K pages, and it doesn't necessarily waste space on-disk
23*4882a593Smuzhiyun * since there can be a hole between i_size and the start of the Merkle tree.
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include <linux/quotaops.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include "ext4.h"
29*4882a593Smuzhiyun #include "ext4_extents.h"
30*4882a593Smuzhiyun #include "ext4_jbd2.h"
31*4882a593Smuzhiyun
ext4_verity_metadata_pos(const struct inode * inode)32*4882a593Smuzhiyun static inline loff_t ext4_verity_metadata_pos(const struct inode *inode)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun return round_up(inode->i_size, 65536);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun * Read some verity metadata from the inode. __vfs_read() can't be used because
39*4882a593Smuzhiyun * we need to read beyond i_size.
40*4882a593Smuzhiyun */
pagecache_read(struct inode * inode,void * buf,size_t count,loff_t pos)41*4882a593Smuzhiyun static int pagecache_read(struct inode *inode, void *buf, size_t count,
42*4882a593Smuzhiyun loff_t pos)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun while (count) {
45*4882a593Smuzhiyun size_t n = min_t(size_t, count,
46*4882a593Smuzhiyun PAGE_SIZE - offset_in_page(pos));
47*4882a593Smuzhiyun struct page *page;
48*4882a593Smuzhiyun void *addr;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun page = read_mapping_page(inode->i_mapping, pos >> PAGE_SHIFT,
51*4882a593Smuzhiyun NULL);
52*4882a593Smuzhiyun if (IS_ERR(page))
53*4882a593Smuzhiyun return PTR_ERR(page);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun addr = kmap_atomic(page);
56*4882a593Smuzhiyun memcpy(buf, addr + offset_in_page(pos), n);
57*4882a593Smuzhiyun kunmap_atomic(addr);
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun put_page(page);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun buf += n;
62*4882a593Smuzhiyun pos += n;
63*4882a593Smuzhiyun count -= n;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun return 0;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /*
69*4882a593Smuzhiyun * Write some verity metadata to the inode for FS_IOC_ENABLE_VERITY.
70*4882a593Smuzhiyun * kernel_write() can't be used because the file descriptor is readonly.
71*4882a593Smuzhiyun */
pagecache_write(struct inode * inode,const void * buf,size_t count,loff_t pos)72*4882a593Smuzhiyun static int pagecache_write(struct inode *inode, const void *buf, size_t count,
73*4882a593Smuzhiyun loff_t pos)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun if (pos + count > inode->i_sb->s_maxbytes)
76*4882a593Smuzhiyun return -EFBIG;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun while (count) {
79*4882a593Smuzhiyun size_t n = min_t(size_t, count,
80*4882a593Smuzhiyun PAGE_SIZE - offset_in_page(pos));
81*4882a593Smuzhiyun struct page *page;
82*4882a593Smuzhiyun void *fsdata;
83*4882a593Smuzhiyun void *addr;
84*4882a593Smuzhiyun int res;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0,
87*4882a593Smuzhiyun &page, &fsdata);
88*4882a593Smuzhiyun if (res)
89*4882a593Smuzhiyun return res;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun addr = kmap_atomic(page);
92*4882a593Smuzhiyun memcpy(addr + offset_in_page(pos), buf, n);
93*4882a593Smuzhiyun kunmap_atomic(addr);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun res = pagecache_write_end(NULL, inode->i_mapping, pos, n, n,
96*4882a593Smuzhiyun page, fsdata);
97*4882a593Smuzhiyun if (res < 0)
98*4882a593Smuzhiyun return res;
99*4882a593Smuzhiyun if (res != n)
100*4882a593Smuzhiyun return -EIO;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun buf += n;
103*4882a593Smuzhiyun pos += n;
104*4882a593Smuzhiyun count -= n;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
ext4_begin_enable_verity(struct file * filp)109*4882a593Smuzhiyun static int ext4_begin_enable_verity(struct file *filp)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
112*4882a593Smuzhiyun const int credits = 2; /* superblock and inode for ext4_orphan_add() */
113*4882a593Smuzhiyun handle_t *handle;
114*4882a593Smuzhiyun int err;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun if (IS_DAX(inode) || ext4_test_inode_flag(inode, EXT4_INODE_DAX))
117*4882a593Smuzhiyun return -EINVAL;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (ext4_verity_in_progress(inode))
120*4882a593Smuzhiyun return -EBUSY;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /*
123*4882a593Smuzhiyun * Since the file was opened readonly, we have to initialize the jbd
124*4882a593Smuzhiyun * inode and quotas here and not rely on ->open() doing it. This must
125*4882a593Smuzhiyun * be done before evicting the inline data.
126*4882a593Smuzhiyun */
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun err = ext4_inode_attach_jinode(inode);
129*4882a593Smuzhiyun if (err)
130*4882a593Smuzhiyun return err;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun err = dquot_initialize(inode);
133*4882a593Smuzhiyun if (err)
134*4882a593Smuzhiyun return err;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun err = ext4_convert_inline_data(inode);
137*4882a593Smuzhiyun if (err)
138*4882a593Smuzhiyun return err;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
141*4882a593Smuzhiyun ext4_warning_inode(inode,
142*4882a593Smuzhiyun "verity is only allowed on extent-based files");
143*4882a593Smuzhiyun return -EOPNOTSUPP;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /*
147*4882a593Smuzhiyun * ext4 uses the last allocated block to find the verity descriptor, so
148*4882a593Smuzhiyun * we must remove any other blocks past EOF which might confuse things.
149*4882a593Smuzhiyun */
150*4882a593Smuzhiyun err = ext4_truncate(inode);
151*4882a593Smuzhiyun if (err)
152*4882a593Smuzhiyun return err;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun handle = ext4_journal_start(inode, EXT4_HT_INODE, credits);
155*4882a593Smuzhiyun if (IS_ERR(handle))
156*4882a593Smuzhiyun return PTR_ERR(handle);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun err = ext4_orphan_add(handle, inode);
159*4882a593Smuzhiyun if (err == 0)
160*4882a593Smuzhiyun ext4_set_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun ext4_journal_stop(handle);
163*4882a593Smuzhiyun return err;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun /*
167*4882a593Smuzhiyun * ext4 stores the verity descriptor beginning on the next filesystem block
168*4882a593Smuzhiyun * boundary after the Merkle tree. Then, the descriptor size is stored in the
169*4882a593Smuzhiyun * last 4 bytes of the last allocated filesystem block --- which is either the
170*4882a593Smuzhiyun * block in which the descriptor ends, or the next block after that if there
171*4882a593Smuzhiyun * weren't at least 4 bytes remaining.
172*4882a593Smuzhiyun *
173*4882a593Smuzhiyun * We can't simply store the descriptor in an xattr because it *must* be
174*4882a593Smuzhiyun * encrypted when ext4 encryption is used, but ext4 encryption doesn't encrypt
175*4882a593Smuzhiyun * xattrs. Also, if the descriptor includes a large signature blob it may be
176*4882a593Smuzhiyun * too large to store in an xattr without the EA_INODE feature.
177*4882a593Smuzhiyun */
ext4_write_verity_descriptor(struct inode * inode,const void * desc,size_t desc_size,u64 merkle_tree_size)178*4882a593Smuzhiyun static int ext4_write_verity_descriptor(struct inode *inode, const void *desc,
179*4882a593Smuzhiyun size_t desc_size, u64 merkle_tree_size)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun const u64 desc_pos = round_up(ext4_verity_metadata_pos(inode) +
182*4882a593Smuzhiyun merkle_tree_size, i_blocksize(inode));
183*4882a593Smuzhiyun const u64 desc_end = desc_pos + desc_size;
184*4882a593Smuzhiyun const __le32 desc_size_disk = cpu_to_le32(desc_size);
185*4882a593Smuzhiyun const u64 desc_size_pos = round_up(desc_end + sizeof(desc_size_disk),
186*4882a593Smuzhiyun i_blocksize(inode)) -
187*4882a593Smuzhiyun sizeof(desc_size_disk);
188*4882a593Smuzhiyun int err;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun err = pagecache_write(inode, desc, desc_size, desc_pos);
191*4882a593Smuzhiyun if (err)
192*4882a593Smuzhiyun return err;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun return pagecache_write(inode, &desc_size_disk, sizeof(desc_size_disk),
195*4882a593Smuzhiyun desc_size_pos);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
ext4_end_enable_verity(struct file * filp,const void * desc,size_t desc_size,u64 merkle_tree_size)198*4882a593Smuzhiyun static int ext4_end_enable_verity(struct file *filp, const void *desc,
199*4882a593Smuzhiyun size_t desc_size, u64 merkle_tree_size)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun struct inode *inode = file_inode(filp);
202*4882a593Smuzhiyun const int credits = 2; /* superblock and inode for ext4_orphan_del() */
203*4882a593Smuzhiyun handle_t *handle;
204*4882a593Smuzhiyun struct ext4_iloc iloc;
205*4882a593Smuzhiyun int err = 0;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * If an error already occurred (which fs/verity/ signals by passing
209*4882a593Smuzhiyun * desc == NULL), then only clean-up is needed.
210*4882a593Smuzhiyun */
211*4882a593Smuzhiyun if (desc == NULL)
212*4882a593Smuzhiyun goto cleanup;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* Append the verity descriptor. */
215*4882a593Smuzhiyun err = ext4_write_verity_descriptor(inode, desc, desc_size,
216*4882a593Smuzhiyun merkle_tree_size);
217*4882a593Smuzhiyun if (err)
218*4882a593Smuzhiyun goto cleanup;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /*
221*4882a593Smuzhiyun * Write all pages (both data and verity metadata). Note that this must
222*4882a593Smuzhiyun * happen before clearing EXT4_STATE_VERITY_IN_PROGRESS; otherwise pages
223*4882a593Smuzhiyun * beyond i_size won't be written properly. For crash consistency, this
224*4882a593Smuzhiyun * also must happen before the verity inode flag gets persisted.
225*4882a593Smuzhiyun */
226*4882a593Smuzhiyun err = filemap_write_and_wait(inode->i_mapping);
227*4882a593Smuzhiyun if (err)
228*4882a593Smuzhiyun goto cleanup;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /*
231*4882a593Smuzhiyun * Finally, set the verity inode flag and remove the inode from the
232*4882a593Smuzhiyun * orphan list (in a single transaction).
233*4882a593Smuzhiyun */
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun handle = ext4_journal_start(inode, EXT4_HT_INODE, credits);
236*4882a593Smuzhiyun if (IS_ERR(handle)) {
237*4882a593Smuzhiyun err = PTR_ERR(handle);
238*4882a593Smuzhiyun goto cleanup;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun err = ext4_orphan_del(handle, inode);
242*4882a593Smuzhiyun if (err)
243*4882a593Smuzhiyun goto stop_and_cleanup;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun err = ext4_reserve_inode_write(handle, inode, &iloc);
246*4882a593Smuzhiyun if (err)
247*4882a593Smuzhiyun goto stop_and_cleanup;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
250*4882a593Smuzhiyun ext4_set_inode_flags(inode, false);
251*4882a593Smuzhiyun err = ext4_mark_iloc_dirty(handle, inode, &iloc);
252*4882a593Smuzhiyun if (err)
253*4882a593Smuzhiyun goto stop_and_cleanup;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun ext4_journal_stop(handle);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
258*4882a593Smuzhiyun return 0;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun stop_and_cleanup:
261*4882a593Smuzhiyun ext4_journal_stop(handle);
262*4882a593Smuzhiyun cleanup:
263*4882a593Smuzhiyun /*
264*4882a593Smuzhiyun * Verity failed to be enabled, so clean up by truncating any verity
265*4882a593Smuzhiyun * metadata that was written beyond i_size (both from cache and from
266*4882a593Smuzhiyun * disk), removing the inode from the orphan list (if it wasn't done
267*4882a593Smuzhiyun * already), and clearing EXT4_STATE_VERITY_IN_PROGRESS.
268*4882a593Smuzhiyun */
269*4882a593Smuzhiyun truncate_inode_pages(inode->i_mapping, inode->i_size);
270*4882a593Smuzhiyun ext4_truncate(inode);
271*4882a593Smuzhiyun ext4_orphan_del(NULL, inode);
272*4882a593Smuzhiyun ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
273*4882a593Smuzhiyun return err;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
ext4_get_verity_descriptor_location(struct inode * inode,size_t * desc_size_ret,u64 * desc_pos_ret)276*4882a593Smuzhiyun static int ext4_get_verity_descriptor_location(struct inode *inode,
277*4882a593Smuzhiyun size_t *desc_size_ret,
278*4882a593Smuzhiyun u64 *desc_pos_ret)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun struct ext4_ext_path *path;
281*4882a593Smuzhiyun struct ext4_extent *last_extent;
282*4882a593Smuzhiyun u32 end_lblk;
283*4882a593Smuzhiyun u64 desc_size_pos;
284*4882a593Smuzhiyun __le32 desc_size_disk;
285*4882a593Smuzhiyun u32 desc_size;
286*4882a593Smuzhiyun u64 desc_pos;
287*4882a593Smuzhiyun int err;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /*
290*4882a593Smuzhiyun * Descriptor size is in last 4 bytes of last allocated block.
291*4882a593Smuzhiyun * See ext4_write_verity_descriptor().
292*4882a593Smuzhiyun */
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
295*4882a593Smuzhiyun EXT4_ERROR_INODE(inode, "verity file doesn't use extents");
296*4882a593Smuzhiyun return -EFSCORRUPTED;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
300*4882a593Smuzhiyun if (IS_ERR(path))
301*4882a593Smuzhiyun return PTR_ERR(path);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun last_extent = path[path->p_depth].p_ext;
304*4882a593Smuzhiyun if (!last_extent) {
305*4882a593Smuzhiyun EXT4_ERROR_INODE(inode, "verity file has no extents");
306*4882a593Smuzhiyun ext4_ext_drop_refs(path);
307*4882a593Smuzhiyun kfree(path);
308*4882a593Smuzhiyun return -EFSCORRUPTED;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun end_lblk = le32_to_cpu(last_extent->ee_block) +
312*4882a593Smuzhiyun ext4_ext_get_actual_len(last_extent);
313*4882a593Smuzhiyun desc_size_pos = (u64)end_lblk << inode->i_blkbits;
314*4882a593Smuzhiyun ext4_ext_drop_refs(path);
315*4882a593Smuzhiyun kfree(path);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun if (desc_size_pos < sizeof(desc_size_disk))
318*4882a593Smuzhiyun goto bad;
319*4882a593Smuzhiyun desc_size_pos -= sizeof(desc_size_disk);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun err = pagecache_read(inode, &desc_size_disk, sizeof(desc_size_disk),
322*4882a593Smuzhiyun desc_size_pos);
323*4882a593Smuzhiyun if (err)
324*4882a593Smuzhiyun return err;
325*4882a593Smuzhiyun desc_size = le32_to_cpu(desc_size_disk);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun /*
328*4882a593Smuzhiyun * The descriptor is stored just before the desc_size_disk, but starting
329*4882a593Smuzhiyun * on a filesystem block boundary.
330*4882a593Smuzhiyun */
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun if (desc_size > INT_MAX || desc_size > desc_size_pos)
333*4882a593Smuzhiyun goto bad;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun desc_pos = round_down(desc_size_pos - desc_size, i_blocksize(inode));
336*4882a593Smuzhiyun if (desc_pos < ext4_verity_metadata_pos(inode))
337*4882a593Smuzhiyun goto bad;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun *desc_size_ret = desc_size;
340*4882a593Smuzhiyun *desc_pos_ret = desc_pos;
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun bad:
344*4882a593Smuzhiyun EXT4_ERROR_INODE(inode, "verity file corrupted; can't find descriptor");
345*4882a593Smuzhiyun return -EFSCORRUPTED;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
ext4_get_verity_descriptor(struct inode * inode,void * buf,size_t buf_size)348*4882a593Smuzhiyun static int ext4_get_verity_descriptor(struct inode *inode, void *buf,
349*4882a593Smuzhiyun size_t buf_size)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun size_t desc_size = 0;
352*4882a593Smuzhiyun u64 desc_pos = 0;
353*4882a593Smuzhiyun int err;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun err = ext4_get_verity_descriptor_location(inode, &desc_size, &desc_pos);
356*4882a593Smuzhiyun if (err)
357*4882a593Smuzhiyun return err;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (buf_size) {
360*4882a593Smuzhiyun if (desc_size > buf_size)
361*4882a593Smuzhiyun return -ERANGE;
362*4882a593Smuzhiyun err = pagecache_read(inode, buf, desc_size, desc_pos);
363*4882a593Smuzhiyun if (err)
364*4882a593Smuzhiyun return err;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun return desc_size;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun
ext4_read_merkle_tree_page(struct inode * inode,pgoff_t index,unsigned long num_ra_pages)369*4882a593Smuzhiyun static struct page *ext4_read_merkle_tree_page(struct inode *inode,
370*4882a593Smuzhiyun pgoff_t index,
371*4882a593Smuzhiyun unsigned long num_ra_pages)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun struct page *page;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
378*4882a593Smuzhiyun if (!page || !PageUptodate(page)) {
379*4882a593Smuzhiyun DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (page)
382*4882a593Smuzhiyun put_page(page);
383*4882a593Smuzhiyun else if (num_ra_pages > 1)
384*4882a593Smuzhiyun page_cache_ra_unbounded(&ractl, num_ra_pages, 0);
385*4882a593Smuzhiyun page = read_mapping_page(inode->i_mapping, index, NULL);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun return page;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
ext4_write_merkle_tree_block(struct inode * inode,const void * buf,u64 index,int log_blocksize)390*4882a593Smuzhiyun static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf,
391*4882a593Smuzhiyun u64 index, int log_blocksize)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun loff_t pos = ext4_verity_metadata_pos(inode) + (index << log_blocksize);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun return pagecache_write(inode, buf, 1 << log_blocksize, pos);
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun const struct fsverity_operations ext4_verityops = {
399*4882a593Smuzhiyun .begin_enable_verity = ext4_begin_enable_verity,
400*4882a593Smuzhiyun .end_enable_verity = ext4_end_enable_verity,
401*4882a593Smuzhiyun .get_verity_descriptor = ext4_get_verity_descriptor,
402*4882a593Smuzhiyun .read_merkle_tree_page = ext4_read_merkle_tree_page,
403*4882a593Smuzhiyun .write_merkle_tree_block = ext4_write_merkle_tree_block,
404*4882a593Smuzhiyun };
405