summaryrefslogtreecommitdiff
path: root/fs/verity
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2023-01-28 01:15:29 +0300
committerEric Biggers <ebiggers@google.com>2023-01-28 01:46:31 +0300
commit5d0f0e57ed900917836385527ce5b122fa1425a3 (patch)
tree2a9dd0ba1351b2783a4febe87e98754e6b8472fe /fs/verity
parent245edf445c3421584f541307cd7a8cd847c3d8d7 (diff)
downloadlinux-5d0f0e57ed900917836385527ce5b122fa1425a3.tar.xz
fsverity: support verifying data from large folios
Try to make fs/verity/verify.c aware of large folios. This includes making fsverity_verify_bio() support the case where the bio contains large folios, and adding a function fsverity_verify_folio() which is the equivalent of fsverity_verify_page(). There's no way to actually test this with large folios yet, but I've tested that this doesn't cause any regressions. Signed-off-by: Eric Biggers <ebiggers@google.com> Link: https://lore.kernel.org/r/20230127221529.299560-1-ebiggers@kernel.org
Diffstat (limited to 'fs/verity')
-rw-r--r--fs/verity/verify.c43
1 files changed, 22 insertions, 21 deletions
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index e59ef9d0e21c..f50e3b5b52c9 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -266,20 +266,23 @@ out:
static bool
verify_data_blocks(struct inode *inode, struct fsverity_info *vi,
- struct ahash_request *req, struct page *data_page,
- unsigned int len, unsigned int offset,
- unsigned long max_ra_pages)
+ struct ahash_request *req, struct folio *data_folio,
+ size_t len, size_t offset, unsigned long max_ra_pages)
{
const unsigned int block_size = vi->tree_params.block_size;
- u64 pos = (u64)data_page->index << PAGE_SHIFT;
+ u64 pos = (u64)data_folio->index << PAGE_SHIFT;
if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offset, block_size)))
return false;
- if (WARN_ON_ONCE(!PageLocked(data_page) || PageUptodate(data_page)))
+ if (WARN_ON_ONCE(!folio_test_locked(data_folio) ||
+ folio_test_uptodate(data_folio)))
return false;
do {
- if (!verify_data_block(inode, vi, req, data_page,
- pos + offset, offset, max_ra_pages))
+ struct page *data_page =
+ folio_page(data_folio, offset >> PAGE_SHIFT);
+
+ if (!verify_data_block(inode, vi, req, data_page, pos + offset,
+ offset & ~PAGE_MASK, max_ra_pages))
return false;
offset += block_size;
len -= block_size;
@@ -288,21 +291,20 @@ verify_data_blocks(struct inode *inode, struct fsverity_info *vi,
}
/**
- * fsverity_verify_blocks() - verify data in a page
- * @page: the page containing the data to verify
- * @len: the length of the data to verify in the page
- * @offset: the offset of the data to verify in the page
+ * fsverity_verify_blocks() - verify data in a folio
+ * @folio: the folio containing the data to verify
+ * @len: the length of the data to verify in the folio
+ * @offset: the offset of the data to verify in the folio
*
* Verify data that has just been read from a verity file. The data must be
- * located in a pagecache page that is still locked and not yet uptodate. The
+ * located in a pagecache folio that is still locked and not yet uptodate. The
* length and offset of the data must be Merkle tree block size aligned.
*
* Return: %true if the data is valid, else %false.
*/
-bool fsverity_verify_blocks(struct page *page, unsigned int len,
- unsigned int offset)
+bool fsverity_verify_blocks(struct folio *folio, size_t len, size_t offset)
{
- struct inode *inode = page->mapping->host;
+ struct inode *inode = folio->mapping->host;
struct fsverity_info *vi = inode->i_verity_info;
struct ahash_request *req;
bool valid;
@@ -310,7 +312,7 @@ bool fsverity_verify_blocks(struct page *page, unsigned int len,
/* This allocation never fails, since it's mempool-backed. */
req = fsverity_alloc_hash_request(vi->tree_params.hash_alg, GFP_NOFS);
- valid = verify_data_blocks(inode, vi, req, page, len, offset, 0);
+ valid = verify_data_blocks(inode, vi, req, folio, len, offset, 0);
fsverity_free_hash_request(vi->tree_params.hash_alg, req);
@@ -338,8 +340,7 @@ void fsverity_verify_bio(struct bio *bio)
struct inode *inode = bio_first_page_all(bio)->mapping->host;
struct fsverity_info *vi = inode->i_verity_info;
struct ahash_request *req;
- struct bio_vec *bv;
- struct bvec_iter_all iter_all;
+ struct folio_iter fi;
unsigned long max_ra_pages = 0;
/* This allocation never fails, since it's mempool-backed. */
@@ -358,9 +359,9 @@ void fsverity_verify_bio(struct bio *bio)
max_ra_pages = bio->bi_iter.bi_size >> (PAGE_SHIFT + 2);
}
- bio_for_each_segment_all(bv, bio, iter_all) {
- if (!verify_data_blocks(inode, vi, req, bv->bv_page, bv->bv_len,
- bv->bv_offset, max_ra_pages)) {
+ bio_for_each_folio_all(fi, bio) {
+ if (!verify_data_blocks(inode, vi, req, fi.folio, fi.length,
+ fi.offset, max_ra_pages)) {
bio->bi_status = BLK_STS_IOERR;
break;
}