From e636c8d336489bf3eed5878299e6cc045bbad077 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:17:29 +0000
Subject: [PATCH] debug lk
---
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