]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/f2fs/verity.c
Merge tag 'audit-pr-20200226' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
[linux.git] / fs / f2fs / verity.c
index a401ef72bc82136b31dfdc8eca4cdcf5bc445dd1..d7d430a6f130555997847557794562a80c39b9e0 100644 (file)
@@ -222,12 +222,55 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf,
        return size;
 }
 
+/*
+ * Prefetch some pages from the file's Merkle tree.
+ *
+ * This is basically a stripped-down version of __do_page_cache_readahead()
+ * which works on pages past i_size.
+ */
+static void f2fs_merkle_tree_readahead(struct address_space *mapping,
+                                      pgoff_t start_index, unsigned long count)
+{
+       LIST_HEAD(pages);
+       unsigned int nr_pages = 0;
+       struct page *page;
+       pgoff_t index;
+       struct blk_plug plug;
+
+       for (index = start_index; index < start_index + count; index++) {
+               page = xa_load(&mapping->i_pages, index);
+               if (!page || xa_is_value(page)) {
+                       page = __page_cache_alloc(readahead_gfp_mask(mapping));
+                       if (!page)
+                               break;
+                       page->index = index;
+                       list_add(&page->lru, &pages);
+                       nr_pages++;
+               }
+       }
+       blk_start_plug(&plug);
+       f2fs_mpage_readpages(mapping, &pages, NULL, nr_pages, true);
+       blk_finish_plug(&plug);
+}
+
 static struct page *f2fs_read_merkle_tree_page(struct inode *inode,
-                                              pgoff_t index)
+                                              pgoff_t index,
+                                              unsigned long num_ra_pages)
 {
+       struct page *page;
+
        index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT;
 
-       return read_mapping_page(inode->i_mapping, index, NULL);
+       page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
+       if (!page || !PageUptodate(page)) {
+               if (page)
+                       put_page(page);
+               else if (num_ra_pages > 1)
+                       f2fs_merkle_tree_readahead(inode->i_mapping, index,
+                                                  num_ra_pages);
+               page = read_mapping_page(inode->i_mapping, index, NULL);
+       }
+       return page;
 }
 
 static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf,