Loading fs/incfs/data_mgmt.c +15 −15 Original line number Original line Diff line number Diff line Loading @@ -144,7 +144,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) if (!S_ISREG(bf->f_inode->i_mode)) if (!S_ISREG(bf->f_inode->i_mode)) return ERR_PTR(-EBADF); return ERR_PTR(-EBADF); bfc = incfs_alloc_bfc(bf); bfc = incfs_alloc_bfc(mi, bf); if (IS_ERR(bfc)) if (IS_ERR(bfc)) return ERR_CAST(bfc); return ERR_CAST(bfc); Loading Loading @@ -199,6 +199,7 @@ void incfs_free_data_file(struct data_file *df) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) data_file_segment_destroy(&df->df_segments[i]); data_file_segment_destroy(&df->df_segments[i]); incfs_free_bfc(df->df_backing_file_context); incfs_free_bfc(df->df_backing_file_context); kfree(df->df_signature); kfree(df); kfree(df); } } Loading Loading @@ -387,8 +388,8 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16)); schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16)); } } static int validate_hash_tree(struct file *bf, struct file *f, int block_index, static int validate_hash_tree(struct backing_file_context *bfc, struct file *f, struct mem_range data, u8 *buf) int block_index, struct mem_range data, u8 *buf) { { struct data_file *df = get_incfs_data_file(f); struct data_file *df = get_incfs_data_file(f); u8 stored_digest[INCFS_MAX_HASH_SIZE] = {}; u8 stored_digest[INCFS_MAX_HASH_SIZE] = {}; Loading Loading @@ -445,7 +446,7 @@ static int validate_hash_tree(struct file *bf, struct file *f, int block_index, if (page) if (page) put_page(page); put_page(page); res = incfs_kread(bf, buf, INCFS_DATA_FILE_BLOCK_SIZE, res = incfs_kread(bfc, buf, INCFS_DATA_FILE_BLOCK_SIZE, hash_block_offset[lvl] + sig->hash_offset); hash_block_offset[lvl] + sig->hash_offset); if (res < 0) if (res < 0) return res; return res; Loading Loading @@ -918,7 +919,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, ssize_t result; ssize_t result; size_t bytes_to_read; size_t bytes_to_read; struct mount_info *mi = NULL; struct mount_info *mi = NULL; struct file *bf = NULL; struct backing_file_context *bfc = NULL; struct data_file_block block = {}; struct data_file_block block = {}; struct data_file *df = get_incfs_data_file(f); struct data_file *df = get_incfs_data_file(f); Loading @@ -929,7 +930,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, return -ERANGE; return -ERANGE; mi = df->df_mount_info; mi = df->df_mount_info; bf = df->df_backing_file_context->bc_file; bfc = df->df_backing_file_context; result = wait_for_data_block(df, index, timeout_ms, &block); result = wait_for_data_block(df, index, timeout_ms, &block); if (result < 0) if (result < 0) Loading @@ -938,20 +939,20 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, pos = block.db_backing_file_data_offset; pos = block.db_backing_file_data_offset; if (block.db_comp_alg == COMPRESSION_NONE) { if (block.db_comp_alg == COMPRESSION_NONE) { bytes_to_read = min(dst.len, block.db_stored_size); bytes_to_read = min(dst.len, block.db_stored_size); result = incfs_kread(bf, dst.data, bytes_to_read, pos); result = incfs_kread(bfc, dst.data, bytes_to_read, pos); /* Some data was read, but not enough */ /* Some data was read, but not enough */ if (result >= 0 && result != bytes_to_read) if (result >= 0 && result != bytes_to_read) result = -EIO; result = -EIO; } else { } else { bytes_to_read = min(tmp.len, block.db_stored_size); bytes_to_read = min(tmp.len, block.db_stored_size); result = incfs_kread(bf, tmp.data, bytes_to_read, pos); result = incfs_kread(bfc, tmp.data, bytes_to_read, pos); if (result == bytes_to_read) { if (result == bytes_to_read) { result = result = decompress(range(tmp.data, bytes_to_read), dst); decompress(range(tmp.data, bytes_to_read), dst); if (result < 0) { if (result < 0) { const char *name = const char *name = bf->f_path.dentry->d_name.name; bfc->bc_file->f_path.dentry->d_name.name; pr_warn_once("incfs: Decompression error. %s", pr_warn_once("incfs: Decompression error. %s", name); name); Loading @@ -963,7 +964,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, } } if (result > 0) { if (result > 0) { int err = validate_hash_tree(bf, f, index, dst, tmp.data); int err = validate_hash_tree(bfc, f, index, dst, tmp.data); if (err < 0) if (err < 0) result = err; result = err; Loading Loading @@ -1026,14 +1027,13 @@ int incfs_process_new_data_block(struct data_file *df, unlock: unlock: mutex_unlock(&segment->blockmap_mutex); mutex_unlock(&segment->blockmap_mutex); if (error) if (error) pr_debug("incfs: %s %d error: %d\n", __func__, pr_debug("%d error: %d\n", block->block_index, error); block->block_index, error); return error; return error; } } int incfs_read_file_signature(struct data_file *df, struct mem_range dst) int incfs_read_file_signature(struct data_file *df, struct mem_range dst) { { struct file *bf = df->df_backing_file_context->bc_file; struct backing_file_context *bfc = df->df_backing_file_context; struct incfs_df_signature *sig; struct incfs_df_signature *sig; int read_res = 0; int read_res = 0; Loading @@ -1047,7 +1047,7 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst) if (dst.len < sig->sig_size) if (dst.len < sig->sig_size) return -E2BIG; return -E2BIG; read_res = incfs_kread(bf, dst.data, sig->sig_size, sig->sig_offset); read_res = incfs_kread(bfc, dst.data, sig->sig_size, sig->sig_offset); if (read_res < 0) if (read_res < 0) return read_res; return read_res; Loading Loading @@ -1173,7 +1173,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg, goto out; goto out; } } read = incfs_kread(df->df_backing_file_context->bc_file, buf, read = incfs_kread(df->df_backing_file_context, buf, signature->sig_size, signature->sig_offset); signature->sig_size, signature->sig_offset); if (read < 0) { if (read < 0) { error = read; error = read; Loading fs/incfs/format.c +22 −12 Original line number Original line Diff line number Diff line Loading @@ -15,7 +15,8 @@ #include "format.h" #include "format.h" #include "data_mgmt.h" #include "data_mgmt.h" struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, struct file *backing_file) { { struct backing_file_context *result = NULL; struct backing_file_context *result = NULL; Loading @@ -24,6 +25,7 @@ struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM); result->bc_file = get_file(backing_file); result->bc_file = get_file(backing_file); result->bc_cred = mi->mi_owner; mutex_init(&result->bc_mutex); mutex_init(&result->bc_mutex); return result; return result; } } Loading Loading @@ -116,7 +118,7 @@ static int append_zeros(struct backing_file_context *bfc, size_t len) static int write_to_bf(struct backing_file_context *bfc, const void *buf, static int write_to_bf(struct backing_file_context *bfc, const void *buf, size_t count, loff_t pos) size_t count, loff_t pos) { { ssize_t res = incfs_kwrite(bfc->bc_file, buf, count, pos); ssize_t res = incfs_kwrite(bfc, buf, count, pos); if (res < 0) if (res < 0) return res; return res; Loading Loading @@ -531,8 +533,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, if (start_index < 0 || bm_base_off <= 0) if (start_index < 0 || bm_base_off <= 0) return -ENODATA; return -ENODATA; result = incfs_kread(bfc->bc_file, entries, bytes_to_read, result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off); bm_entry_off); if (result < 0) if (result < 0) return result; return result; return result / sizeof(*entries); return result / sizeof(*entries); Loading @@ -548,8 +549,7 @@ int incfs_read_file_header(struct backing_file_context *bfc, if (!bfc || !first_md_off) if (!bfc || !first_md_off) return -EFAULT; return -EFAULT; LOCK_REQUIRED(bfc->bc_mutex); bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0); bytes_read = incfs_kread(bfc->bc_file, &fh, sizeof(fh), 0); if (bytes_read < 0) if (bytes_read < 0) return bytes_read; return bytes_read; Loading Loading @@ -603,8 +603,8 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return -EPERM; return -EPERM; memset(&handler->md_buffer, 0, max_md_size); memset(&handler->md_buffer, 0, max_md_size); bytes_read = incfs_kread(bfc->bc_file, &handler->md_buffer, bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size, max_md_size, handler->md_record_offset); handler->md_record_offset); if (bytes_read < 0) if (bytes_read < 0) return bytes_read; return bytes_read; if (bytes_read < sizeof(*md_hdr)) if (bytes_read < sizeof(*md_hdr)) Loading Loading @@ -680,12 +680,22 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return res; return res; } } ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos) ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, loff_t pos) { { return kernel_read(f, buf, size, &pos); const struct cred *old_cred = override_creds(bfc->bc_cred); int ret = kernel_read(bfc->bc_file, buf, size, &pos); revert_creds(old_cred); return ret; } } ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos) ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, size_t size, loff_t pos) { { return kernel_write(f, buf, size, &pos); const struct cred *old_cred = override_creds(bfc->bc_cred); int ret = kernel_write(bfc->bc_file, buf, size, &pos); revert_creds(old_cred); return ret; } } fs/incfs/format.h +14 −3 Original line number Original line Diff line number Diff line Loading @@ -256,6 +256,13 @@ struct backing_file_context { * 0 means there are no metadata records. * 0 means there are no metadata records. */ */ loff_t bc_last_md_record_offset; loff_t bc_last_md_record_offset; /* * Credentials to set before reads/writes * Note that this is a pointer to the mount_info mi_owner field so * there is no need to get/put the creds */ const struct cred *bc_cred; }; }; struct metadata_handler { struct metadata_handler { Loading Loading @@ -283,7 +290,9 @@ struct metadata_handler { loff_t incfs_get_end_offset(struct file *f); loff_t incfs_get_end_offset(struct file *f); /* Backing file context management */ /* Backing file context management */ struct backing_file_context *incfs_alloc_bfc(struct file *backing_file); struct mount_info; struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, struct file *backing_file); void incfs_free_bfc(struct backing_file_context *bfc); void incfs_free_bfc(struct backing_file_context *bfc); Loading Loading @@ -334,7 +343,9 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, int incfs_read_next_metadata_record(struct backing_file_context *bfc, int incfs_read_next_metadata_record(struct backing_file_context *bfc, struct metadata_handler *handler); struct metadata_handler *handler); ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos); ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos); loff_t pos); ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, size_t size, loff_t pos); #endif /* _INCFS_FORMAT_H */ #endif /* _INCFS_FORMAT_H */ fs/incfs/main.c +10 −0 Original line number Original line Diff line number Diff line Loading @@ -30,8 +30,18 @@ static ssize_t corefs_show(struct kobject *kobj, static struct kobj_attribute corefs_attr = __ATTR_RO(corefs); static struct kobj_attribute corefs_attr = __ATTR_RO(corefs); static ssize_t mounter_context_for_backing_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buff) { return scnprintf(buff, PAGE_SIZE, "%s", "supported\n"); } static struct kobj_attribute mounter_context_for_backing_rw_attr = __ATTR_RO(mounter_context_for_backing_rw); static struct attribute *attributes[] = { static struct attribute *attributes[] = { &corefs_attr.attr, &corefs_attr.attr, &mounter_context_for_backing_rw_attr.attr, NULL, NULL, }; }; Loading fs/incfs/vfs.c +14 −8 Original line number Original line Diff line number Diff line Loading @@ -604,8 +604,11 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect); reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect); while (reads_to_collect > 0) { while (reads_to_collect > 0) { struct read_log_state next_state = READ_ONCE(log_state->state); struct read_log_state next_state; int reads_collected = incfs_collect_logged_reads( int reads_collected; memcpy(&next_state, &log_state->state, sizeof(next_state)); reads_collected = incfs_collect_logged_reads( mi, &next_state, reads_buf, mi, &next_state, reads_buf, min_t(ssize_t, reads_to_collect, reads_per_page)); min_t(ssize_t, reads_to_collect, reads_per_page)); if (reads_collected <= 0) { if (reads_collected <= 0) { Loading @@ -624,7 +627,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, goto out; goto out; } } WRITE_ONCE(log_state->state, next_state); memcpy(&log_state->state, &next_state, sizeof(next_state)); total_reads_collected += reads_collected; total_reads_collected += reads_collected; buf += reads_collected * sizeof(*reads_buf); buf += reads_collected * sizeof(*reads_buf); reads_to_collect -= reads_collected; reads_to_collect -= reads_collected; Loading Loading @@ -897,14 +900,14 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .dentry = dentry .dentry = dentry }; }; new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); current_cred()); if (IS_ERR(new_file)) { if (IS_ERR(new_file)) { error = PTR_ERR(new_file); error = PTR_ERR(new_file); goto out; goto out; } } bfc = incfs_alloc_bfc(new_file); bfc = incfs_alloc_bfc(mi, new_file); fput(new_file); fput(new_file); if (IS_ERR(bfc)) { if (IS_ERR(bfc)) { error = PTR_ERR(bfc); error = PTR_ERR(bfc); Loading Loading @@ -1025,7 +1028,7 @@ static int dir_relative_path_resolve( if (dir_fd < 0) if (dir_fd < 0) return dir_fd; return dir_fd; dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner); dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred()); if (IS_ERR(dir_f)) { if (IS_ERR(dir_f)) { error = PTR_ERR(dir_f); error = PTR_ERR(dir_f); Loading Loading @@ -1903,10 +1906,13 @@ static int file_open(struct inode *inode, struct file *file) struct file *backing_file = NULL; struct file *backing_file = NULL; struct path backing_path = {}; struct path backing_path = {}; int err = 0; int err = 0; const struct cred *old_cred; get_incfs_backing_path(file->f_path.dentry, &backing_path); get_incfs_backing_path(file->f_path.dentry, &backing_path); backing_file = dentry_open( old_cred = override_creds(mi->mi_owner); &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); backing_file = dentry_open(&backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, current_cred()); revert_creds(old_cred); path_put(&backing_path); path_put(&backing_path); if (IS_ERR(backing_file)) { if (IS_ERR(backing_file)) { Loading Loading
fs/incfs/data_mgmt.c +15 −15 Original line number Original line Diff line number Diff line Loading @@ -144,7 +144,7 @@ struct data_file *incfs_open_data_file(struct mount_info *mi, struct file *bf) if (!S_ISREG(bf->f_inode->i_mode)) if (!S_ISREG(bf->f_inode->i_mode)) return ERR_PTR(-EBADF); return ERR_PTR(-EBADF); bfc = incfs_alloc_bfc(bf); bfc = incfs_alloc_bfc(mi, bf); if (IS_ERR(bfc)) if (IS_ERR(bfc)) return ERR_CAST(bfc); return ERR_CAST(bfc); Loading Loading @@ -199,6 +199,7 @@ void incfs_free_data_file(struct data_file *df) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) for (i = 0; i < ARRAY_SIZE(df->df_segments); i++) data_file_segment_destroy(&df->df_segments[i]); data_file_segment_destroy(&df->df_segments[i]); incfs_free_bfc(df->df_backing_file_context); incfs_free_bfc(df->df_backing_file_context); kfree(df->df_signature); kfree(df); kfree(df); } } Loading Loading @@ -387,8 +388,8 @@ static void log_block_read(struct mount_info *mi, incfs_uuid_t *id, schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16)); schedule_delayed_work(&log->ml_wakeup_work, msecs_to_jiffies(16)); } } static int validate_hash_tree(struct file *bf, struct file *f, int block_index, static int validate_hash_tree(struct backing_file_context *bfc, struct file *f, struct mem_range data, u8 *buf) int block_index, struct mem_range data, u8 *buf) { { struct data_file *df = get_incfs_data_file(f); struct data_file *df = get_incfs_data_file(f); u8 stored_digest[INCFS_MAX_HASH_SIZE] = {}; u8 stored_digest[INCFS_MAX_HASH_SIZE] = {}; Loading Loading @@ -445,7 +446,7 @@ static int validate_hash_tree(struct file *bf, struct file *f, int block_index, if (page) if (page) put_page(page); put_page(page); res = incfs_kread(bf, buf, INCFS_DATA_FILE_BLOCK_SIZE, res = incfs_kread(bfc, buf, INCFS_DATA_FILE_BLOCK_SIZE, hash_block_offset[lvl] + sig->hash_offset); hash_block_offset[lvl] + sig->hash_offset); if (res < 0) if (res < 0) return res; return res; Loading Loading @@ -918,7 +919,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, ssize_t result; ssize_t result; size_t bytes_to_read; size_t bytes_to_read; struct mount_info *mi = NULL; struct mount_info *mi = NULL; struct file *bf = NULL; struct backing_file_context *bfc = NULL; struct data_file_block block = {}; struct data_file_block block = {}; struct data_file *df = get_incfs_data_file(f); struct data_file *df = get_incfs_data_file(f); Loading @@ -929,7 +930,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, return -ERANGE; return -ERANGE; mi = df->df_mount_info; mi = df->df_mount_info; bf = df->df_backing_file_context->bc_file; bfc = df->df_backing_file_context; result = wait_for_data_block(df, index, timeout_ms, &block); result = wait_for_data_block(df, index, timeout_ms, &block); if (result < 0) if (result < 0) Loading @@ -938,20 +939,20 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, pos = block.db_backing_file_data_offset; pos = block.db_backing_file_data_offset; if (block.db_comp_alg == COMPRESSION_NONE) { if (block.db_comp_alg == COMPRESSION_NONE) { bytes_to_read = min(dst.len, block.db_stored_size); bytes_to_read = min(dst.len, block.db_stored_size); result = incfs_kread(bf, dst.data, bytes_to_read, pos); result = incfs_kread(bfc, dst.data, bytes_to_read, pos); /* Some data was read, but not enough */ /* Some data was read, but not enough */ if (result >= 0 && result != bytes_to_read) if (result >= 0 && result != bytes_to_read) result = -EIO; result = -EIO; } else { } else { bytes_to_read = min(tmp.len, block.db_stored_size); bytes_to_read = min(tmp.len, block.db_stored_size); result = incfs_kread(bf, tmp.data, bytes_to_read, pos); result = incfs_kread(bfc, tmp.data, bytes_to_read, pos); if (result == bytes_to_read) { if (result == bytes_to_read) { result = result = decompress(range(tmp.data, bytes_to_read), dst); decompress(range(tmp.data, bytes_to_read), dst); if (result < 0) { if (result < 0) { const char *name = const char *name = bf->f_path.dentry->d_name.name; bfc->bc_file->f_path.dentry->d_name.name; pr_warn_once("incfs: Decompression error. %s", pr_warn_once("incfs: Decompression error. %s", name); name); Loading @@ -963,7 +964,7 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, } } if (result > 0) { if (result > 0) { int err = validate_hash_tree(bf, f, index, dst, tmp.data); int err = validate_hash_tree(bfc, f, index, dst, tmp.data); if (err < 0) if (err < 0) result = err; result = err; Loading Loading @@ -1026,14 +1027,13 @@ int incfs_process_new_data_block(struct data_file *df, unlock: unlock: mutex_unlock(&segment->blockmap_mutex); mutex_unlock(&segment->blockmap_mutex); if (error) if (error) pr_debug("incfs: %s %d error: %d\n", __func__, pr_debug("%d error: %d\n", block->block_index, error); block->block_index, error); return error; return error; } } int incfs_read_file_signature(struct data_file *df, struct mem_range dst) int incfs_read_file_signature(struct data_file *df, struct mem_range dst) { { struct file *bf = df->df_backing_file_context->bc_file; struct backing_file_context *bfc = df->df_backing_file_context; struct incfs_df_signature *sig; struct incfs_df_signature *sig; int read_res = 0; int read_res = 0; Loading @@ -1047,7 +1047,7 @@ int incfs_read_file_signature(struct data_file *df, struct mem_range dst) if (dst.len < sig->sig_size) if (dst.len < sig->sig_size) return -E2BIG; return -E2BIG; read_res = incfs_kread(bf, dst.data, sig->sig_size, sig->sig_offset); read_res = incfs_kread(bfc, dst.data, sig->sig_size, sig->sig_offset); if (read_res < 0) if (read_res < 0) return read_res; return read_res; Loading Loading @@ -1173,7 +1173,7 @@ static int process_file_signature_md(struct incfs_file_signature *sg, goto out; goto out; } } read = incfs_kread(df->df_backing_file_context->bc_file, buf, read = incfs_kread(df->df_backing_file_context, buf, signature->sig_size, signature->sig_offset); signature->sig_size, signature->sig_offset); if (read < 0) { if (read < 0) { error = read; error = read; Loading
fs/incfs/format.c +22 −12 Original line number Original line Diff line number Diff line Loading @@ -15,7 +15,8 @@ #include "format.h" #include "format.h" #include "data_mgmt.h" #include "data_mgmt.h" struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, struct file *backing_file) { { struct backing_file_context *result = NULL; struct backing_file_context *result = NULL; Loading @@ -24,6 +25,7 @@ struct backing_file_context *incfs_alloc_bfc(struct file *backing_file) return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM); result->bc_file = get_file(backing_file); result->bc_file = get_file(backing_file); result->bc_cred = mi->mi_owner; mutex_init(&result->bc_mutex); mutex_init(&result->bc_mutex); return result; return result; } } Loading Loading @@ -116,7 +118,7 @@ static int append_zeros(struct backing_file_context *bfc, size_t len) static int write_to_bf(struct backing_file_context *bfc, const void *buf, static int write_to_bf(struct backing_file_context *bfc, const void *buf, size_t count, loff_t pos) size_t count, loff_t pos) { { ssize_t res = incfs_kwrite(bfc->bc_file, buf, count, pos); ssize_t res = incfs_kwrite(bfc, buf, count, pos); if (res < 0) if (res < 0) return res; return res; Loading Loading @@ -531,8 +533,7 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, if (start_index < 0 || bm_base_off <= 0) if (start_index < 0 || bm_base_off <= 0) return -ENODATA; return -ENODATA; result = incfs_kread(bfc->bc_file, entries, bytes_to_read, result = incfs_kread(bfc, entries, bytes_to_read, bm_entry_off); bm_entry_off); if (result < 0) if (result < 0) return result; return result; return result / sizeof(*entries); return result / sizeof(*entries); Loading @@ -548,8 +549,7 @@ int incfs_read_file_header(struct backing_file_context *bfc, if (!bfc || !first_md_off) if (!bfc || !first_md_off) return -EFAULT; return -EFAULT; LOCK_REQUIRED(bfc->bc_mutex); bytes_read = incfs_kread(bfc, &fh, sizeof(fh), 0); bytes_read = incfs_kread(bfc->bc_file, &fh, sizeof(fh), 0); if (bytes_read < 0) if (bytes_read < 0) return bytes_read; return bytes_read; Loading Loading @@ -603,8 +603,8 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return -EPERM; return -EPERM; memset(&handler->md_buffer, 0, max_md_size); memset(&handler->md_buffer, 0, max_md_size); bytes_read = incfs_kread(bfc->bc_file, &handler->md_buffer, bytes_read = incfs_kread(bfc, &handler->md_buffer, max_md_size, max_md_size, handler->md_record_offset); handler->md_record_offset); if (bytes_read < 0) if (bytes_read < 0) return bytes_read; return bytes_read; if (bytes_read < sizeof(*md_hdr)) if (bytes_read < sizeof(*md_hdr)) Loading Loading @@ -680,12 +680,22 @@ int incfs_read_next_metadata_record(struct backing_file_context *bfc, return res; return res; } } ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos) ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, loff_t pos) { { return kernel_read(f, buf, size, &pos); const struct cred *old_cred = override_creds(bfc->bc_cred); int ret = kernel_read(bfc->bc_file, buf, size, &pos); revert_creds(old_cred); return ret; } } ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos) ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, size_t size, loff_t pos) { { return kernel_write(f, buf, size, &pos); const struct cred *old_cred = override_creds(bfc->bc_cred); int ret = kernel_write(bfc->bc_file, buf, size, &pos); revert_creds(old_cred); return ret; } }
fs/incfs/format.h +14 −3 Original line number Original line Diff line number Diff line Loading @@ -256,6 +256,13 @@ struct backing_file_context { * 0 means there are no metadata records. * 0 means there are no metadata records. */ */ loff_t bc_last_md_record_offset; loff_t bc_last_md_record_offset; /* * Credentials to set before reads/writes * Note that this is a pointer to the mount_info mi_owner field so * there is no need to get/put the creds */ const struct cred *bc_cred; }; }; struct metadata_handler { struct metadata_handler { Loading Loading @@ -283,7 +290,9 @@ struct metadata_handler { loff_t incfs_get_end_offset(struct file *f); loff_t incfs_get_end_offset(struct file *f); /* Backing file context management */ /* Backing file context management */ struct backing_file_context *incfs_alloc_bfc(struct file *backing_file); struct mount_info; struct backing_file_context *incfs_alloc_bfc(struct mount_info *mi, struct file *backing_file); void incfs_free_bfc(struct backing_file_context *bfc); void incfs_free_bfc(struct backing_file_context *bfc); Loading Loading @@ -334,7 +343,9 @@ int incfs_read_blockmap_entries(struct backing_file_context *bfc, int incfs_read_next_metadata_record(struct backing_file_context *bfc, int incfs_read_next_metadata_record(struct backing_file_context *bfc, struct metadata_handler *handler); struct metadata_handler *handler); ssize_t incfs_kread(struct file *f, void *buf, size_t size, loff_t pos); ssize_t incfs_kread(struct backing_file_context *bfc, void *buf, size_t size, ssize_t incfs_kwrite(struct file *f, const void *buf, size_t size, loff_t pos); loff_t pos); ssize_t incfs_kwrite(struct backing_file_context *bfc, const void *buf, size_t size, loff_t pos); #endif /* _INCFS_FORMAT_H */ #endif /* _INCFS_FORMAT_H */
fs/incfs/main.c +10 −0 Original line number Original line Diff line number Diff line Loading @@ -30,8 +30,18 @@ static ssize_t corefs_show(struct kobject *kobj, static struct kobj_attribute corefs_attr = __ATTR_RO(corefs); static struct kobj_attribute corefs_attr = __ATTR_RO(corefs); static ssize_t mounter_context_for_backing_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buff) { return scnprintf(buff, PAGE_SIZE, "%s", "supported\n"); } static struct kobj_attribute mounter_context_for_backing_rw_attr = __ATTR_RO(mounter_context_for_backing_rw); static struct attribute *attributes[] = { static struct attribute *attributes[] = { &corefs_attr.attr, &corefs_attr.attr, &mounter_context_for_backing_rw_attr.attr, NULL, NULL, }; }; Loading
fs/incfs/vfs.c +14 −8 Original line number Original line Diff line number Diff line Loading @@ -604,8 +604,11 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect); reads_to_collect = min_t(ssize_t, rl_size, reads_to_collect); while (reads_to_collect > 0) { while (reads_to_collect > 0) { struct read_log_state next_state = READ_ONCE(log_state->state); struct read_log_state next_state; int reads_collected = incfs_collect_logged_reads( int reads_collected; memcpy(&next_state, &log_state->state, sizeof(next_state)); reads_collected = incfs_collect_logged_reads( mi, &next_state, reads_buf, mi, &next_state, reads_buf, min_t(ssize_t, reads_to_collect, reads_per_page)); min_t(ssize_t, reads_to_collect, reads_per_page)); if (reads_collected <= 0) { if (reads_collected <= 0) { Loading @@ -624,7 +627,7 @@ static ssize_t log_read(struct file *f, char __user *buf, size_t len, goto out; goto out; } } WRITE_ONCE(log_state->state, next_state); memcpy(&log_state->state, &next_state, sizeof(next_state)); total_reads_collected += reads_collected; total_reads_collected += reads_collected; buf += reads_collected * sizeof(*reads_buf); buf += reads_collected * sizeof(*reads_buf); reads_to_collect -= reads_collected; reads_to_collect -= reads_collected; Loading Loading @@ -897,14 +900,14 @@ static int init_new_file(struct mount_info *mi, struct dentry *dentry, .dentry = dentry .dentry = dentry }; }; new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, new_file = dentry_open(&path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); current_cred()); if (IS_ERR(new_file)) { if (IS_ERR(new_file)) { error = PTR_ERR(new_file); error = PTR_ERR(new_file); goto out; goto out; } } bfc = incfs_alloc_bfc(new_file); bfc = incfs_alloc_bfc(mi, new_file); fput(new_file); fput(new_file); if (IS_ERR(bfc)) { if (IS_ERR(bfc)) { error = PTR_ERR(bfc); error = PTR_ERR(bfc); Loading Loading @@ -1025,7 +1028,7 @@ static int dir_relative_path_resolve( if (dir_fd < 0) if (dir_fd < 0) return dir_fd; return dir_fd; dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, mi->mi_owner); dir_f = dentry_open(base_path, O_RDONLY | O_NOATIME, current_cred()); if (IS_ERR(dir_f)) { if (IS_ERR(dir_f)) { error = PTR_ERR(dir_f); error = PTR_ERR(dir_f); Loading Loading @@ -1903,10 +1906,13 @@ static int file_open(struct inode *inode, struct file *file) struct file *backing_file = NULL; struct file *backing_file = NULL; struct path backing_path = {}; struct path backing_path = {}; int err = 0; int err = 0; const struct cred *old_cred; get_incfs_backing_path(file->f_path.dentry, &backing_path); get_incfs_backing_path(file->f_path.dentry, &backing_path); backing_file = dentry_open( old_cred = override_creds(mi->mi_owner); &backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, mi->mi_owner); backing_file = dentry_open(&backing_path, O_RDWR | O_NOATIME | O_LARGEFILE, current_cred()); revert_creds(old_cred); path_put(&backing_path); path_put(&backing_path); if (IS_ERR(backing_file)) { if (IS_ERR(backing_file)) { Loading