| .. | .. |
|---|
| 79 | 79 | size_t n = min_t(size_t, count, |
|---|
| 80 | 80 | PAGE_SIZE - offset_in_page(pos)); |
|---|
| 81 | 81 | struct page *page; |
|---|
| 82 | | - void *fsdata; |
|---|
| 83 | | - void *addr; |
|---|
| 82 | + void *fsdata = NULL; |
|---|
| 84 | 83 | int res; |
|---|
| 85 | 84 | |
|---|
| 86 | 85 | res = pagecache_write_begin(NULL, inode->i_mapping, pos, n, 0, |
|---|
| .. | .. |
|---|
| 88 | 87 | if (res) |
|---|
| 89 | 88 | return res; |
|---|
| 90 | 89 | |
|---|
| 91 | | - addr = kmap_atomic(page); |
|---|
| 92 | | - memcpy(addr + offset_in_page(pos), buf, n); |
|---|
| 93 | | - kunmap_atomic(addr); |
|---|
| 90 | + memcpy_to_page(page, offset_in_page(pos), buf, n); |
|---|
| 94 | 91 | |
|---|
| 95 | 92 | res = pagecache_write_end(NULL, inode->i_mapping, pos, n, n, |
|---|
| 96 | 93 | page, fsdata); |
|---|
| .. | .. |
|---|
| 112 | 109 | const int credits = 2; /* superblock and inode for ext4_orphan_add() */ |
|---|
| 113 | 110 | handle_t *handle; |
|---|
| 114 | 111 | int err; |
|---|
| 112 | + |
|---|
| 113 | + if (IS_DAX(inode) || ext4_test_inode_flag(inode, EXT4_INODE_DAX)) |
|---|
| 114 | + return -EINVAL; |
|---|
| 115 | 115 | |
|---|
| 116 | 116 | if (ext4_verity_in_progress(inode)) |
|---|
| 117 | 117 | return -EBUSY; |
|---|
| .. | .. |
|---|
| 198 | 198 | struct inode *inode = file_inode(filp); |
|---|
| 199 | 199 | const int credits = 2; /* superblock and inode for ext4_orphan_del() */ |
|---|
| 200 | 200 | handle_t *handle; |
|---|
| 201 | + struct ext4_iloc iloc; |
|---|
| 201 | 202 | 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 | 203 | |
|---|
| 218 | 204 | /* |
|---|
| 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. |
|---|
| 205 | + * If an error already occurred (which fs/verity/ signals by passing |
|---|
| 206 | + * desc == NULL), then only clean-up is needed. |
|---|
| 223 | 207 | */ |
|---|
| 208 | + if (desc == NULL) |
|---|
| 209 | + goto cleanup; |
|---|
| 224 | 210 | |
|---|
| 225 | | - ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); |
|---|
| 211 | + /* Append the verity descriptor. */ |
|---|
| 212 | + err = ext4_write_verity_descriptor(inode, desc, desc_size, |
|---|
| 213 | + merkle_tree_size); |
|---|
| 214 | + if (err) |
|---|
| 215 | + goto cleanup; |
|---|
| 216 | + |
|---|
| 217 | + /* |
|---|
| 218 | + * Write all pages (both data and verity metadata). Note that this must |
|---|
| 219 | + * happen before clearing EXT4_STATE_VERITY_IN_PROGRESS; otherwise pages |
|---|
| 220 | + * beyond i_size won't be written properly. For crash consistency, this |
|---|
| 221 | + * also must happen before the verity inode flag gets persisted. |
|---|
| 222 | + */ |
|---|
| 223 | + err = filemap_write_and_wait(inode->i_mapping); |
|---|
| 224 | + if (err) |
|---|
| 225 | + goto cleanup; |
|---|
| 226 | + |
|---|
| 227 | + /* |
|---|
| 228 | + * Finally, set the verity inode flag and remove the inode from the |
|---|
| 229 | + * orphan list (in a single transaction). |
|---|
| 230 | + */ |
|---|
| 226 | 231 | |
|---|
| 227 | 232 | handle = ext4_journal_start(inode, EXT4_HT_INODE, credits); |
|---|
| 228 | 233 | if (IS_ERR(handle)) { |
|---|
| 229 | | - ext4_orphan_del(NULL, inode); |
|---|
| 230 | | - return PTR_ERR(handle); |
|---|
| 234 | + err = PTR_ERR(handle); |
|---|
| 235 | + goto cleanup; |
|---|
| 231 | 236 | } |
|---|
| 232 | 237 | |
|---|
| 233 | | - err2 = ext4_orphan_del(handle, inode); |
|---|
| 234 | | - if (err2) |
|---|
| 235 | | - goto out_stop; |
|---|
| 238 | + err = ext4_orphan_del(handle, inode); |
|---|
| 239 | + if (err) |
|---|
| 240 | + goto stop_and_cleanup; |
|---|
| 236 | 241 | |
|---|
| 237 | | - if (desc != NULL && !err) { |
|---|
| 238 | | - struct ext4_iloc iloc; |
|---|
| 242 | + err = ext4_reserve_inode_write(handle, inode, &iloc); |
|---|
| 243 | + if (err) |
|---|
| 244 | + goto stop_and_cleanup; |
|---|
| 239 | 245 | |
|---|
| 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: |
|---|
| 246 | + ext4_set_inode_flag(inode, EXT4_INODE_VERITY); |
|---|
| 247 | + ext4_set_inode_flags(inode, false); |
|---|
| 248 | + err = ext4_mark_iloc_dirty(handle, inode, &iloc); |
|---|
| 249 | + if (err) |
|---|
| 250 | + goto stop_and_cleanup; |
|---|
| 251 | + |
|---|
| 248 | 252 | ext4_journal_stop(handle); |
|---|
| 249 | | - return err ?: err2; |
|---|
| 253 | + |
|---|
| 254 | + ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); |
|---|
| 255 | + return 0; |
|---|
| 256 | + |
|---|
| 257 | +stop_and_cleanup: |
|---|
| 258 | + ext4_journal_stop(handle); |
|---|
| 259 | +cleanup: |
|---|
| 260 | + /* |
|---|
| 261 | + * Verity failed to be enabled, so clean up by truncating any verity |
|---|
| 262 | + * metadata that was written beyond i_size (both from cache and from |
|---|
| 263 | + * disk), removing the inode from the orphan list (if it wasn't done |
|---|
| 264 | + * already), and clearing EXT4_STATE_VERITY_IN_PROGRESS. |
|---|
| 265 | + */ |
|---|
| 266 | + truncate_inode_pages(inode->i_mapping, inode->i_size); |
|---|
| 267 | + ext4_truncate(inode); |
|---|
| 268 | + ext4_orphan_del(NULL, inode); |
|---|
| 269 | + ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS); |
|---|
| 270 | + return err; |
|---|
| 250 | 271 | } |
|---|
| 251 | 272 | |
|---|
| 252 | 273 | static int ext4_get_verity_descriptor_location(struct inode *inode, |
|---|
| .. | .. |
|---|
| 342 | 363 | return desc_size; |
|---|
| 343 | 364 | } |
|---|
| 344 | 365 | |
|---|
| 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 | 366 | static struct page *ext4_read_merkle_tree_page(struct inode *inode, |
|---|
| 379 | 367 | pgoff_t index, |
|---|
| 380 | 368 | unsigned long num_ra_pages) |
|---|
| .. | .. |
|---|
| 385 | 373 | |
|---|
| 386 | 374 | page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED); |
|---|
| 387 | 375 | if (!page || !PageUptodate(page)) { |
|---|
| 376 | + DEFINE_READAHEAD(ractl, NULL, inode->i_mapping, index); |
|---|
| 377 | + |
|---|
| 388 | 378 | if (page) |
|---|
| 389 | 379 | put_page(page); |
|---|
| 390 | 380 | else if (num_ra_pages > 1) |
|---|
| 391 | | - ext4_merkle_tree_readahead(inode->i_mapping, index, |
|---|
| 392 | | - num_ra_pages); |
|---|
| 381 | + page_cache_ra_unbounded(&ractl, num_ra_pages, 0); |
|---|
| 393 | 382 | page = read_mapping_page(inode->i_mapping, index, NULL); |
|---|
| 394 | 383 | } |
|---|
| 395 | 384 | return page; |
|---|