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 <paullawrence@google.com> Change-Id: Ifb2da77cfd8c9d653c7047ba1eb7f39d795fa1c2
This commit is contained in:
@@ -347,13 +347,28 @@ static bool is_data_block_present(struct data_file_block *block)
|
|||||||
(block->db_stored_size != 0);
|
(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,
|
static int get_data_file_block(struct data_file *df, int index,
|
||||||
struct data_file_block *res_block)
|
struct data_file_block *res_block)
|
||||||
{
|
{
|
||||||
struct incfs_blockmap_entry bme = {};
|
struct incfs_blockmap_entry bme = {};
|
||||||
struct backing_file_context *bfc = NULL;
|
struct backing_file_context *bfc = NULL;
|
||||||
loff_t blockmap_off = 0;
|
loff_t blockmap_off = 0;
|
||||||
u16 flags = 0;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
if (!df || !res_block)
|
if (!df || !res_block)
|
||||||
@@ -369,16 +384,7 @@ static int get_data_file_block(struct data_file *df, int index,
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
flags = le16_to_cpu(bme.me_flags);
|
convert_data_file_block(&bme, res_block);
|
||||||
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;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,6 +438,7 @@ static int update_file_header_flags(struct data_file *df, u32 bits_to_reset,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define READ_BLOCKMAP_ENTRIES 512
|
||||||
int incfs_get_filled_blocks(struct data_file *df,
|
int incfs_get_filled_blocks(struct data_file *df,
|
||||||
struct incfs_get_filled_blocks_args *arg)
|
struct incfs_get_filled_blocks_args *arg)
|
||||||
{
|
{
|
||||||
@@ -443,6 +450,9 @@ int incfs_get_filled_blocks(struct data_file *df,
|
|||||||
u32 end_index =
|
u32 end_index =
|
||||||
arg->end_index ? arg->end_index : df->df_total_block_count;
|
arg->end_index ? arg->end_index : df->df_total_block_count;
|
||||||
u32 *size_out = &arg->range_buffer_size_out;
|
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;
|
*size_out = 0;
|
||||||
if (end_index > df->df_total_block_count)
|
if (end_index > df->df_total_block_count)
|
||||||
@@ -474,13 +484,33 @@ int incfs_get_filled_blocks(struct data_file *df,
|
|||||||
return 0;
|
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;
|
for (arg->index_out = arg->start_index; arg->index_out < end_index;
|
||||||
++arg->index_out) {
|
++arg->index_out) {
|
||||||
struct data_file_block dfb;
|
struct data_file_block dfb;
|
||||||
|
|
||||||
error = get_data_file_block(df, arg->index_out, &dfb);
|
if (++i == READ_BLOCKMAP_ENTRIES) {
|
||||||
if (error)
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_data_file_block(bme + i, &dfb);
|
||||||
|
|
||||||
if (is_data_block_present(&dfb) == in_range)
|
if (is_data_block_present(&dfb) == in_range)
|
||||||
continue;
|
continue;
|
||||||
@@ -520,6 +550,7 @@ int incfs_get_filled_blocks(struct data_file *df,
|
|||||||
pr_debug("Marked file full with result %d", result);
|
pr_debug("Marked file full with result %d", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(bme);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -514,8 +514,19 @@ int incfs_read_blockmap_entry(struct backing_file_context *bfc, int block_index,
|
|||||||
loff_t bm_base_off,
|
loff_t bm_base_off,
|
||||||
struct incfs_blockmap_entry *bm_entry)
|
struct incfs_blockmap_entry *bm_entry)
|
||||||
{
|
{
|
||||||
return incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1,
|
int error = incfs_read_blockmap_entries(bfc, bm_entry, block_index, 1,
|
||||||
bm_base_off);
|
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,
|
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);
|
bm_entry_off);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
return result;
|
||||||
if (result < bytes_to_read)
|
return result / sizeof(*entries);
|
||||||
return -EIO;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int incfs_read_file_header(struct backing_file_context *bfc,
|
int incfs_read_file_header(struct backing_file_context *bfc,
|
||||||
|
|||||||
Reference in New Issue
Block a user