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

Commit 6fe44a54 authored by Paul Lawrence's avatar Paul Lawrence
Browse files

Revert "ANDROID: Incremental fs: Create mapped file"



This reverts commit 0eae0d27.

Set incfs back to rvc shipping incfs

Bug: 178509184
Test: incfs_test passes
Signed-off-by: default avatarPaul Lawrence <paullawrence@google.com>
Change-Id: Ic8e2c2b8b0bcbc2df620cb7a3ded3d0df93f3f29
parent a7538ee7
Loading
Loading
Loading
Loading
+0 −88
Original line number Original line Diff line number Diff line
@@ -8,7 +8,6 @@
#include <linux/ktime.h>
#include <linux/ktime.h>
#include <linux/lz4.h>
#include <linux/lz4.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/types.h>
@@ -124,86 +123,6 @@ static void data_file_segment_init(struct data_file_segment *segment)
	INIT_LIST_HEAD(&segment->reads_list_head);
	INIT_LIST_HEAD(&segment->reads_list_head);
}
}


char *file_id_to_str(incfs_uuid_t id)
{
	char *result = kmalloc(1 + sizeof(id.bytes) * 2, GFP_NOFS);
	char *end;

	if (!result)
		return NULL;

	end = bin2hex(result, id.bytes, sizeof(id.bytes));
	*end = 0;
	return result;
}

struct dentry *incfs_lookup_dentry(struct dentry *parent, const char *name)
{
	struct inode *inode;
	struct dentry *result = NULL;

	if (!parent)
		return ERR_PTR(-EFAULT);

	inode = d_inode(parent);
	inode_lock_nested(inode, I_MUTEX_PARENT);
	result = lookup_one_len(name, parent, strlen(name));
	inode_unlock(inode);

	if (IS_ERR(result))
		pr_warn("%s err:%ld\n", __func__, PTR_ERR(result));

	return result;
}

static struct data_file *handle_mapped_file(struct mount_info *mi,
					    struct data_file *df)
{
	char *file_id_str;
	struct dentry *index_file_dentry;
	struct path path;
	struct file *bf;
	struct data_file *result = NULL;

	file_id_str = file_id_to_str(df->df_id);
	if (!file_id_str)
		return ERR_PTR(-ENOENT);

	index_file_dentry = incfs_lookup_dentry(mi->mi_index_dir,
						file_id_str);
	kfree(file_id_str);
	if (!index_file_dentry)
		return ERR_PTR(-ENOENT);
	if (IS_ERR(index_file_dentry))
		return (struct data_file *)index_file_dentry;
	if (!d_really_is_positive(index_file_dentry)) {
		result = ERR_PTR(-ENOENT);
		goto out;
	}

	path = (struct path) {
		.mnt = mi->mi_backing_dir_path.mnt,
		.dentry = index_file_dentry
	};

	bf = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner);
	if (IS_ERR(bf)) {
		result = (struct data_file *)bf;
		goto out;
	}

	result = incfs_open_data_file(mi, bf);
	fput(bf);
	if (IS_ERR(result))
		goto out;

	result->df_mapped_offset = df->df_metadata_off;

out:
	dput(index_file_dentry);
	return result;
}

struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
{
{
	struct data_file *df = NULL;
	struct data_file *df = NULL;
@@ -248,13 +167,6 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
	if (size > 0)
	if (size > 0)
		df->df_data_block_count = get_blocks_count_for_size(size);
		df->df_data_block_count = get_blocks_count_for_size(size);


	if (df->df_header_flags & INCFS_FILE_MAPPED) {
		struct data_file *mapped_df = handle_mapped_file(mi, df);

		incfs_free_data_file(df);
		return mapped_df;
	}

	md_records = incfs_scan_metadata_chain(df);
	md_records = incfs_scan_metadata_chain(df);
	if (md_records < 0)
	if (md_records < 0)
		error = md_records;
		error = md_records;
+0 −5
Original line number Original line Diff line number Diff line
@@ -235,9 +235,6 @@ struct data_file {
	/* Total number of blocks, data + hash */
	/* Total number of blocks, data + hash */
	int df_total_block_count;
	int df_total_block_count;


	/* For mapped files, the offset into the actual file */
	loff_t df_mapped_offset;

	struct file_attr n_attr;
	struct file_attr n_attr;


	struct mtree *df_hash_tree;
	struct mtree *df_hash_tree;
@@ -274,8 +271,6 @@ int incfs_realloc_mount_info(struct mount_info *mi,


void incfs_free_mount_info(struct mount_info *mi);
void incfs_free_mount_info(struct mount_info *mi);


char *file_id_to_str(incfs_uuid_t id);
struct dentry *incfs_lookup_dentry(struct dentry *parent, const char *name);
struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf);
struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf);
void incfs_free_data_file(struct data_file *df);
void incfs_free_data_file(struct data_file *df);


+4 −35
Original line number Original line Diff line number Diff line
@@ -233,7 +233,8 @@ int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags)
		return -EFAULT;
		return -EFAULT;


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


/*
/*
@@ -384,7 +385,7 @@ int incfs_write_signature_to_backing_file(struct backing_file_context *bfc,
/*
/*
 * Write a backing file header
 * Write a backing file header
 * It should always be called only on empty file.
 * It should always be called only on empty file.
 * fh.fh_first_md_offset is 0 for now, but will be updated
 * incfs_super_block.s_first_md_offset is 0 for now, but will be updated
 * once first metadata record is added.
 * once first metadata record is added.
 */
 */
int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
@@ -414,38 +415,6 @@ int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
	return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
	return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
}
}


/*
 * Write a backing file header for a mapping file
 * It should always be called only on empty file.
 */
int incfs_write_mapping_fh_to_backing_file(struct backing_file_context *bfc,
				incfs_uuid_t *uuid, u64 file_size, u64 offset)
{
	struct incfs_file_header fh = {};
	loff_t file_pos = 0;

	if (!bfc)
		return -EFAULT;

	fh.fh_magic = cpu_to_le64(INCFS_MAGIC_NUMBER);
	fh.fh_version = cpu_to_le64(INCFS_FORMAT_CURRENT_VER);
	fh.fh_header_size = cpu_to_le16(sizeof(fh));
	fh.fh_original_offset = cpu_to_le64(offset);
	fh.fh_data_block_size = cpu_to_le16(INCFS_DATA_FILE_BLOCK_SIZE);

	fh.fh_mapped_file_size = cpu_to_le64(file_size);
	fh.fh_original_uuid = *uuid;
	fh.fh_flags = INCFS_FILE_MAPPED;

	LOCK_REQUIRED(bfc->bc_mutex);

	file_pos = incfs_get_end_offset(bfc->bc_file);
	if (file_pos != 0)
		return -EEXIST;

	return write_to_bf(bfc, &fh, sizeof(fh), file_pos);
}

/* Write a given data block and update file's blockmap to point it. */
/* Write a given data block and update file's blockmap to point it. */
int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
				     struct mem_range block, int block_index,
				     struct mem_range block, int block_index,
@@ -629,7 +598,7 @@ int incfs_read_file_header(struct backing_file_context *bfc,
	if (file_size)
	if (file_size)
		*file_size = le64_to_cpu(fh.fh_file_size);
		*file_size = le64_to_cpu(fh.fh_file_size);
	if (flags)
	if (flags)
		*flags = le32_to_cpu(fh.fh_flags);
		*flags = le32_to_cpu(fh.fh_file_header_flags);
	return 0;
	return 0;
}
}


+14 −31
Original line number Original line Diff line number Diff line
@@ -72,7 +72,7 @@
 *
 *
 *
 *
 *              +-------------------------------------------+
 *              +-------------------------------------------+
 *              |            incfs_file_header              |]---+
 *              |            incfs_super_block              |]---+
 *              +-------------------------------------------+    |
 *              +-------------------------------------------+    |
 *              |                 metadata                  |<---+
 *              |                 metadata                  |<---+
 *              |           incfs_file_signature            |]---+
 *              |           incfs_file_signature            |]---+
@@ -123,7 +123,6 @@ enum incfs_metadata_type {


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


/* Header included at the beginning of all metadata records on the disk. */
/* Header included at the beginning of all metadata records on the disk. */
@@ -165,33 +164,20 @@ struct incfs_file_header {
	__le16 fh_data_block_size;
	__le16 fh_data_block_size;


	/* File flags, from incfs_file_header_flags */
	/* File flags, from incfs_file_header_flags */
	__le32 fh_flags;
	__le32 fh_file_header_flags;


	union {
		/* Standard incfs file */
		struct {
	/* Offset of the first metadata record */
	/* Offset of the first metadata record */
	__le64 fh_first_md_offset;
	__le64 fh_first_md_offset;


	/*
	 * Put file specific information after this point
	 */

	/* Full size of the file's content */
	/* Full size of the file's content */
	__le64 fh_file_size;
	__le64 fh_file_size;


	/* File uuid */
	/* File uuid */
	incfs_uuid_t fh_uuid;
	incfs_uuid_t fh_uuid;
		};

		/* Mapped file - INCFS_FILE_MAPPED set in fh_flags */
		struct {
			/* Offset in original file */
			__le64 fh_original_offset;

			/* Full size of the file's content */
			__le64 fh_mapped_file_size;

			/* Original file's uuid */
			incfs_uuid_t fh_original_uuid;
		};
	};
} __packed;
} __packed;


enum incfs_block_map_entry_flags {
enum incfs_block_map_entry_flags {
@@ -308,9 +294,6 @@ int incfs_write_blockmap_to_backing_file(struct backing_file_context *bfc,
int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
int incfs_write_fh_to_backing_file(struct backing_file_context *bfc,
				   incfs_uuid_t *uuid, u64 file_size);
				   incfs_uuid_t *uuid, u64 file_size);


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

int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
					   struct mem_range block,
					   struct mem_range block,
					   int block_index, loff_t bm_base_off,
					   int block_index, loff_t bm_base_off,
+35 −197
Original line number Original line Diff line number Diff line
@@ -735,6 +735,26 @@ static int incfs_init_dentry(struct dentry *dentry, struct path *path)
	return 0;
	return 0;
}
}


static struct dentry *incfs_lookup_dentry(struct dentry *parent,
						const char *name)
{
	struct inode *inode;
	struct dentry *result = NULL;

	if (!parent)
		return ERR_PTR(-EFAULT);

	inode = d_inode(parent);
	inode_lock_nested(inode, I_MUTEX_PARENT);
	result = lookup_one_len(name, parent, strlen(name));
	inode_unlock(inode);

	if (IS_ERR(result))
		pr_warn("%s err:%ld\n", __func__, PTR_ERR(result));

	return result;
}

static struct dentry *open_or_create_index_dir(struct dentry *backing_dir)
static struct dentry *open_or_create_index_dir(struct dentry *backing_dir)
{
{
	static const char name[] = ".index";
	static const char name[] = ".index";
@@ -789,8 +809,7 @@ static int read_single_page(struct file *f, struct page *page)


	page_start = kmap(page);
	page_start = kmap(page);
	offset = page_offset(page);
	offset = page_offset(page);
	block_index = (offset + df->df_mapped_offset) /
	block_index = offset / INCFS_DATA_FILE_BLOCK_SIZE;
		INCFS_DATA_FILE_BLOCK_SIZE;
	size = df->df_size;
	size = df->df_size;
	timeout_ms = df->df_mount_info->mi_options.read_timeout_ms;
	timeout_ms = df->df_mount_info->mi_options.read_timeout_ms;


@@ -832,6 +851,19 @@ static int read_single_page(struct file *f, struct page *page)
	return result;
	return result;
}
}


static char *file_id_to_str(incfs_uuid_t id)
{
	char *result = kmalloc(1 + sizeof(id.bytes) * 2, GFP_NOFS);
	char *end;

	if (!result)
		return NULL;

	end = bin2hex(result, id.bytes, sizeof(id.bytes));
	*end = 0;
	return result;
}

static struct mem_range incfs_copy_signature_info_from_user(u8 __user *original,
static struct mem_range incfs_copy_signature_info_from_user(u8 __user *original,
							    u64 size)
							    u64 size)
{
{
@@ -949,54 +981,6 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry,
	return error;
	return error;
}
}


static int init_new_mapped_file(struct mount_info *mi, struct dentry *dentry,
			 incfs_uuid_t *uuid, u64 size, u64 offset)
{
	struct path path = {};
	struct file *new_file;
	int error = 0;
	struct backing_file_context *bfc = NULL;

	if (!mi || !dentry || !uuid)
		return -EFAULT;

	/* Resize newly created file to its true size. */
	path = (struct path) {
		.mnt = mi->mi_backing_dir_path.mnt,
		.dentry = dentry
	};
	new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE,
			       mi->mi_owner);

	if (IS_ERR(new_file)) {
		error = PTR_ERR(new_file);
		goto out;
	}

	bfc = incfs_alloc_bfc(new_file);
	fput(new_file);
	if (IS_ERR(bfc)) {
		error = PTR_ERR(bfc);
		bfc = NULL;
		goto out;
	}

	mutex_lock(&bfc->bc_mutex);
	error = incfs_write_mapping_fh_to_backing_file(bfc, uuid, size, offset);
	if (error)
		goto out;

out:
	if (bfc) {
		mutex_unlock(&bfc->bc_mutex);
		incfs_free_bfc(bfc);
	}

	if (error)
		pr_debug("incfs: %s error: %d\n", __func__, error);
	return error;
}

static int incfs_link(struct dentry *what, struct dentry *where)
static int incfs_link(struct dentry *what, struct dentry *where)
{
{
	struct dentry *parent_dentry = dget_parent(where);
	struct dentry *parent_dentry = dget_parent(where);
@@ -1285,7 +1269,7 @@ static long ioctl_create_file(struct mount_info *mi,
	if (error)
	if (error)
		goto delete_index_file;
		goto delete_index_file;


	/* Linking a file with its real name from the requested dir. */
	/* Linking a file with it's real name from the requested dir. */
	error = incfs_link(index_file_dentry, named_file_dentry);
	error = incfs_link(index_file_dentry, named_file_dentry);


	if (!error)
	if (!error)
@@ -1498,150 +1482,6 @@ static long ioctl_get_filled_blocks(struct file *f, void __user *arg)
	return error;
	return error;
}
}


static long ioctl_create_mapped_file(struct mount_info *mi, void __user *arg)
{
	struct incfs_create_mapped_file_args __user *args_usr_ptr = arg;
	struct incfs_create_mapped_file_args args = {};
	char *file_name;
	int error = 0;
	struct path parent_dir_path = {};
	char *source_file_name = NULL;
	struct dentry *source_file_dentry = NULL;
	u64 source_file_size;
	struct dentry *file_dentry = NULL;
	struct inode *parent_inode;
	__le64 size_attr_value;

	if (copy_from_user(&args, args_usr_ptr, sizeof(args)) > 0)
		return -EINVAL;

	file_name = strndup_user(u64_to_user_ptr(args.file_name), PATH_MAX);
	if (IS_ERR(file_name)) {
		error = PTR_ERR(file_name);
		file_name = NULL;
		goto out;
	}

	error = validate_name(file_name);
	if (error)
		goto out;

	if (args.source_offset % INCFS_DATA_FILE_BLOCK_SIZE) {
		error = -EINVAL;
		goto out;
	}

	/* Validate file mapping is in range */
	source_file_name = file_id_to_str(args.source_file_id);
	if (!source_file_name) {
		pr_warn("Failed to alloc source_file_name\n");
		error = -ENOMEM;
		goto out;
	}

	source_file_dentry = incfs_lookup_dentry(mi->mi_index_dir,
						       source_file_name);
	if (!source_file_dentry) {
		pr_warn("Source file does not exist\n");
		error = -EINVAL;
		goto out;
	}
	if (IS_ERR(source_file_dentry)) {
		pr_warn("Error opening source file\n");
		error = PTR_ERR(source_file_dentry);
		source_file_dentry = NULL;
		goto out;
	}
	if (!d_really_is_positive(source_file_dentry)) {
		pr_warn("Source file dentry negative\n");
		error = -EINVAL;
		goto out;
	}

	error = vfs_getxattr(source_file_dentry, INCFS_XATTR_SIZE_NAME,
			     (char *)&size_attr_value, sizeof(size_attr_value));
	if (error < 0)
		goto out;

	if (error != sizeof(size_attr_value)) {
		pr_warn("Mapped file has no size attr\n");
		error = -EINVAL;
		goto out;
	}

	source_file_size = le64_to_cpu(size_attr_value);
	if (args.source_offset + args.size > source_file_size) {
		pr_warn("Mapped file out of range\n");
		error = -EINVAL;
		goto out;
	}

	/* Find a directory to put the file into. */
	error = dir_relative_path_resolve(mi,
			u64_to_user_ptr(args.directory_path),
			&parent_dir_path);
	if (error)
		goto out;

	if (parent_dir_path.dentry == mi->mi_index_dir) {
		/* Can't create a file directly inside .index */
		error = -EBUSY;
		goto out;
	}

	/* Look up a dentry in the parent dir. It should be negative. */
	file_dentry = incfs_lookup_dentry(parent_dir_path.dentry,
					file_name);
	if (!file_dentry) {
		error = -EFAULT;
		goto out;
	}
	if (IS_ERR(file_dentry)) {
		error = PTR_ERR(file_dentry);
		file_dentry = NULL;
		goto out;
	}
	if (d_really_is_positive(file_dentry)) {
		error = -EEXIST;
		goto out;
	}

	parent_inode = d_inode(parent_dir_path.dentry);
	inode_lock_nested(parent_inode, I_MUTEX_PARENT);
	error = vfs_create(parent_inode, file_dentry, args.mode | 0222, true);
	inode_unlock(parent_inode);
	if (error)
		goto out;

	/* Save the file's size as an xattr for easy fetching in future. */
	size_attr_value = cpu_to_le64(args.size);
	error = vfs_setxattr(file_dentry, INCFS_XATTR_SIZE_NAME,
		(char *)&size_attr_value, sizeof(size_attr_value),
		XATTR_CREATE);
	if (error) {
		pr_debug("incfs: vfs_setxattr err:%d\n", error);
		goto delete_file;
	}

	error = init_new_mapped_file(mi, file_dentry, &args.source_file_id,
			size_attr_value, cpu_to_le64(args.source_offset));
	if (error)
		goto delete_file;

	goto out;

delete_file:
	incfs_unlink(file_dentry);

out:
	dput(file_dentry);
	dput(source_file_dentry);
	path_put(&parent_dir_path);
	kfree(file_name);
	kfree(source_file_name);
	return error;
}

static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg)
static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg)
{
{
	struct mount_info *mi = get_mount_info(file_superblock(f));
	struct mount_info *mi = get_mount_info(file_superblock(f));
@@ -1657,8 +1497,6 @@ static long dispatch_ioctl(struct file *f, unsigned int req, unsigned long arg)
		return ioctl_read_file_signature(f, (void __user *)arg);
		return ioctl_read_file_signature(f, (void __user *)arg);
	case INCFS_IOC_GET_FILLED_BLOCKS:
	case INCFS_IOC_GET_FILLED_BLOCKS:
		return ioctl_get_filled_blocks(f, (void __user *)arg);
		return ioctl_get_filled_blocks(f, (void __user *)arg);
	case INCFS_IOC_CREATE_MAPPED_FILE:
		return ioctl_create_mapped_file(mi, (void __user *)arg);
	default:
	default:
		return -EINVAL;
		return -EINVAL;
	}
	}
Loading