From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/fs/incfs/vfs.c | 48 +++++++++++++++++++++++++++++++++++++----------- 1 files changed, 37 insertions(+), 11 deletions(-) diff --git a/kernel/fs/incfs/vfs.c b/kernel/fs/incfs/vfs.c index 342998f..f393f17 100644 --- a/kernel/fs/incfs/vfs.c +++ b/kernel/fs/incfs/vfs.c @@ -5,6 +5,7 @@ #include <linux/blkdev.h> #include <linux/compat.h> +#include <linux/delay.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/fs_stack.h> @@ -477,7 +478,8 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f, int block_index, struct mem_range range, - struct mem_range tmp) + struct mem_range tmp, + unsigned int *delayed_min_us) { struct mount_info *mi = df->df_mount_info; struct incfs_read_data_file_timeouts timeouts = { @@ -509,7 +511,23 @@ } return incfs_read_data_file_block(range, f, block_index, tmp, - &timeouts); + &timeouts, delayed_min_us); +} + +static int usleep_interruptible(u32 us) +{ + /* See: + * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt + * for explanation + */ + if (us < 10) { + udelay(us); + return 0; + } else if (us < 20000) { + usleep_range(us, us + us / 10); + return 0; + } else + return msleep_interruptible(us / 1000); } static int read_single_page(struct file *f, struct page *page) @@ -522,6 +540,7 @@ int result = 0; void *page_start; int block_index; + unsigned int delayed_min_us = 0; if (!df) { SetPageError(page); @@ -547,7 +566,8 @@ bytes_to_read = min_t(loff_t, size - offset, PAGE_SIZE); read_result = read_single_page_timeouts(df, f, block_index, - range(page_start, bytes_to_read), tmp); + range(page_start, bytes_to_read), tmp, + &delayed_min_us); free_pages((unsigned long)tmp.data, get_order(tmp.len)); } else { @@ -569,6 +589,8 @@ flush_dcache_page(page); kunmap(page); unlock_page(page); + if (delayed_min_us) + usleep_interruptible(delayed_min_us); return result; } @@ -662,8 +684,7 @@ dput(file); } -static void maybe_delete_incomplete_file(struct file *f, - struct data_file *df) +static void handle_file_completed(struct file *f, struct data_file *df) { struct backing_file_context *bfc; struct mount_info *mi = df->df_mount_info; @@ -671,9 +692,6 @@ struct dentry *incomplete_file_dentry = NULL; const struct cred *old_cred = override_creds(mi->mi_owner); int error; - - if (atomic_read(&df->df_data_blocks_written) < df->df_data_block_count) - goto out; /* Truncate file to remove any preallocated space */ bfc = df->df_backing_file_context; @@ -733,6 +751,7 @@ u8 *data_buf = NULL; ssize_t error = 0; int i = 0; + bool complete = false; if (!df) return -EBADF; @@ -774,7 +793,7 @@ data_buf); } else { error = incfs_process_new_data_block(df, &fill_block, - data_buf); + data_buf, &complete); } if (error) break; @@ -783,7 +802,8 @@ if (data_buf) free_pages((unsigned long)data_buf, get_order(data_buf_size)); - maybe_delete_incomplete_file(f, df); + if (complete) + handle_file_completed(f, df); /* * Only report the error if no records were processed, otherwise @@ -1908,6 +1928,13 @@ pr_debug("incfs: unmount\n"); + /* + * We must kill the super before freeing mi, since killing the super + * triggers inode eviction, which triggers the final update of the + * backing file, which uses certain information for mi + */ + kill_anon_super(sb); + if (mi) { if (mi->mi_backing_dir_path.dentry) dinode = d_inode(mi->mi_backing_dir_path.dentry); @@ -1923,7 +1950,6 @@ incfs_free_mount_info(mi); sb->s_fs_info = NULL; } - kill_anon_super(sb); } static int show_options(struct seq_file *m, struct dentry *root) -- Gitblit v1.6.2