vendor/rockchip/common/modular_kernel/4.19/incrementalfs_patch/0021-ANDROID-Incremental-fs...

251 lines
8.4 KiB
Diff

From 80f43471ceb913040175b9d3d9a7e5ae04f3b59c Mon Sep 17 00:00:00 2001
From: Paul Lawrence <paullawrence@google.com>
Date: Mon, 30 Nov 2020 11:36:28 -0800
Subject: [PATCH 21/31] ANDROID: Incremental fs: Change per UID timeouts to
microseconds
Bug: 174495152
Test: incfs_test passes
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: I41c23d5f38adab35ee6fab25a6926a8a6aebe2e8
---
fs/incfs/data_mgmt.c | 48 ++++++++++++++++++++----------
fs/incfs/data_mgmt.h | 4 +--
fs/incfs/pseudo_files.c | 2 +-
fs/incfs/vfs.c | 25 ++++++++++------
include/uapi/linux/incrementalfs.h | 22 +++++++-------
5 files changed, 62 insertions(+), 39 deletions(-)
diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c
index 703cad49724e..52165f08f3a7 100644
--- a/fs/incfs/data_mgmt.c
+++ b/fs/incfs/data_mgmt.c
@@ -1071,9 +1071,25 @@ static void notify_pending_reads(struct mount_info *mi,
wake_up_all(&mi->mi_blocks_written_notif_wq);
}
+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 wait_for_data_block(struct data_file *df, int block_index,
- int min_time_ms, int min_pending_time_ms,
- int max_pending_time_ms,
+ u32 min_time_us, u32 min_pending_time_us,
+ u32 max_pending_time_us,
struct data_file_block *res_block)
{
struct data_file_block block = {};
@@ -1110,13 +1126,13 @@ static int wait_for_data_block(struct data_file *df, int block_index,
/* If the block was found, just return it. No need to wait. */
if (is_data_block_present(&block)) {
- if (min_time_ms)
- error = msleep_interruptible(min_time_ms);
+ if (min_time_us)
+ error = usleep_interruptible(min_time_us);
*res_block = block;
return error;
} else {
/* If it's not found, create a pending read */
- if (max_pending_time_ms != 0) {
+ if (max_pending_time_us != 0) {
read = add_pending_read(df, block_index);
if (!read)
return -ENOMEM;
@@ -1126,14 +1142,14 @@ static int wait_for_data_block(struct data_file *df, int block_index,
}
}
- if (min_pending_time_ms)
+ if (min_pending_time_us)
time = ktime_get_ns();
/* Wait for notifications about block's arrival */
wait_res =
wait_event_interruptible_timeout(segment->new_data_arrival_wq,
(is_read_done(read)),
- msecs_to_jiffies(max_pending_time_ms));
+ usecs_to_jiffies(max_pending_time_us));
/* Woke up, the pending read is no longer needed. */
remove_pending_read(df, read);
@@ -1151,11 +1167,11 @@ static int wait_for_data_block(struct data_file *df, int block_index,
return wait_res;
}
- if (min_pending_time_ms) {
- time = div_u64(ktime_get_ns() - time, 1000000);
- if (min_pending_time_ms > time) {
- error = msleep_interruptible(
- min_pending_time_ms - time);
+ if (min_pending_time_us) {
+ time = div_u64(ktime_get_ns() - time, 1000);
+ if (min_pending_time_us > time) {
+ error = usleep_interruptible(
+ min_pending_time_us - time);
if (error)
return error;
}
@@ -1188,8 +1204,8 @@ static int wait_for_data_block(struct data_file *df, int block_index,
}
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
- int index, int min_time_ms,
- int min_pending_time_ms, int max_pending_time_ms,
+ int index, u32 min_time_us,
+ u32 min_pending_time_us, u32 max_pending_time_us,
struct mem_range tmp)
{
loff_t pos;
@@ -1209,8 +1225,8 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
mi = df->df_mount_info;
bf = df->df_backing_file_context->bc_file;
- result = wait_for_data_block(df, index, min_time_ms,
- min_pending_time_ms, max_pending_time_ms, &block);
+ result = wait_for_data_block(df, index, min_time_us,
+ min_pending_time_us, max_pending_time_us, &block);
if (result < 0)
goto out;
diff --git a/fs/incfs/data_mgmt.h b/fs/incfs/data_mgmt.h
index 4ed06dbb05aa..516e2e0dd5da 100644
--- a/fs/incfs/data_mgmt.h
+++ b/fs/incfs/data_mgmt.h
@@ -373,8 +373,8 @@ struct dir_file *incfs_open_dir_file(struct mount_info *mi, struct file *bf);
void incfs_free_dir_file(struct dir_file *dir);
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
- int index, int min_time_ms,
- int min_pending_time_ms, int max_pending_time_ms,
+ int index, u32 min_time_us,
+ u32 min_pending_time_us, u32 max_pending_time_us,
struct mem_range tmp);
int incfs_get_filled_blocks(struct data_file *df,
diff --git a/fs/incfs/pseudo_files.c b/fs/incfs/pseudo_files.c
index 8d2e4a26792e..fd9e0581fe39 100644
--- a/fs/incfs/pseudo_files.c
+++ b/fs/incfs/pseudo_files.c
@@ -972,7 +972,7 @@ static long ioctl_set_read_timeouts(struct mount_info *mi, void __user *arg)
for (i = 0; i < size / sizeof(*buffer); ++i) {
struct incfs_per_uid_read_timeouts *t = &buffer[i];
- if (t->min_pending_time_ms > t->max_pending_time_ms) {
+ if (t->min_pending_time_us > t->max_pending_time_us) {
error = -EINVAL;
goto out;
}
diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c
index 00279ae04878..46dfabfebd52 100644
--- a/fs/incfs/vfs.c
+++ b/fs/incfs/vfs.c
@@ -239,6 +239,8 @@ static int parse_options(struct mount_options *opts, char *str)
case Opt_read_timeout:
if (match_int(&args[0], &value))
return -EINVAL;
+ if (value > 3600000)
+ return -EINVAL;
opts->read_timeout_ms = value;
break;
case Opt_readahead_pages:
@@ -458,9 +460,9 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f,
struct mem_range tmp)
{
struct mount_info *mi = df->df_mount_info;
- u32 min_time_ms = 0;
- u32 min_pending_time_ms = 0;
- u32 max_pending_time_ms = U32_MAX;
+ u32 min_time_us = 0;
+ u32 min_pending_time_us = 0;
+ u32 max_pending_time_us = U32_MAX;
int uid = current_uid().val;
int i;
@@ -471,18 +473,23 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f,
&mi->mi_per_uid_read_timeouts[i];
if(t->uid == uid) {
- min_time_ms = t->min_time_ms;
- min_pending_time_ms = t->min_pending_time_ms;
- max_pending_time_ms = t->max_pending_time_ms;
+ min_time_us = t->min_time_us;
+ min_pending_time_us = t->min_pending_time_us;
+ max_pending_time_us = t->max_pending_time_us;
break;
}
}
spin_unlock(&mi->mi_per_uid_read_timeouts_lock);
- if (max_pending_time_ms == U32_MAX)
- max_pending_time_ms = mi->mi_options.read_timeout_ms;
+ if (max_pending_time_us == U32_MAX) {
+ u64 read_timeout_us = (u64)mi->mi_options.read_timeout_ms *
+ 1000;
+
+ max_pending_time_us = read_timeout_us <= U32_MAX ?
+ read_timeout_us : U32_MAX;
+ }
return incfs_read_data_file_block(range, f, block_index,
- min_time_ms, min_pending_time_ms, max_pending_time_ms,
+ min_time_us, min_pending_time_us, max_pending_time_us,
tmp);
}
diff --git a/include/uapi/linux/incrementalfs.h b/include/uapi/linux/incrementalfs.h
index dae528d9d0c0..32fa517cd635 100644
--- a/include/uapi/linux/incrementalfs.h
+++ b/include/uapi/linux/incrementalfs.h
@@ -482,24 +482,24 @@ struct incfs_per_uid_read_timeouts {
__u32 uid;
/*
- * Min time to read any block. Note that this doesn't apply to reads
- * which are satisfied from the page cache.
+ * Min time in microseconds to read any block. Note that this doesn't
+ * apply to reads which are satisfied from the page cache.
*/
- __u32 min_time_ms;
+ __u32 min_time_us;
/*
- * Min time to satisfy a pending read. Must be >= min_time_ms. Any
- * pending read which is filled before this time will be delayed so
- * that the total read time >= this value.
+ * Min time in microseconds to satisfy a pending read. Any pending read
+ * which is filled before this time will be delayed so that the total
+ * read time >= this value.
*/
- __u32 min_pending_time_ms;
+ __u32 min_pending_time_us;
/*
- * Max time to satisfy a pending read before the read times out.
- * If set to U32_MAX, defaults to mount options read_timeout_ms=
- * Must be >= min_pending_time_ms
+ * Max time in microseconds to satisfy a pending read before the read
+ * times out. If set to U32_MAX, defaults to mount options
+ * read_timeout_ms * 1000. Must be >= min_pending_time_us
*/
- __u32 max_pending_time_ms;
+ __u32 max_pending_time_us;
};
/*
--
2.17.1