From e302f3a21b6554722c72787fddc4780c0280e88b Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Wed, 28 Jun 2023 13:17:03 -0700 Subject: [PATCH] ANDROID: incremental-fs: Make work with 16k pages Bug: 260919895 Test: incfs_test passes Signed-off-by: Paul Lawrence Change-Id: Ia4fbb6011930b085bc00a36851e9b0e8559d3dc5 (cherry picked from commit 5ac10739bcf2dae9220a7a39392aa41235bc64c2) --- fs/incfs/pseudo_files.c | 10 +++--- fs/incfs/verity.c | 8 ++--- fs/incfs/vfs.c | 67 ++++++++++++++++++++++------------------- 3 files changed, 45 insertions(+), 40 deletions(-) diff --git a/fs/incfs/pseudo_files.c b/fs/incfs/pseudo_files.c index 814d7063581a..eea115de98c7 100644 --- a/fs/incfs/pseudo_files.c +++ b/fs/incfs/pseudo_files.c @@ -1073,7 +1073,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, int rl_size; ssize_t result = 0; bool report_uid; - unsigned long page = 0; + void *page = 0; struct incfs_pending_read_info *reads_buf = NULL; struct incfs_pending_read_info2 *reads_buf2 = NULL; size_t record_size; @@ -1086,13 +1086,13 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, report_uid = mi->mi_options.report_uid; record_size = report_uid ? sizeof(*reads_buf2) : sizeof(*reads_buf); reads_to_collect = len / record_size; - reads_per_page = PAGE_SIZE / record_size; + reads_per_page = INCFS_DATA_FILE_BLOCK_SIZE / record_size; rl_size = READ_ONCE(mi->mi_log.rl_size); if (rl_size == 0) return 0; - page = __get_free_page(GFP_NOFS); + page = kzalloc(INCFS_DATA_FILE_BLOCK_SIZE, GFP_NOFS); if (!page) return -ENOMEM; @@ -1116,7 +1116,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, reads_collected; goto out; } - if (copy_to_user(buf, (void *)page, + if (copy_to_user(buf, page, reads_collected * record_size)) { result = total_reads_collected ? total_reads_collected * record_size : @@ -1133,7 +1133,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, result = total_reads_collected * record_size; *ppos = 0; out: - free_page(page); + kfree(page); return result; } diff --git a/fs/incfs/verity.c b/fs/incfs/verity.c index 562a8e774178..b49441a146d2 100644 --- a/fs/incfs/verity.c +++ b/fs/incfs/verity.c @@ -303,8 +303,8 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df, struct mem_range buf = {.len = INCFS_DATA_FILE_BLOCK_SIZE}; struct mem_range tmp = {.len = 2 * INCFS_DATA_FILE_BLOCK_SIZE}; - buf.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(buf.len)); - tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len)); + buf.data = (u8 *)kzalloc(buf.len, GFP_NOFS); + tmp.data = (u8 *)kzalloc(tmp.len, GFP_NOFS); if (!buf.data || !tmp.data) { error = -ENOMEM; goto out; @@ -372,8 +372,8 @@ static int incfs_build_merkle_tree(struct file *f, struct data_file *df, } out: - free_pages((unsigned long)tmp.data, get_order(tmp.len)); - free_pages((unsigned long)buf.data, get_order(buf.len)); + kfree(tmp.data); + kfree(buf.data); return error; } diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index 0c80779e99e9..7086135a4d7f 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -541,13 +541,15 @@ static int read_folio(struct file *f, struct folio *folio) struct page *page = &folio->page; loff_t offset = 0; loff_t size = 0; - ssize_t bytes_to_read = 0; - ssize_t read_result = 0; + ssize_t total_read = 0; struct data_file *df = get_incfs_data_file(f); int result = 0; void *page_start; int block_index; unsigned int delayed_min_us = 0; + struct mem_range tmp = { + .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE + }; if (!df) { SetPageError(page); @@ -561,32 +563,39 @@ static int read_folio(struct file *f, struct folio *folio) INCFS_DATA_FILE_BLOCK_SIZE; size = df->df_size; - if (offset < size) { - struct mem_range tmp = { - .len = 2 * INCFS_DATA_FILE_BLOCK_SIZE - }; - tmp.data = (u8 *)__get_free_pages(GFP_NOFS, get_order(tmp.len)); - if (!tmp.data) { - read_result = -ENOMEM; - goto err; - } - bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE); - - read_result = read_single_page_timeouts(df, f, block_index, - range(page_start, bytes_to_read), tmp, - &delayed_min_us); - - free_pages((unsigned long)tmp.data, get_order(tmp.len)); - } else { - bytes_to_read = 0; - read_result = 0; + tmp.data = kzalloc(tmp.len, GFP_NOFS); + if (!tmp.data) { + result = -ENOMEM; + goto err; } + while (offset + total_read < size) { + ssize_t bytes_to_read = min_t(loff_t, + size - offset - total_read, + INCFS_DATA_FILE_BLOCK_SIZE); + + result = read_single_page_timeouts(df, f, block_index, + range(page_start + total_read, bytes_to_read), + tmp, &delayed_min_us); + if (result < 0) + break; + + total_read += result; + block_index++; + + if (result < INCFS_DATA_FILE_BLOCK_SIZE) + break; + if (total_read == PAGE_SIZE) + break; + } + kfree(tmp.data); err: - if (read_result < 0) - result = read_result; - else if (read_result < PAGE_SIZE) - zero_user(page, read_result, PAGE_SIZE - read_result); + if (result < 0) + total_read = 0; + else + result = 0; + if (total_read < PAGE_SIZE) + zero_user(page, total_read, PAGE_SIZE - total_read); if (result == 0) SetPageUptodate(page); @@ -770,8 +779,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg) return -EFAULT; usr_fill_block_array = u64_to_user_ptr(fill_blocks.fill_blocks); - data_buf = (u8 *)__get_free_pages(GFP_NOFS | __GFP_COMP, - get_order(data_buf_size)); + data_buf = (u8 *)kzalloc(data_buf_size, GFP_NOFS); if (!data_buf) return -ENOMEM; @@ -806,8 +814,7 @@ static long ioctl_fill_blocks(struct file *f, void __user *arg) break; } - if (data_buf) - free_pages((unsigned long)data_buf, get_order(data_buf_size)); + kfree(data_buf); if (complete) handle_file_completed(f, df); @@ -1807,8 +1814,6 @@ struct dentry *incfs_mount_fs(struct file_system_type *type, int flags, sb->s_blocksize_bits = blksize_bits(sb->s_blocksize); sb->s_xattr = incfs_xattr_ops; - BUILD_BUG_ON(PAGE_SIZE != INCFS_DATA_FILE_BLOCK_SIZE); - if (!dev_name) { pr_err("incfs: Backing dir is not set, filesystem can't be mounted.\n"); error = -ENOENT;