Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5128381d authored by Paul Lawrence's avatar Paul Lawrence
Browse files

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: default avatarPaul Lawrence <paullawrence@google.com>
Change-Id: Ifb2da77cfd8c9d653c7047ba1eb7f39d795fa1c2
parent 23f5b7c5
Loading
Loading
Loading
Loading
+44 −13
Original line number Diff line number Diff line
@@ -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;
}

+14 −5
Original line number Diff line number Diff line
@@ -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,
	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,