From 467d1f63e3baf0550e6524df58fd56adb974705b Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Fri, 3 Apr 2020 10:36:30 -0700 Subject: [PATCH] ANDROID: Incremental fs: Optimize get_filled_block This led to a 20x speed improvement on QEMU. 512 is somewhat arbitrary - most of the gains are already there reading 64 records at a time, but since the record size is 10 bytes, 512 is just over a page and seems a good choice. Bug: 153170997 Test: incfs_test passes. Adding logging to incfs_get_filled_blocks to measure performance shows a 20x improvement Signed-off-by: Paul Lawrence Change-Id: Ifb2da77cfd8c9d653c7047ba1eb7f39d795fa1c2 --- fs/incfs/data_mgmt.c | 57 ++++++++++++++++++++++++++++++++++---------- fs/incfs/format.c | 19 +++++++++++---- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c index eac949243fd9..193323ec6cd0 100644 --- a/fs/incfs/data_mgmt.c +++ b/fs/incfs/data_mgmt.c @@ -347,13 +347,28 @@ static bool is_data_block_present(struct data_file_block *block) (block->db_stored_size != 0); } +static void convert_data_file_block(struct incfs_blockmap_entry *bme, + struct data_file_block *res_block) +{ + u16 flags = le16_to_cpu(bme->me_flags); + + res_block->db_backing_file_data_offset = + le16_to_cpu(bme->me_data_offset_hi); + res_block->db_backing_file_data_offset <<= 32; + res_block->db_backing_file_data_offset |= + le32_to_cpu(bme->me_data_offset_lo); + res_block->db_stored_size = le16_to_cpu(bme->me_data_size); + res_block->db_comp_alg = (flags & INCFS_BLOCK_COMPRESSED_LZ4) ? + COMPRESSION_LZ4 : + COMPRESSION_NONE; +} + static int get_data_file_block(struct data_file *df, int index, struct data_file_block *res_block) { struct incfs_blockmap_entry bme = {}; struct backing_file_context *bfc = NULL; loff_t blockmap_off = 0; - u16 flags = 0; int error = 0; if (!df || !res_block) @@ -369,16 +384,7 @@ static int get_data_file_block(struct data_file *df, int index, if (error) return error; - flags = le16_to_cpu(bme.me_flags); - res_block->db_backing_file_data_offset = - le16_to_cpu(bme.me_data_offset_hi); - res_block->db_backing_file_data_offset <<= 32; - res_block->db_backing_file_data_offset |= - le32_to_cpu(bme.me_data_offset_lo); - res_block->db_stored_size = le16_to_cpu(bme.me_data_size); - res_block->db_comp_alg = (flags & INCFS_BLOCK_COMPRESSED_LZ4) ? - COMPRESSION_LZ4 : - COMPRESSION_NONE; + convert_data_file_block(&bme, res_block); return 0; } @@ -432,6 +438,7 @@ static int update_file_header_flags(struct data_file *df, u32 bits_to_reset, return result; } +#define READ_BLOCKMAP_ENTRIES 512 int incfs_get_filled_blocks(struct data_file *df, struct incfs_get_filled_blocks_args *arg) { @@ -443,6 +450,9 @@ int incfs_get_filled_blocks(struct data_file *df, u32 end_index = arg->end_index ? arg->end_index : df->df_total_block_count; u32 *size_out = &arg->range_buffer_size_out; + int i = READ_BLOCKMAP_ENTRIES - 1; + int entries_read = 0; + struct incfs_blockmap_entry *bme; *size_out = 0; if (end_index > df->df_total_block_count) @@ -474,13 +484,33 @@ int incfs_get_filled_blocks(struct data_file *df, return 0; } + bme = kzalloc(sizeof(*bme) * READ_BLOCKMAP_ENTRIES, GFP_NOFS); + if (!bme) + return -ENOMEM; + for (arg->index_out = arg->start_index; arg->index_out < end_index; ++arg->index_out) { struct data_file_block dfb; - error = get_data_file_block(df, arg->index_out, &dfb); - if (error) + if (++i == READ_BLOCKMAP_ENTRIES) { + entries_read = incfs_read_blockmap_entries( + df->df_backing_file_context, bme, + arg->index_out, READ_BLOCKMAP_ENTRIES, + df->df_blockmap_off); + if (entries_read < 0) { + error = entries_read; + break; + } + + i = 0; + } + + if (i >= entries_read) { + error = -EIO; break; + } + + convert_data_file_block(bme + i, &dfb); if (is_data_block_present(&dfb) == in_range) continue; @@ -520,6 +550,7 @@ int incfs_get_filled_blocks(struct data_file *df, pr_debug("Marked file full with result %d", result); } + kfree(bme); return error; } diff --git a/fs/incfs/format.c b/fs/incfs/format.c index ff3a2219fc24..8f3a3b3f8f7b 100644 --- a/fs/incfs/format.c +++ b/fs/incfs/format.c @@ -514,8 +514,19 @@ int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index, loff_t bm_base_off, struct incfs_blockmap_entry *bm_entry) { - return incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1, - bm_base_off); + int error = incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1, + bm_base_off); + + if (error < 0) + return error; + + if (error == 0) + return -EIO; + + if (error != 1) + return -EFAULT; + + return 0; } int incfs_read_blockmap_entries(struct backing_file_context *bfc, @@ -539,9 +550,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, bm_entry_off); if (result < 0) return result; - if (result < bytes_to_read) - return -EIO; - return 0; + return result / sizeof(*entries); } int incfs_read_file_header(struct backing_file_context *bfc,