ANDROID: Incremental fs: Add INCFS_IOC_GET_FILLED_BLOCKS
Test: incfs_test passes
Bug: 151240628
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: I66d0ba1911adc5d68ed404585222e6a81a7eb94f
(cherry picked from commit 8d963bb24076b60cb2de0f2d49deaff1d52e8270)
Git-commit: 05cf04f60a
Git-repo: https://android.googlesource.com/kernel/common/
Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
This commit is contained in:
committed by
Blagovest Kolenichev
parent
27681b2b59
commit
c38495f0d8
@@ -118,8 +118,8 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
|
||||
error = mutex_lock_interruptible(&bfc->bc_mutex);
|
||||
if (error)
|
||||
goto out;
|
||||
error = incfs_read_file_header(bfc, &df->df_metadata_off,
|
||||
&df->df_id, &size);
|
||||
error = incfs_read_file_header(bfc, &df->df_metadata_off, &df->df_id,
|
||||
&size, &df->df_header_flags);
|
||||
mutex_unlock(&bfc->bc_mutex);
|
||||
|
||||
if (error)
|
||||
@@ -127,7 +127,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
|
||||
|
||||
df->df_size = size;
|
||||
if (size > 0)
|
||||
df->df_block_count = get_blocks_count_for_size(size);
|
||||
df->df_data_block_count = get_blocks_count_for_size(size);
|
||||
|
||||
md_records = incfs_scan_metadata_chain(df);
|
||||
if (md_records < 0)
|
||||
@@ -351,7 +351,7 @@ static int get_data_file_block(struct data_file *df, int index,
|
||||
blockmap_off = df->df_blockmap_off;
|
||||
bfc = df->df_backing_file_context;
|
||||
|
||||
if (index < 0 || index >= df->df_block_count || blockmap_off == 0)
|
||||
if (index < 0 || blockmap_off == 0)
|
||||
return -EINVAL;
|
||||
|
||||
error = incfs_read_blockmap_entry(bfc, index, blockmap_off, &bme);
|
||||
@@ -371,6 +371,96 @@ static int get_data_file_block(struct data_file *df, int index,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_one_range(struct incfs_filled_range *range, void __user *buffer,
|
||||
u32 size, u32 *size_out)
|
||||
{
|
||||
if (*size_out + sizeof(*range) > size)
|
||||
return -ERANGE;
|
||||
|
||||
if (copy_to_user(((char *)buffer) + *size_out, range, sizeof(*range)))
|
||||
return -EFAULT;
|
||||
|
||||
*size_out += sizeof(*range);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int incfs_get_filled_blocks(struct data_file *df,
|
||||
struct incfs_get_filled_blocks_args *arg)
|
||||
{
|
||||
int error = 0;
|
||||
bool in_range = false;
|
||||
struct incfs_filled_range range;
|
||||
void *buffer = u64_to_user_ptr(arg->range_buffer);
|
||||
u32 size = arg->range_buffer_size;
|
||||
u32 end_index =
|
||||
arg->end_index ? arg->end_index : df->df_total_block_count;
|
||||
u32 *size_out = &arg->range_buffer_size_out;
|
||||
|
||||
*size_out = 0;
|
||||
if (end_index > df->df_total_block_count)
|
||||
end_index = df->df_total_block_count;
|
||||
arg->total_blocks_out = df->df_total_block_count;
|
||||
|
||||
if (df->df_header_flags & INCFS_FILE_COMPLETE) {
|
||||
pr_debug("File marked full, fast get_filled_blocks");
|
||||
if (arg->start_index > end_index) {
|
||||
arg->index_out = arg->start_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
range = (struct incfs_filled_range){
|
||||
.begin = arg->start_index,
|
||||
.end = end_index,
|
||||
};
|
||||
|
||||
arg->index_out = end_index;
|
||||
return copy_one_range(&range, buffer, size, size_out);
|
||||
}
|
||||
|
||||
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)
|
||||
break;
|
||||
|
||||
if (is_data_block_present(&dfb) == in_range)
|
||||
continue;
|
||||
|
||||
if (!in_range) {
|
||||
in_range = true;
|
||||
range.begin = arg->index_out;
|
||||
} else {
|
||||
range.end = arg->index_out;
|
||||
error = copy_one_range(&range, buffer, size, size_out);
|
||||
if (error)
|
||||
break;
|
||||
in_range = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_range) {
|
||||
range.end = arg->index_out;
|
||||
error = copy_one_range(&range, buffer, size, size_out);
|
||||
}
|
||||
|
||||
if (!error && in_range && arg->start_index == 0 &&
|
||||
end_index == df->df_total_block_count &&
|
||||
*size_out == sizeof(struct incfs_filled_range)) {
|
||||
int result;
|
||||
|
||||
df->df_header_flags |= INCFS_FILE_COMPLETE;
|
||||
result = incfs_update_file_header_flags(
|
||||
df->df_backing_file_context, df->df_header_flags);
|
||||
|
||||
/* Log failure only, since it's just a failed optimization */
|
||||
pr_debug("Marked file full with result %d", result);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool is_read_done(struct pending_read *read)
|
||||
{
|
||||
return atomic_read_acquire(&read->done) != 0;
|
||||
@@ -470,7 +560,7 @@ static int wait_for_data_block(struct data_file *df, int block_index,
|
||||
if (!df || !res_block)
|
||||
return -EFAULT;
|
||||
|
||||
if (block_index < 0 || block_index >= df->df_block_count)
|
||||
if (block_index < 0 || block_index >= df->df_data_block_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (df->df_blockmap_off <= 0)
|
||||
@@ -640,7 +730,7 @@ int incfs_process_new_data_block(struct data_file *df,
|
||||
bfc = df->df_backing_file_context;
|
||||
mi = df->df_mount_info;
|
||||
|
||||
if (block->block_index >= df->df_block_count)
|
||||
if (block->block_index >= df->df_data_block_count)
|
||||
return -ERANGE;
|
||||
|
||||
segment = get_file_segment(df, block->block_index);
|
||||
@@ -746,7 +836,7 @@ int incfs_process_new_hash_block(struct data_file *df,
|
||||
if (!error)
|
||||
error = incfs_write_hash_block_to_backing_file(
|
||||
bfc, range(data, block->data_len), block->block_index,
|
||||
hash_area_base);
|
||||
hash_area_base, df->df_blockmap_off, df->df_size);
|
||||
mutex_unlock(&bfc->bc_mutex);
|
||||
return error;
|
||||
}
|
||||
@@ -762,9 +852,10 @@ static int process_blockmap_md(struct incfs_blockmap *bm,
|
||||
if (!df)
|
||||
return -EFAULT;
|
||||
|
||||
if (df->df_block_count != block_count)
|
||||
if (df->df_data_block_count > block_count)
|
||||
return -EBADMSG;
|
||||
|
||||
df->df_total_block_count = block_count;
|
||||
df->df_blockmap_off = base_off;
|
||||
return error;
|
||||
}
|
||||
@@ -829,7 +920,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg,
|
||||
}
|
||||
|
||||
hash_tree = incfs_alloc_mtree(range(buf, signature->sig_size),
|
||||
df->df_block_count);
|
||||
df->df_data_block_count);
|
||||
if (IS_ERR(hash_tree)) {
|
||||
error = PTR_ERR(hash_tree);
|
||||
hash_tree = NULL;
|
||||
@@ -911,6 +1002,17 @@ int incfs_scan_metadata_chain(struct data_file *df)
|
||||
result = records_count;
|
||||
}
|
||||
mutex_unlock(&bfc->bc_mutex);
|
||||
|
||||
if (df->df_hash_tree) {
|
||||
int hash_block_count = get_blocks_count_for_size(
|
||||
df->df_hash_tree->hash_tree_area_size);
|
||||
|
||||
if (df->df_data_block_count + hash_block_count !=
|
||||
df->df_total_block_count)
|
||||
result = -EINVAL;
|
||||
} else if (df->df_data_block_count != df->df_total_block_count)
|
||||
result = -EINVAL;
|
||||
|
||||
out:
|
||||
kfree(handler);
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user