From e282124750ba405df0499a64cacdc0cf45472572 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Mon, 4 May 2020 10:55:19 -0700 Subject: [PATCH] ANDROID: Incremental fs: Fix issues with very large files Test: incfs_test passes Bug: 155590527 Signed-off-by: Paul Lawrence Change-Id: Iaecfcd40e8c089d11b34c7aff2090fbfe0c36219 (cherry picked from commit 3e4fa206ce8ae4d3141af7514cb5d3d813cd4290) --- fs/incfs/vfs.c | 7 ++- .../selftests/filesystems/incfs/incfs_test.c | 60 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c index a2932d3a4e8f..d2c82047dd7c 100644 --- a/fs/incfs/vfs.c +++ b/fs/incfs/vfs.c @@ -896,7 +896,8 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .mnt = mi->mi_backing_dir_path.mnt, .dentry = dentry }; - new_file = dentry_open(&path, O_RDWR | O_NOATIME, mi->mi_owner); + new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, + mi->mi_owner); if (IS_ERR(new_file)) { error = PTR_ERR(new_file); @@ -1904,8 +1905,8 @@ static int file_open(struct inode *inode, struct file *file) int err = 0; get_incfs_backing_path(file->f_path.dentry, &backing_path); - backing_file = dentry_open(&backing_path, O_RDWR | O_NOATIME, - mi->mi_owner); + backing_file = dentry_open( + &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); path_put(&backing_path); if (IS_ERR(backing_file)) { diff --git a/tools/testing/selftests/filesystems/incfs/incfs_test.c b/tools/testing/selftests/filesystems/incfs/incfs_test.c index 0fc4c04c514a..6809399eac97 100644 --- a/tools/testing/selftests/filesystems/incfs/incfs_test.c +++ b/tools/testing/selftests/filesystems/incfs/incfs_test.c @@ -2609,6 +2609,65 @@ failure: return TEST_FAILURE; } +static int large_file(char *mount_dir) +{ + char *backing_dir; + int cmd_fd = -1; + int i; + int result = TEST_FAILURE; + uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {}; + int block_count = 3LL * 1024 * 1024 * 1024 / INCFS_DATA_FILE_BLOCK_SIZE; + struct incfs_fill_block *block_buf = + calloc(block_count, sizeof(struct incfs_fill_block)); + struct incfs_fill_blocks fill_blocks = { + .count = block_count, + .fill_blocks = ptr_to_u64(block_buf), + }; + incfs_uuid_t id; + int fd; + + backing_dir = create_backing_dir(mount_dir); + if (!backing_dir) + goto failure; + + if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0) + goto failure; + + cmd_fd = open_commands_file(mount_dir); + if (cmd_fd < 0) + goto failure; + + if (emit_file(cmd_fd, NULL, "very_large_file", &id, + (uint64_t)block_count * INCFS_DATA_FILE_BLOCK_SIZE, + NULL) < 0) + goto failure; + + for (i = 0; i < block_count; i++) { + block_buf[i].compression = COMPRESSION_NONE; + block_buf[i].block_index = i; + block_buf[i].data_len = INCFS_DATA_FILE_BLOCK_SIZE; + block_buf[i].data = ptr_to_u64(data); + } + + fd = open_file_by_id(mount_dir, id, true); + if (fd < 0) + goto failure; + + if (ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks) != block_count) + goto failure; + + if (emit_file(cmd_fd, NULL, "very_very_large_file", &id, 1LL << 40, + NULL) < 0) + goto failure; + + result = TEST_SUCCESS; + +failure: + close(fd); + close(cmd_fd); + return result; +} + static char *setup_mount_dir() { struct stat st; @@ -2678,6 +2737,7 @@ int main(int argc, char *argv[]) MAKE_TEST(read_log_test), MAKE_TEST(get_blocks_test), MAKE_TEST(get_hash_blocks_test), + MAKE_TEST(large_file), }; #undef MAKE_TEST