Revert "ANDROID: Incremental fs: Create mapped file"
This reverts commit 0eae0d2704.
Set incfs back to rvc shipping incfs
Bug: 178509184
Test: incfs_test passes
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: Ic8e2c2b8b0bcbc2df620cb7a3ded3d0df93f3f29
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/lz4.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/slab.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);
|
||||
}
|
||||
|
||||
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 *df = NULL;
|
||||
@@ -248,13 +167,6 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf)
|
||||
if (size > 0)
|
||||
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);
|
||||
if (md_records < 0)
|
||||
error = md_records;
|
||||
|
||||
@@ -235,9 +235,6 @@ struct data_file {
|
||||
/* Total number of blocks, data + hash */
|
||||
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 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);
|
||||
|
||||
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);
|
||||
void incfs_free_data_file(struct data_file *df);
|
||||
|
||||
|
||||
@@ -233,7 +233,8 @@ int incfs_write_file_header_flags(struct backing_file_context *bfc, u32 flags)
|
||||
return -EFAULT;
|
||||
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
int incfs_write_data_block_to_backing_file(struct backing_file_context *bfc,
|
||||
struct mem_range block, int block_index,
|
||||
@@ -629,7 +598,7 @@ int incfs_read_file_header(struct backing_file_context *bfc,
|
||||
if (file_size)
|
||||
*file_size = le64_to_cpu(fh.fh_file_size);
|
||||
if (flags)
|
||||
*flags = le32_to_cpu(fh.fh_flags);
|
||||
*flags = le32_to_cpu(fh.fh_file_header_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
*
|
||||
*
|
||||
* +-------------------------------------------+
|
||||
* | incfs_file_header |]---+
|
||||
* | incfs_super_block |]---+
|
||||
* +-------------------------------------------+ |
|
||||
* | metadata |<---+
|
||||
* | incfs_file_signature |]---+
|
||||
@@ -123,7 +123,6 @@ enum incfs_metadata_type {
|
||||
|
||||
enum incfs_file_header_flags {
|
||||
INCFS_FILE_COMPLETE = 1 << 0,
|
||||
INCFS_FILE_MAPPED = 1 << 1,
|
||||
};
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 */
|
||||
__le64 fh_first_md_offset;
|
||||
/* Offset of the first metadata record */
|
||||
__le64 fh_first_md_offset;
|
||||
|
||||
/* Full size of the file's content */
|
||||
__le64 fh_file_size;
|
||||
/*
|
||||
* Put file specific information after this point
|
||||
*/
|
||||
|
||||
/* File uuid */
|
||||
incfs_uuid_t fh_uuid;
|
||||
};
|
||||
/* Full size of the file's content */
|
||||
__le64 fh_file_size;
|
||||
|
||||
/* 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;
|
||||
};
|
||||
};
|
||||
/* File uuid */
|
||||
incfs_uuid_t fh_uuid;
|
||||
} __packed;
|
||||
|
||||
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,
|
||||
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,
|
||||
struct mem_range block,
|
||||
int block_index, loff_t bm_base_off,
|
||||
|
||||
232
fs/incfs/vfs.c
232
fs/incfs/vfs.c
@@ -735,6 +735,26 @@ static int incfs_init_dentry(struct dentry *dentry, struct path *path)
|
||||
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 const char name[] = ".index";
|
||||
@@ -789,8 +809,7 @@ static int read_single_page(struct file *f, struct page *page)
|
||||
|
||||
page_start = kmap(page);
|
||||
offset = page_offset(page);
|
||||
block_index = (offset + df->df_mapped_offset) /
|
||||
INCFS_DATA_FILE_BLOCK_SIZE;
|
||||
block_index = offset / INCFS_DATA_FILE_BLOCK_SIZE;
|
||||
size = df->df_size;
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
u64 size)
|
||||
{
|
||||
@@ -949,54 +981,6 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry,
|
||||
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)
|
||||
{
|
||||
struct dentry *parent_dentry = dget_parent(where);
|
||||
@@ -1285,7 +1269,7 @@ static long ioctl_create_file(struct mount_info *mi,
|
||||
if (error)
|
||||
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);
|
||||
|
||||
if (!error)
|
||||
@@ -1498,150 +1482,6 @@ static long ioctl_get_filled_blocks(struct file *f, void __user *arg)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
case INCFS_IOC_GET_FILLED_BLOCKS:
|
||||
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:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -92,10 +92,6 @@
|
||||
#define INCFS_IOC_GET_FILLED_BLOCKS \
|
||||
_IOR(INCFS_IOCTL_BASE_CODE, 34, struct incfs_get_filled_blocks_args)
|
||||
|
||||
/* Creates a new mapped file */
|
||||
#define INCFS_IOC_CREATE_MAPPED_FILE \
|
||||
_IOWR(INCFS_IOCTL_BASE_CODE, 35, struct incfs_create_mapped_file_args)
|
||||
|
||||
enum incfs_compression_alg {
|
||||
COMPRESSION_NONE = 0,
|
||||
COMPRESSION_LZ4 = 1
|
||||
@@ -335,50 +331,4 @@ struct incfs_get_filled_blocks_args {
|
||||
__u32 index_out;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new mapped file
|
||||
* Argument for INCFS_IOC_CREATE_MAPPED_FILE
|
||||
*/
|
||||
struct incfs_create_mapped_file_args {
|
||||
/*
|
||||
* Total size of the new file.
|
||||
*/
|
||||
__aligned_u64 size;
|
||||
|
||||
/*
|
||||
* File mode. Permissions and dir flag.
|
||||
*/
|
||||
__u16 mode;
|
||||
|
||||
__u16 reserved1;
|
||||
|
||||
__u32 reserved2;
|
||||
|
||||
/*
|
||||
* A pointer to a null-terminated relative path to the incfs mount
|
||||
* point
|
||||
* Max length: PATH_MAX
|
||||
*
|
||||
* Equivalent to: char *directory_path;
|
||||
*/
|
||||
__aligned_u64 directory_path;
|
||||
|
||||
/*
|
||||
* A pointer to a null-terminated file name.
|
||||
* Max length: PATH_MAX
|
||||
*
|
||||
* Equivalent to: char *file_name;
|
||||
*/
|
||||
__aligned_u64 file_name;
|
||||
|
||||
/* Id of source file to map. */
|
||||
incfs_uuid_t source_file_id;
|
||||
|
||||
/*
|
||||
* Offset in source file to start mapping. Must be a multiple of
|
||||
* INCFS_DATA_FILE_BLOCK_SIZE
|
||||
*/
|
||||
__aligned_u64 source_offset;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_INCREMENTALFS_H */
|
||||
|
||||
@@ -2232,8 +2232,7 @@ static int read_log_test(const char *mount_dir)
|
||||
return TEST_FAILURE;
|
||||
}
|
||||
|
||||
static int emit_partial_test_file_data(const char *mount_dir,
|
||||
struct test_file *file)
|
||||
static int emit_partial_test_file_data(const char *mount_dir, struct test_file *file)
|
||||
{
|
||||
int i, j;
|
||||
int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
|
||||
@@ -2456,8 +2455,7 @@ static int get_blocks_test(const char *mount_dir)
|
||||
return TEST_FAILURE;
|
||||
}
|
||||
|
||||
static int emit_partial_test_file_hash(const char *mount_dir,
|
||||
struct test_file *file)
|
||||
static int emit_partial_test_file_hash(const char *mount_dir, struct test_file *file)
|
||||
{
|
||||
int err;
|
||||
int fd;
|
||||
@@ -2681,166 +2679,6 @@ static int large_file_test(const char *mount_dir)
|
||||
failure:
|
||||
close(fd);
|
||||
close(cmd_fd);
|
||||
umount(mount_dir);
|
||||
free(backing_dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int validate_mapped_file(const char *orig_name, const char *name,
|
||||
size_t size, size_t offset)
|
||||
{
|
||||
struct stat st;
|
||||
int orig_fd = -1, fd = -1;
|
||||
size_t block;
|
||||
int result = TEST_FAILURE;
|
||||
|
||||
if (stat(name, &st)) {
|
||||
ksft_print_msg("Failed to stat %s with error %s\n",
|
||||
name, strerror(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (size != st.st_size) {
|
||||
ksft_print_msg("Mismatched file sizes for file %s - expected %llu, got %llu\n",
|
||||
name, size, st.st_size);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
fd = open(name, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
ksft_print_msg("Failed to open %s with error %s\n", name,
|
||||
strerror(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
orig_fd = open(orig_name, O_RDONLY | O_CLOEXEC);
|
||||
if (orig_fd == -1) {
|
||||
ksft_print_msg("Failed to open %s with error %s\n", orig_name,
|
||||
strerror(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (block = 0; block < size; block += INCFS_DATA_FILE_BLOCK_SIZE) {
|
||||
uint8_t orig_data[INCFS_DATA_FILE_BLOCK_SIZE];
|
||||
uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
|
||||
ssize_t orig_read, mapped_read;
|
||||
|
||||
orig_read = pread(orig_fd, orig_data,
|
||||
INCFS_DATA_FILE_BLOCK_SIZE, block + offset);
|
||||
mapped_read = pread(fd, data, INCFS_DATA_FILE_BLOCK_SIZE,
|
||||
block);
|
||||
|
||||
if (orig_read < mapped_read ||
|
||||
mapped_read != min(size - block,
|
||||
INCFS_DATA_FILE_BLOCK_SIZE)) {
|
||||
ksft_print_msg("Failed to read enough data: %llu %llu %llu %lld %lld\n",
|
||||
block, size, offset, orig_read,
|
||||
mapped_read);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (memcmp(orig_data, data, mapped_read)) {
|
||||
ksft_print_msg("Data doesn't match: %llu %llu %llu %lld %lld\n",
|
||||
block, size, offset, orig_read,
|
||||
mapped_read);
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
result = TEST_SUCCESS;
|
||||
|
||||
failure:
|
||||
close(orig_fd);
|
||||
close(fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int mapped_file_test(const char *mount_dir)
|
||||
{
|
||||
char *backing_dir;
|
||||
int result = TEST_FAILURE;
|
||||
int cmd_fd = -1;
|
||||
int i;
|
||||
struct test_files_set test = get_test_files_set();
|
||||
const int file_num = test.files_count;
|
||||
|
||||
backing_dir = create_backing_dir(mount_dir);
|
||||
if (!backing_dir)
|
||||
goto failure;
|
||||
|
||||
if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0)
|
||||
goto failure;
|
||||
|
||||
cmd_fd = open_commands_file(mount_dir);
|
||||
if (cmd_fd < 0)
|
||||
goto failure;
|
||||
|
||||
for (i = 0; i < file_num; ++i) {
|
||||
struct test_file *file = &test.files[i];
|
||||
size_t blocks = file->size / INCFS_DATA_FILE_BLOCK_SIZE;
|
||||
size_t mapped_offset = blocks / 4 *
|
||||
INCFS_DATA_FILE_BLOCK_SIZE;
|
||||
size_t mapped_size = file->size / 4 * 3 - mapped_offset;
|
||||
struct incfs_create_mapped_file_args mfa;
|
||||
char mapped_file_name[FILENAME_MAX];
|
||||
char orig_file_path[PATH_MAX];
|
||||
char mapped_file_path[PATH_MAX];
|
||||
|
||||
if (emit_file(cmd_fd, NULL, file->name, &file->id, file->size,
|
||||
NULL) < 0)
|
||||
goto failure;
|
||||
|
||||
if (emit_test_file_data(mount_dir, file))
|
||||
goto failure;
|
||||
|
||||
if (snprintf(mapped_file_name, ARRAY_SIZE(mapped_file_name),
|
||||
"%s.mapped", file->name) < 0)
|
||||
goto failure;
|
||||
|
||||
mfa = (struct incfs_create_mapped_file_args) {
|
||||
.size = mapped_size,
|
||||
.mode = 0664,
|
||||
.file_name = ptr_to_u64(mapped_file_name),
|
||||
.source_file_id = file->id,
|
||||
.source_offset = mapped_offset,
|
||||
};
|
||||
|
||||
result = ioctl(cmd_fd, INCFS_IOC_CREATE_MAPPED_FILE, &mfa);
|
||||
if (result) {
|
||||
ksft_print_msg(
|
||||
"Failed to create mapped file with error %d\n",
|
||||
result);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
result = snprintf(orig_file_path,
|
||||
ARRAY_SIZE(orig_file_path), "%s/%s",
|
||||
mount_dir, file->name);
|
||||
|
||||
if (result < 0 || result >= ARRAY_SIZE(mapped_file_path)) {
|
||||
result = TEST_FAILURE;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
result = snprintf(mapped_file_path,
|
||||
ARRAY_SIZE(mapped_file_path), "%s/%s",
|
||||
mount_dir, mapped_file_name);
|
||||
|
||||
if (result < 0 || result >= ARRAY_SIZE(mapped_file_path)) {
|
||||
result = TEST_FAILURE;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
result = validate_mapped_file(orig_file_path, mapped_file_path,
|
||||
mapped_size, mapped_offset);
|
||||
if (result)
|
||||
goto failure;
|
||||
}
|
||||
|
||||
failure:
|
||||
close(cmd_fd);
|
||||
umount(mount_dir);
|
||||
free(backing_dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2953,7 +2791,6 @@ int main(int argc, char *argv[])
|
||||
MAKE_TEST(get_blocks_test),
|
||||
MAKE_TEST(get_hash_blocks_test),
|
||||
MAKE_TEST(large_file_test),
|
||||
MAKE_TEST(mapped_file_test),
|
||||
};
|
||||
#undef MAKE_TEST
|
||||
|
||||
|
||||
Reference in New Issue
Block a user