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