.. | .. |
---|
113 | 113 | handle_t *handle; |
---|
114 | 114 | int err; |
---|
115 | 115 | |
---|
| 116 | + if (IS_DAX(inode) || ext4_test_inode_flag(inode, EXT4_INODE_DAX)) |
---|
| 117 | + return -EINVAL; |
---|
| 118 | + |
---|
116 | 119 | if (ext4_verity_in_progress(inode)) |
---|
117 | 120 | return -EBUSY; |
---|
118 | 121 | |
---|
.. | .. |
---|
198 | 201 | struct inode *inode = file_inode(filp); |
---|
199 | 202 | const int credits = 2; /* superblock and inode for ext4_orphan_del() */ |
---|
200 | 203 | handle_t *handle; |
---|
| 204 | + struct ext4_iloc iloc; |
---|
201 | 205 | int err = 0; |
---|
202 | | - int err2; |
---|
203 | | - |
---|
204 | | - if (desc != NULL) { |
---|
205 | | - /* Succeeded; write the verity descriptor. */ |
---|
206 | | - err = ext4_write_verity_descriptor(inode, desc, desc_size, |
---|
207 | | - merkle_tree_size); |
---|
208 | | - |
---|
209 | | - /* Write all pages before clearing VERITY_IN_PROGRESS. */ |
---|
210 | | - if (!err) |
---|
211 | | - err = filemap_write_and_wait(inode->i_mapping); |
---|
212 | | - } |
---|
213 | | - |
---|
214 | | - /* If we failed, truncate anything we wrote past i_size. */ |
---|
215 | | - if (desc == NULL || err) |
---|
216 | | - ext4_truncate(inode); |
---|
217 | 206 | |
---|
218 | 207 | /* |
---|
219 | | - * We must always clean up by clearing EXT4_STATE_VERITY_IN_PROGRESS and |
---|
220 | | - * deleting the inode from the orphan list, even if something failed. |
---|
221 | | - * If everything succeeded, we'll also set the verity bit in the same |
---|
222 | | - * transaction. |
---|
| 208 | + * If an error already occurred (which fs/verity/ signals by passing |
---|
| 209 | + * desc == NULL), then only clean-up is needed. |
---|
223 | 210 | */ |
---|
| 211 | + if (desc == NULL) |
---|
| 212 | + goto cleanup; |
---|
224 | 213 | |
---|
225 | | - ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); |
---|
| 214 | + /* Append the verity descriptor. */ |
---|
| 215 | + err = ext4_write_verity_descriptor(inode, desc, desc_size, |
---|
| 216 | + merkle_tree_size); |
---|
| 217 | + if (err) |
---|
| 218 | + goto cleanup; |
---|
| 219 | + |
---|
| 220 | + /* |
---|
| 221 | + * Write all pages (both data and verity metadata). Note that this must |
---|
| 222 | + * happen before clearing EXT4_STATE_VERITY_IN_PROGRESS; otherwise pages |
---|
| 223 | + * beyond i_size won't be written properly. For crash consistency, this |
---|
| 224 | + * also must happen before the verity inode flag gets persisted. |
---|
| 225 | + */ |
---|
| 226 | + err = filemap_write_and_wait(inode->i_mapping); |
---|
| 227 | + if (err) |
---|
| 228 | + goto cleanup; |
---|
| 229 | + |
---|
| 230 | + /* |
---|
| 231 | + * Finally, set the verity inode flag and remove the inode from the |
---|
| 232 | + * orphan list (in a single transaction). |
---|
| 233 | + */ |
---|
226 | 234 | |
---|
227 | 235 | handle = ext4_journal_start(inode, EXT4_HT_INODE, credits); |
---|
228 | 236 | if (IS_ERR(handle)) { |
---|
229 | | - ext4_orphan_del(NULL, inode); |
---|
230 | | - return PTR_ERR(handle); |
---|
| 237 | + err = PTR_ERR(handle); |
---|
| 238 | + goto cleanup; |
---|
231 | 239 | } |
---|
232 | 240 | |
---|
233 | | - err2 = ext4_orphan_del(handle, inode); |
---|
234 | | - if (err2) |
---|
235 | | - goto out_stop; |
---|
| 241 | + err = ext4_orphan_del(handle, inode); |
---|
| 242 | + if (err) |
---|
| 243 | + goto stop_and_cleanup; |
---|
236 | 244 | |
---|
237 | | - if (desc != NULL && !err) { |
---|
238 | | - struct ext4_iloc iloc; |
---|
| 245 | + err = ext4_reserve_inode_write(handle, inode, &iloc); |
---|
| 246 | + if (err) |
---|
| 247 | + goto stop_and_cleanup; |
---|
239 | 248 | |
---|
240 | | - err = ext4_reserve_inode_write(handle, inode, &iloc); |
---|
241 | | - if (err) |
---|
242 | | - goto out_stop; |
---|
243 | | - ext4_set_inode_flag(inode, EXT4_INODE_VERITY); |
---|
244 | | - ext4_set_inode_flags(inode); |
---|
245 | | - err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
---|
246 | | - } |
---|
247 | | -out_stop: |
---|
| 249 | + ext4_set_inode_flag(inode, EXT4_INODE_VERITY); |
---|
| 250 | + ext4_set_inode_flags(inode, false); |
---|
| 251 | + err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
---|
| 252 | + if (err) |
---|
| 253 | + goto stop_and_cleanup; |
---|
| 254 | + |
---|
248 | 255 | ext4_journal_stop(handle); |
---|
249 | | - return err ?: err2; |
---|
| 256 | + |
---|
| 257 | + ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); |
---|
| 258 | + return 0; |
---|
| 259 | + |
---|
| 260 | +stop_and_cleanup: |
---|
| 261 | + ext4_journal_stop(handle); |
---|
| 262 | +cleanup: |
---|
| 263 | + /* |
---|
| 264 | + * Verity failed to be enabled, so clean up by truncating any verity |
---|
| 265 | + * metadata that was written beyond i_size (both from cache and from |
---|
| 266 | + * disk), removing the inode from the orphan list (if it wasn't done |
---|
| 267 | + * already), and clearing EXT4_STATE_VERITY_IN_PROGRESS. |
---|
| 268 | + */ |
---|
| 269 | + truncate_inode_pages(inode->i_mapping, inode->i_size); |
---|
| 270 | + ext4_truncate(inode); |
---|
| 271 | + ext4_orphan_del(NULL, inode); |
---|
| 272 | + ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); |
---|
| 273 | + return err; |
---|
250 | 274 | } |
---|
251 | 275 | |
---|
252 | 276 | static int ext4_get_verity_descriptor_location(struct inode *inode, |
---|
.. | .. |
---|
342 | 366 | return desc_size; |
---|
343 | 367 | } |
---|
344 | 368 | |
---|
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 | | - rcu_read_lock(); |
---|
362 | | - page = radix_tree_lookup(&mapping->i_pages, index); |
---|
363 | | - rcu_read_unlock(); |
---|
364 | | - if (!page || radix_tree_exceptional_entry(page)) { |
---|
365 | | - page = __page_cache_alloc(readahead_gfp_mask(mapping)); |
---|
366 | | - if (!page) |
---|
367 | | - break; |
---|
368 | | - page->index = index; |
---|
369 | | - list_add(&page->lru, &pages); |
---|
370 | | - nr_pages++; |
---|
371 | | - } |
---|
372 | | - } |
---|
373 | | - blk_start_plug(&plug); |
---|
374 | | - ext4_mpage_readpages(mapping, &pages, NULL, nr_pages, true); |
---|
375 | | - blk_finish_plug(&plug); |
---|
376 | | -} |
---|
377 | | - |
---|
378 | 369 | static struct page *ext4_read_merkle_tree_page(struct inode *inode, |
---|
379 | 370 | pgoff_t index, |
---|
380 | 371 | unsigned long num_ra_pages) |
---|
.. | .. |
---|
385 | 376 | |
---|
386 | 377 | page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED); |
---|
387 | 378 | if (!page || !PageUptodate(page)) { |
---|
| 379 | + DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index); |
---|
| 380 | + |
---|
388 | 381 | if (page) |
---|
389 | 382 | put_page(page); |
---|
390 | 383 | else if (num_ra_pages > 1) |
---|
391 | | - ext4_merkle_tree_readahead(inode->i_mapping, index, |
---|
392 | | - num_ra_pages); |
---|
| 384 | + page_cache_ra_unbounded(&ractl, num_ra_pages, 0); |
---|
393 | 385 | page = read_mapping_page(inode->i_mapping, index, NULL); |
---|
394 | 386 | } |
---|
395 | 387 | return page; |
---|