xref: /linux/fs/verity/pagecache.c (revision 056a5087d87ead77dedbe9cf5bde53b7cd4b4651)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2019 Google LLC
4  */
5 #include "fsverity_private.h"
6 
7 #include <linux/export.h>
8 #include <linux/fsverity.h>
9 #include <linux/pagemap.h>
10 
11 /**
12  * generic_read_merkle_tree_page - generic ->read_merkle_tree_page helper
13  * @inode:	inode containing the Merkle tree
14  * @index:	0-based index of the Merkle tree page in the inode
15  *
16  * The caller needs to adjust @index from the Merkle-tree relative index passed
17  * to ->read_merkle_tree_page to the actual index where the Merkle tree is
18  * stored in the page cache for @inode.
19  */
20 struct page *generic_read_merkle_tree_page(struct inode *inode, pgoff_t index)
21 {
22 	struct folio *folio;
23 
24 	folio = read_mapping_folio(inode->i_mapping, index, NULL);
25 	if (IS_ERR(folio))
26 		return ERR_CAST(folio);
27 	return folio_file_page(folio, index);
28 }
29 EXPORT_SYMBOL_GPL(generic_read_merkle_tree_page);
30 
31 /**
32  * generic_readahead_merkle_tree() - generic ->readahead_merkle_tree helper
33  * @inode:	inode containing the Merkle tree
34  * @index:	0-based index of the first Merkle tree page to read ahead in the
35  *		inode
36  * @nr_pages:	the number of Merkle tree pages that should be read ahead
37  *
38  * The caller needs to adjust @index from the Merkle-tree relative index passed
39  * to ->read_merkle_tree_page to the actual index where the Merkle tree is
40  * stored in the page cache for @inode.
41  */
42 void generic_readahead_merkle_tree(struct inode *inode, pgoff_t index,
43 				   unsigned long nr_pages)
44 {
45 	struct folio *folio;
46 
47 	lockdep_assert_held(&inode->i_mapping->invalidate_lock);
48 
49 	folio = __filemap_get_folio(inode->i_mapping, index, FGP_ACCESSED, 0);
50 	if (folio == ERR_PTR(-ENOENT) ||
51 	    (!IS_ERR(folio) && !folio_test_uptodate(folio))) {
52 		DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
53 
54 		page_cache_ra_unbounded(&ractl, nr_pages, 0);
55 	}
56 	if (!IS_ERR(folio))
57 		folio_put(folio);
58 }
59 EXPORT_SYMBOL_GPL(generic_readahead_merkle_tree);
60 
61 /**
62  * fsverity_fill_zerohash() - fill folio with hashes of zero data block
63  * @folio:	folio to fill
64  * @offset:	offset in the folio to start
65  * @len:	length of the range to fill with hashes
66  * @vi:		fsverity info
67  */
68 void fsverity_fill_zerohash(struct folio *folio, size_t offset, size_t len,
69 			      struct fsverity_info *vi)
70 {
71 	size_t off = offset;
72 
73 	WARN_ON_ONCE(!IS_ALIGNED(offset, vi->tree_params.digest_size));
74 	WARN_ON_ONCE(!IS_ALIGNED(len, vi->tree_params.digest_size));
75 
76 	for (; off < (offset + len); off += vi->tree_params.digest_size)
77 		memcpy_to_folio(folio, off, vi->tree_params.zero_digest,
78 				vi->tree_params.digest_size);
79 }
80 EXPORT_SYMBOL_GPL(fsverity_fill_zerohash);
81