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

Commit 0109bfa8 authored by Paul Lawrence's avatar Paul Lawrence Committed by Sahil Sonar
Browse files

ANDROID: Incremental fs: Fix filled block count from get filled blocks



Bug: 165929150
Test: incfs_test passes
Signed-off-by: default avatarPaul Lawrence <paullawrence@google.com>
Change-Id: I41ef60ba8b8667eca06caf762d35e2c789238586
parent c13e784e
Loading
Loading
Loading
Loading
+33 −36
Original line number Diff line number Diff line
@@ -686,36 +686,9 @@ static int copy_one_range(struct incfs_filled_range *range, void __user *buffer,
	return 0;
}

static int update_file_header_flags(struct data_file *df, u32 bits_to_reset,
				    u32 bits_to_set)
{
	int result;
	u32 new_flags;
	struct backing_file_context *bfc;

	if (!df)
		return -EFAULT;
	bfc = df->df_backing_file_context;
	if (!bfc)
		return -EFAULT;

	result = mutex_lock_interruptible(&bfc->bc_mutex);
	if (result)
		return result;

	new_flags = (df->df_header_flags & ~bits_to_reset) | bits_to_set;
	if (new_flags != df->df_header_flags) {
		df->df_header_flags = new_flags;
		result = incfs_write_file_header_flags(bfc, new_flags);
	}

	mutex_unlock(&bfc->bc_mutex);

	return result;
}

#define READ_BLOCKMAP_ENTRIES 512
int incfs_get_filled_blocks(struct data_file *df,
			    struct incfs_file_data *fd,
			    struct incfs_get_filled_blocks_args *arg)
{
	int error = 0;
@@ -729,6 +702,8 @@ int incfs_get_filled_blocks(struct data_file *df,
	int i = READ_BLOCKMAP_ENTRIES - 1;
	int entries_read = 0;
	struct incfs_blockmap_entry *bme;
	int data_blocks_filled = 0;
	int hash_blocks_filled = 0;

	*size_out = 0;
	if (end_index > df->df_total_block_count)
@@ -736,7 +711,8 @@ int incfs_get_filled_blocks(struct data_file *df,
	arg->total_blocks_out = df->df_total_block_count;
	arg->data_blocks_out = df->df_data_block_count;

	if (df->df_header_flags & INCFS_FILE_COMPLETE) {
	if (atomic_read(&df->df_data_blocks_written) ==
	    df->df_data_block_count) {
		pr_debug("File marked full, fast get_filled_blocks");
		if (arg->start_index > end_index) {
			arg->index_out = arg->start_index;
@@ -789,6 +765,12 @@ int incfs_get_filled_blocks(struct data_file *df,

		convert_data_file_block(bme + i, &dfb);

		if (is_data_block_present(&dfb))
			if (arg->index_out >= df->df_data_block_count)
				++hash_blocks_filled;
			else
				++data_blocks_filled;

		if (is_data_block_present(&dfb) == in_range)
			continue;

@@ -818,13 +800,28 @@ int incfs_get_filled_blocks(struct data_file *df,
			arg->index_out = range.begin;
	}

	if (!error && in_range && arg->start_index == 0 &&
	    end_index == df->df_total_block_count &&
	    *size_out == sizeof(struct incfs_filled_range)) {
		int result =
			update_file_header_flags(df, 0, INCFS_FILE_COMPLETE);
		/* Log failure only, since it's just a failed optimization */
		pr_debug("Marked file full with result %d", result);
	if (arg->start_index == 0) {
		fd->fd_get_block_pos = 0;
		fd->fd_filled_data_blocks = 0;
		fd->fd_filled_hash_blocks = 0;
	}

	if (arg->start_index == fd->fd_get_block_pos) {
		fd->fd_get_block_pos = arg->index_out + 1;
		fd->fd_filled_data_blocks += data_blocks_filled;
		fd->fd_filled_hash_blocks += hash_blocks_filled;
	}

	if (fd->fd_get_block_pos == df->df_total_block_count + 1) {
		if (fd->fd_filled_data_blocks >
		   atomic_read(&df->df_data_blocks_written))
			atomic_set(&df->df_data_blocks_written,
				   fd->fd_filled_data_blocks);

		if (fd->fd_filled_hash_blocks >
		   atomic_read(&df->df_hash_blocks_written))
			atomic_set(&df->df_hash_blocks_written,
				   fd->fd_filled_hash_blocks);
	}

	kfree(bme);
+18 −1
Original line number Diff line number Diff line
@@ -161,7 +161,6 @@ struct mount_info {

	/* Number of blocks written since mount */
	atomic_t mi_blocks_written;

};

struct data_file_block {
@@ -289,6 +288,23 @@ struct dentry_info {
	struct path backing_path;
};

enum FILL_PERMISSION {
	CANT_FILL = 0,
	CAN_FILL = 1,
};

struct incfs_file_data {
	/* Does this file handle have INCFS_IOC_FILL_BLOCKS permission */
	enum FILL_PERMISSION fd_fill_permission;

	/* If INCFS_IOC_GET_FILLED_BLOCKS has been called, where are we */
	int fd_get_block_pos;

	/* And how many filled blocks are there up to that point */
	int fd_filled_data_blocks;
	int fd_filled_hash_blocks;
};

struct mount_info *incfs_alloc_mount_info(struct super_block *sb,
					  struct mount_options *options,
					  struct path *backing_dir_path);
@@ -313,6 +329,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
				   struct mem_range tmp);

int incfs_get_filled_blocks(struct data_file *df,
			    struct incfs_file_data *fd,
			    struct incfs_get_filled_blocks_args *arg);

int incfs_read_file_signature(struct data_file *df, struct mem_range dst);
+0 −9
Original line number Diff line number Diff line
@@ -205,15 +205,6 @@ static int append_md_to_backing_file(struct backing_file_context *bfc,
	return result;
}

int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags)
{
	if (!bfc)
		return -EFAULT;

	return write_to_bf(bfc, &flags, sizeof(flags),
			   offsetof(struct incfs_file_header, fh_flags));
}

/*
 * Reserve 0-filled space for the blockmap body, and append
 * incfs_blockmap metadata record pointing to it.
+1 −4
Original line number Diff line number Diff line
@@ -123,7 +123,6 @@ enum incfs_metadata_type {
};

enum incfs_file_header_flags {
	INCFS_FILE_COMPLETE = 1 << 0,
	INCFS_FILE_MAPPED = 1 << 1,
};

@@ -254,7 +253,7 @@ struct incfs_status {
	__le32 is_hash_blocks_written; /* Number of hash blocks written */

	__le32 is_dummy[6]; /* Spare fields */
};
} __packed;

/* State of the backing file. */
struct backing_file_context {
@@ -330,8 +329,6 @@ int incfs_write_status_to_backing_file(struct backing_file_context *bfc,
				       u32 data_blocks_written,
				       u32 hash_blocks_written);

int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags);

int incfs_make_empty_backing_file(struct backing_file_context *bfc,
				  incfs_uuid_t *uuid, u64 file_size);

+5 −2
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ static long ioctl_permit_fill(struct file *f, void __user *arg)
	struct incfs_permit_fill permit_fill;
	long error = 0;
	struct file *file = NULL;
	struct incfs_file_data *fd;

	if (copy_from_user(&permit_fill, usr_permit_fill, sizeof(permit_fill)))
		return -EFAULT;
@@ -292,9 +293,11 @@ static long ioctl_permit_fill(struct file *f, void __user *arg)
		goto out;
	}

	switch ((uintptr_t)file->private_data) {
	fd = file->private_data;

	switch (fd->fd_fill_permission) {
	case CANT_FILL:
		file->private_data = (void *)CAN_FILL;
		fd->fd_fill_permission = CAN_FILL;
		break;

	case CAN_FILL:
Loading