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: Id76d2fec83a0eb7b70ad85f1fac81bf319563a66
This commit is contained in:
parent
6fb25c4252
commit
5ef8ab7172
@ -1005,9 +1005,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 = {};
|
||||
@ -1044,13 +1060,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;
|
||||
@ -1060,14 +1076,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);
|
||||
@ -1085,11 +1101,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;
|
||||
}
|
||||
@ -1122,8 +1138,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;
|
||||
@ -1143,8 +1159,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;
|
||||
|
||||
|
@ -335,8 +335,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,
|
||||
|
@ -1018,7 +1018,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;
|
||||
}
|
||||
|
@ -199,6 +199,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:
|
||||
@ -408,9 +410,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;
|
||||
|
||||
@ -421,18 +423,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);
|
||||
}
|
||||
|
||||
|
@ -490,24 +490,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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -3358,9 +3358,9 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
|
||||
struct incfs_per_uid_read_timeouts purt_set[] = {
|
||||
{
|
||||
.uid = 0,
|
||||
.min_time_ms = 1000,
|
||||
.min_pending_time_ms = 2000,
|
||||
.max_pending_time_ms = 3000,
|
||||
.min_time_us = 1000000,
|
||||
.min_pending_time_us = 2000000,
|
||||
.max_pending_time_us = 3000000,
|
||||
},
|
||||
};
|
||||
struct incfs_set_read_timeouts_args srt = {
|
||||
@ -3402,11 +3402,11 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
|
||||
TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0);
|
||||
TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get));
|
||||
TESTEQUAL(purt_get[0].uid, purt_set[0].uid);
|
||||
TESTEQUAL(purt_get[0].min_time_ms, purt_set[0].min_time_ms);
|
||||
TESTEQUAL(purt_get[0].min_pending_time_ms,
|
||||
purt_set[0].min_pending_time_ms);
|
||||
TESTEQUAL(purt_get[0].max_pending_time_ms,
|
||||
purt_set[0].max_pending_time_ms);
|
||||
TESTEQUAL(purt_get[0].min_time_us, purt_set[0].min_time_us);
|
||||
TESTEQUAL(purt_get[0].min_pending_time_us,
|
||||
purt_set[0].min_pending_time_us);
|
||||
TESTEQUAL(purt_get[0].max_pending_time_us,
|
||||
purt_set[0].max_pending_time_us);
|
||||
|
||||
/* Still 1000 in UID 2 */
|
||||
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
||||
@ -3421,7 +3421,7 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
|
||||
TESTEQUAL(is_close(&start, 1000), 0);
|
||||
|
||||
/* Set it to default */
|
||||
purt_set[0].max_pending_time_ms = UINT32_MAX;
|
||||
purt_set[0].max_pending_time_us = UINT32_MAX;
|
||||
TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
|
||||
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
||||
TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
|
||||
|
Loading…
Reference in New Issue
Block a user