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);
|
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,
|
static int wait_for_data_block(struct data_file *df, int block_index,
|
||||||
int min_time_ms, int min_pending_time_ms,
|
u32 min_time_us, u32 min_pending_time_us,
|
||||||
int max_pending_time_ms,
|
u32 max_pending_time_us,
|
||||||
struct data_file_block *res_block)
|
struct data_file_block *res_block)
|
||||||
{
|
{
|
||||||
struct data_file_block 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 the block was found, just return it. No need to wait. */
|
||||||
if (is_data_block_present(&block)) {
|
if (is_data_block_present(&block)) {
|
||||||
if (min_time_ms)
|
if (min_time_us)
|
||||||
error = msleep_interruptible(min_time_ms);
|
error = usleep_interruptible(min_time_us);
|
||||||
*res_block = block;
|
*res_block = block;
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
/* If it's not found, create a pending read */
|
/* 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);
|
read = add_pending_read(df, block_index);
|
||||||
if (!read)
|
if (!read)
|
||||||
return -ENOMEM;
|
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();
|
time = ktime_get_ns();
|
||||||
|
|
||||||
/* Wait for notifications about block's arrival */
|
/* Wait for notifications about block's arrival */
|
||||||
wait_res =
|
wait_res =
|
||||||
wait_event_interruptible_timeout(segment->new_data_arrival_wq,
|
wait_event_interruptible_timeout(segment->new_data_arrival_wq,
|
||||||
(is_read_done(read)),
|
(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. */
|
/* Woke up, the pending read is no longer needed. */
|
||||||
remove_pending_read(df, read);
|
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;
|
return wait_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min_pending_time_ms) {
|
if (min_pending_time_us) {
|
||||||
time = div_u64(ktime_get_ns() - time, 1000000);
|
time = div_u64(ktime_get_ns() - time, 1000);
|
||||||
if (min_pending_time_ms > time) {
|
if (min_pending_time_us > time) {
|
||||||
error = msleep_interruptible(
|
error = usleep_interruptible(
|
||||||
min_pending_time_ms - time);
|
min_pending_time_us - time);
|
||||||
if (error)
|
if (error)
|
||||||
return 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,
|
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
||||||
int index, int min_time_ms,
|
int index, u32 min_time_us,
|
||||||
int min_pending_time_ms, int max_pending_time_ms,
|
u32 min_pending_time_us, u32 max_pending_time_us,
|
||||||
struct mem_range tmp)
|
struct mem_range tmp)
|
||||||
{
|
{
|
||||||
loff_t pos;
|
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;
|
mi = df->df_mount_info;
|
||||||
bf = df->df_backing_file_context->bc_file;
|
bf = df->df_backing_file_context->bc_file;
|
||||||
|
|
||||||
result = wait_for_data_block(df, index, min_time_ms,
|
result = wait_for_data_block(df, index, min_time_us,
|
||||||
min_pending_time_ms, max_pending_time_ms, &block);
|
min_pending_time_us, max_pending_time_us, &block);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
goto out;
|
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);
|
void incfs_free_dir_file(struct dir_file *dir);
|
||||||
|
|
||||||
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
|
||||||
int index, int min_time_ms,
|
int index, u32 min_time_us,
|
||||||
int min_pending_time_ms, int max_pending_time_ms,
|
u32 min_pending_time_us, u32 max_pending_time_us,
|
||||||
struct mem_range tmp);
|
struct mem_range tmp);
|
||||||
|
|
||||||
int incfs_get_filled_blocks(struct data_file *df,
|
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) {
|
for (i = 0; i < size / sizeof(*buffer); ++i) {
|
||||||
struct incfs_per_uid_read_timeouts *t = &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;
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -199,6 +199,8 @@ static int parse_options(struct mount_options *opts, char *str)
|
|||||||
case Opt_read_timeout:
|
case Opt_read_timeout:
|
||||||
if (match_int(&args[0], &value))
|
if (match_int(&args[0], &value))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (value > 3600000)
|
||||||
|
return -EINVAL;
|
||||||
opts->read_timeout_ms = value;
|
opts->read_timeout_ms = value;
|
||||||
break;
|
break;
|
||||||
case Opt_readahead_pages:
|
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 mem_range tmp)
|
||||||
{
|
{
|
||||||
struct mount_info *mi = df->df_mount_info;
|
struct mount_info *mi = df->df_mount_info;
|
||||||
u32 min_time_ms = 0;
|
u32 min_time_us = 0;
|
||||||
u32 min_pending_time_ms = 0;
|
u32 min_pending_time_us = 0;
|
||||||
u32 max_pending_time_ms = U32_MAX;
|
u32 max_pending_time_us = U32_MAX;
|
||||||
int uid = current_uid().val;
|
int uid = current_uid().val;
|
||||||
int i;
|
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];
|
&mi->mi_per_uid_read_timeouts[i];
|
||||||
|
|
||||||
if(t->uid == uid) {
|
if(t->uid == uid) {
|
||||||
min_time_ms = t->min_time_ms;
|
min_time_us = t->min_time_us;
|
||||||
min_pending_time_ms = t->min_pending_time_ms;
|
min_pending_time_us = t->min_pending_time_us;
|
||||||
max_pending_time_ms = t->max_pending_time_ms;
|
max_pending_time_us = t->max_pending_time_us;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&mi->mi_per_uid_read_timeouts_lock);
|
spin_unlock(&mi->mi_per_uid_read_timeouts_lock);
|
||||||
if (max_pending_time_ms == U32_MAX)
|
if (max_pending_time_us == U32_MAX) {
|
||||||
max_pending_time_ms = mi->mi_options.read_timeout_ms;
|
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,
|
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);
|
tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,24 +490,24 @@ struct incfs_per_uid_read_timeouts {
|
|||||||
__u32 uid;
|
__u32 uid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Min time to read any block. Note that this doesn't apply to reads
|
* Min time in microseconds to read any block. Note that this doesn't
|
||||||
* which are satisfied from the page cache.
|
* 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
|
* Min time in microseconds to satisfy a pending read. Any pending read
|
||||||
* pending read which is filled before this time will be delayed so
|
* which is filled before this time will be delayed so that the total
|
||||||
* that the total read time >= this value.
|
* 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.
|
* Max time in microseconds to satisfy a pending read before the read
|
||||||
* If set to U32_MAX, defaults to mount options read_timeout_ms=
|
* times out. If set to U32_MAX, defaults to mount options
|
||||||
* Must be >= min_pending_time_ms
|
* 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[] = {
|
struct incfs_per_uid_read_timeouts purt_set[] = {
|
||||||
{
|
{
|
||||||
.uid = 0,
|
.uid = 0,
|
||||||
.min_time_ms = 1000,
|
.min_time_us = 1000000,
|
||||||
.min_pending_time_ms = 2000,
|
.min_pending_time_us = 2000000,
|
||||||
.max_pending_time_ms = 3000,
|
.max_pending_time_us = 3000000,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
struct incfs_set_read_timeouts_args srt = {
|
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(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0);
|
||||||
TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get));
|
TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get));
|
||||||
TESTEQUAL(purt_get[0].uid, purt_set[0].uid);
|
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_time_us, purt_set[0].min_time_us);
|
||||||
TESTEQUAL(purt_get[0].min_pending_time_ms,
|
TESTEQUAL(purt_get[0].min_pending_time_us,
|
||||||
purt_set[0].min_pending_time_ms);
|
purt_set[0].min_pending_time_us);
|
||||||
TESTEQUAL(purt_get[0].max_pending_time_ms,
|
TESTEQUAL(purt_get[0].max_pending_time_us,
|
||||||
purt_set[0].max_pending_time_ms);
|
purt_set[0].max_pending_time_us);
|
||||||
|
|
||||||
/* Still 1000 in UID 2 */
|
/* Still 1000 in UID 2 */
|
||||||
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
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);
|
TESTEQUAL(is_close(&start, 1000), 0);
|
||||||
|
|
||||||
/* Set it to default */
|
/* 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(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
|
||||||
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
|
||||||
TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
|
TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
|
||||||
|
Loading…
Reference in New Issue
Block a user