aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lawrence2020-11-30 13:36:28 -0600
committerPaul Lawrence2020-12-11 10:08:10 -0600
commitc18f2a956e7321eb6f9798b4d026cae47727437e (patch)
treebe03038bc5e9910d1f70353cb7cc7535249ca831
parent82e433b1dd8d83842a994bc8237dfc4c241154af (diff)
downloadkernel-c18f2a956e7321eb6f9798b4d026cae47727437e.tar.gz
kernel-c18f2a956e7321eb6f9798b4d026cae47727437e.tar.xz
kernel-c18f2a956e7321eb6f9798b4d026cae47727437e.zip
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
-rw-r--r--fs/incfs/data_mgmt.c48
-rw-r--r--fs/incfs/data_mgmt.h4
-rw-r--r--fs/incfs/pseudo_files.c2
-rw-r--r--fs/incfs/vfs.c25
-rw-r--r--include/uapi/linux/incrementalfs.h22
-rw-r--r--tools/testing/selftests/filesystems/incfs/incfs_test.c18
6 files changed, 71 insertions, 48 deletions
diff --git a/fs/incfs/data_mgmt.c b/fs/incfs/data_mgmt.c
index 48ab7428d627..09b781501d79 100644
--- a/fs/incfs/data_mgmt.c
+++ b/fs/incfs/data_mgmt.c
@@ -1005,9 +1005,25 @@ static void notify_pending_reads(struct mount_info *mi,
1005 wake_up_all(&mi->mi_blocks_written_notif_wq); 1005 wake_up_all(&mi->mi_blocks_written_notif_wq);
1006} 1006}
1007 1007
1008static int usleep_interruptible(u32 us)
1009{
1010 /* See:
1011 * https://www.kernel.org/doc/Documentation/timers/timers-howto.txt
1012 * for explanation
1013 */
1014 if (us < 10) {
1015 udelay(us);
1016 return 0;
1017 } else if (us < 20000) {
1018 usleep_range(us, us + us / 10);
1019 return 0;
1020 } else
1021 return msleep_interruptible(us / 1000);
1022}
1023
1008static int wait_for_data_block(struct data_file *df, int block_index, 1024static int wait_for_data_block(struct data_file *df, int block_index,
1009 int min_time_ms, int min_pending_time_ms, 1025 u32 min_time_us, u32 min_pending_time_us,
1010 int max_pending_time_ms, 1026 u32 max_pending_time_us,
1011 struct data_file_block *res_block) 1027 struct data_file_block *res_block)
1012{ 1028{
1013 struct data_file_block block = {}; 1029 struct data_file_block block = {};
@@ -1044,13 +1060,13 @@ static int wait_for_data_block(struct data_file *df, int block_index,
1044 1060
1045 /* If the block was found, just return it. No need to wait. */ 1061 /* If the block was found, just return it. No need to wait. */
1046 if (is_data_block_present(&block)) { 1062 if (is_data_block_present(&block)) {
1047 if (min_time_ms) 1063 if (min_time_us)
1048 error = msleep_interruptible(min_time_ms); 1064 error = usleep_interruptible(min_time_us);
1049 *res_block = block; 1065 *res_block = block;
1050 return error; 1066 return error;
1051 } else { 1067 } else {
1052 /* If it's not found, create a pending read */ 1068 /* If it's not found, create a pending read */
1053 if (max_pending_time_ms != 0) { 1069 if (max_pending_time_us != 0) {
1054 read = add_pending_read(df, block_index); 1070 read = add_pending_read(df, block_index);
1055 if (!read) 1071 if (!read)
1056 return -ENOMEM; 1072 return -ENOMEM;
@@ -1060,14 +1076,14 @@ static int wait_for_data_block(struct data_file *df, int block_index,
1060 } 1076 }
1061 } 1077 }
1062 1078
1063 if (min_pending_time_ms) 1079 if (min_pending_time_us)
1064 time = ktime_get_ns(); 1080 time = ktime_get_ns();
1065 1081
1066 /* Wait for notifications about block's arrival */ 1082 /* Wait for notifications about block's arrival */
1067 wait_res = 1083 wait_res =
1068 wait_event_interruptible_timeout(segment->new_data_arrival_wq, 1084 wait_event_interruptible_timeout(segment->new_data_arrival_wq,
1069 (is_read_done(read)), 1085 (is_read_done(read)),
1070 msecs_to_jiffies(max_pending_time_ms)); 1086 usecs_to_jiffies(max_pending_time_us));
1071 1087
1072 /* Woke up, the pending read is no longer needed. */ 1088 /* Woke up, the pending read is no longer needed. */
1073 remove_pending_read(df, read); 1089 remove_pending_read(df, read);
@@ -1085,11 +1101,11 @@ static int wait_for_data_block(struct data_file *df, int block_index,
1085 return wait_res; 1101 return wait_res;
1086 } 1102 }
1087 1103
1088 if (min_pending_time_ms) { 1104 if (min_pending_time_us) {
1089 time = div_u64(ktime_get_ns() - time, 1000000); 1105 time = div_u64(ktime_get_ns() - time, 1000);
1090 if (min_pending_time_ms > time) { 1106 if (min_pending_time_us > time) {
1091 error = msleep_interruptible( 1107 error = usleep_interruptible(
1092 min_pending_time_ms - time); 1108 min_pending_time_us - time);
1093 if (error) 1109 if (error)
1094 return error; 1110 return error;
1095 } 1111 }
@@ -1122,8 +1138,8 @@ static int wait_for_data_block(struct data_file *df, int block_index,
1122} 1138}
1123 1139
1124ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, 1140ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
1125 int index, int min_time_ms, 1141 int index, u32 min_time_us,
1126 int min_pending_time_ms, int max_pending_time_ms, 1142 u32 min_pending_time_us, u32 max_pending_time_us,
1127 struct mem_range tmp) 1143 struct mem_range tmp)
1128{ 1144{
1129 loff_t pos; 1145 loff_t pos;
@@ -1143,8 +1159,8 @@ ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
1143 mi = df->df_mount_info; 1159 mi = df->df_mount_info;
1144 bf = df->df_backing_file_context->bc_file; 1160 bf = df->df_backing_file_context->bc_file;
1145 1161
1146 result = wait_for_data_block(df, index, min_time_ms, 1162 result = wait_for_data_block(df, index, min_time_us,
1147 min_pending_time_ms, max_pending_time_ms, &block); 1163 min_pending_time_us, max_pending_time_us, &block);
1148 if (result < 0) 1164 if (result < 0)
1149 goto out; 1165 goto out;
1150 1166
diff --git a/fs/incfs/data_mgmt.h b/fs/incfs/data_mgmt.h
index a63af708fa6d..76b16999f854 100644
--- a/fs/incfs/data_mgmt.h
+++ b/fs/incfs/data_mgmt.h
@@ -335,8 +335,8 @@ struct dir_file *incfs_open_dir_file(struct mount_info *mi, struct file *bf);
335void incfs_free_dir_file(struct dir_file *dir); 335void incfs_free_dir_file(struct dir_file *dir);
336 336
337ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f, 337ssize_t incfs_read_data_file_block(struct mem_range dst, struct file *f,
338 int index, int min_time_ms, 338 int index, u32 min_time_us,
339 int min_pending_time_ms, int max_pending_time_ms, 339 u32 min_pending_time_us, u32 max_pending_time_us,
340 struct mem_range tmp); 340 struct mem_range tmp);
341 341
342int incfs_get_filled_blocks(struct data_file *df, 342int incfs_get_filled_blocks(struct data_file *df,
diff --git a/fs/incfs/pseudo_files.c b/fs/incfs/pseudo_files.c
index 768abd4269cf..8067f47a920d 100644
--- a/fs/incfs/pseudo_files.c
+++ b/fs/incfs/pseudo_files.c
@@ -1018,7 +1018,7 @@ static long ioctl_set_read_timeouts(struct mount_info *mi, void __user *arg)
1018 for (i = 0; i < size / sizeof(*buffer); ++i) { 1018 for (i = 0; i < size / sizeof(*buffer); ++i) {
1019 struct incfs_per_uid_read_timeouts *t = &buffer[i]; 1019 struct incfs_per_uid_read_timeouts *t = &buffer[i];
1020 1020
1021 if (t->min_pending_time_ms > t->max_pending_time_ms) { 1021 if (t->min_pending_time_us > t->max_pending_time_us) {
1022 error = -EINVAL; 1022 error = -EINVAL;
1023 goto out; 1023 goto out;
1024 } 1024 }
diff --git a/fs/incfs/vfs.c b/fs/incfs/vfs.c
index 40192863eb4e..f3f65ddfa64c 100644
--- a/fs/incfs/vfs.c
+++ b/fs/incfs/vfs.c
@@ -198,6 +198,8 @@ static int parse_options(struct mount_options *opts, char *str)
198 case Opt_read_timeout: 198 case Opt_read_timeout:
199 if (match_int(&args[0], &value)) 199 if (match_int(&args[0], &value))
200 return -EINVAL; 200 return -EINVAL;
201 if (value > 3600000)
202 return -EINVAL;
201 opts->read_timeout_ms = value; 203 opts->read_timeout_ms = value;
202 break; 204 break;
203 case Opt_readahead_pages: 205 case Opt_readahead_pages:
@@ -407,9 +409,9 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f,
407 struct mem_range tmp) 409 struct mem_range tmp)
408{ 410{
409 struct mount_info *mi = df->df_mount_info; 411 struct mount_info *mi = df->df_mount_info;
410 u32 min_time_ms = 0; 412 u32 min_time_us = 0;
411 u32 min_pending_time_ms = 0; 413 u32 min_pending_time_us = 0;
412 u32 max_pending_time_ms = U32_MAX; 414 u32 max_pending_time_us = U32_MAX;
413 int uid = current_uid().val; 415 int uid = current_uid().val;
414 int i; 416 int i;
415 417
@@ -420,18 +422,23 @@ static int read_single_page_timeouts(struct data_file *df, struct file *f,
420 &mi->mi_per_uid_read_timeouts[i]; 422 &mi->mi_per_uid_read_timeouts[i];
421 423
422 if(t->uid == uid) { 424 if(t->uid == uid) {
423 min_time_ms = t->min_time_ms; 425 min_time_us = t->min_time_us;
424 min_pending_time_ms = t->min_pending_time_ms; 426 min_pending_time_us = t->min_pending_time_us;
425 max_pending_time_ms = t->max_pending_time_ms; 427 max_pending_time_us = t->max_pending_time_us;
426 break; 428 break;
427 } 429 }
428 } 430 }
429 spin_unlock(&mi->mi_per_uid_read_timeouts_lock); 431 spin_unlock(&mi->mi_per_uid_read_timeouts_lock);
430 if (max_pending_time_ms == U32_MAX) 432 if (max_pending_time_us == U32_MAX) {
431 max_pending_time_ms = mi->mi_options.read_timeout_ms; 433 u64 read_timeout_us = (u64)mi->mi_options.read_timeout_ms *
434 1000;
435
436 max_pending_time_us = read_timeout_us <= U32_MAX ?
437 read_timeout_us : U32_MAX;
438 }
432 439
433 return incfs_read_data_file_block(range, f, block_index, 440 return incfs_read_data_file_block(range, f, block_index,
434 min_time_ms, min_pending_time_ms, max_pending_time_ms, 441 min_time_us, min_pending_time_us, max_pending_time_us,
435 tmp); 442 tmp);
436} 443}
437 444
diff --git a/include/uapi/linux/incrementalfs.h b/include/uapi/linux/incrementalfs.h
index 4a05570fe4d2..e59072c53fb9 100644
--- a/include/uapi/linux/incrementalfs.h
+++ b/include/uapi/linux/incrementalfs.h
@@ -490,24 +490,24 @@ struct incfs_per_uid_read_timeouts {
490 __u32 uid; 490 __u32 uid;
491 491
492 /* 492 /*
493 * Min time to read any block. Note that this doesn't apply to reads 493 * Min time in microseconds to read any block. Note that this doesn't
494 * which are satisfied from the page cache. 494 * apply to reads which are satisfied from the page cache.
495 */ 495 */
496 __u32 min_time_ms; 496 __u32 min_time_us;
497 497
498 /* 498 /*
499 * Min time to satisfy a pending read. Must be >= min_time_ms. Any 499 * Min time in microseconds to satisfy a pending read. Any pending read
500 * pending read which is filled before this time will be delayed so 500 * which is filled before this time will be delayed so that the total
501 * that the total read time >= this value. 501 * read time >= this value.
502 */ 502 */
503 __u32 min_pending_time_ms; 503 __u32 min_pending_time_us;
504 504
505 /* 505 /*
506 * Max time to satisfy a pending read before the read times out. 506 * Max time in microseconds to satisfy a pending read before the read
507 * If set to U32_MAX, defaults to mount options read_timeout_ms= 507 * times out. If set to U32_MAX, defaults to mount options
508 * Must be >= min_pending_time_ms 508 * read_timeout_ms * 1000. Must be >= min_pending_time_us
509 */ 509 */
510 __u32 max_pending_time_ms; 510 __u32 max_pending_time_us;
511}; 511};
512 512
513/* 513/*
diff --git a/tools/testing/selftests/filesystems/incfs/incfs_test.c b/tools/testing/selftests/filesystems/incfs/incfs_test.c
index de9fccf6b608..ce5d3432a224 100644
--- a/tools/testing/selftests/filesystems/incfs/incfs_test.c
+++ b/tools/testing/selftests/filesystems/incfs/incfs_test.c
@@ -3358,9 +3358,9 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
3358 struct incfs_per_uid_read_timeouts purt_set[] = { 3358 struct incfs_per_uid_read_timeouts purt_set[] = {
3359 { 3359 {
3360 .uid = 0, 3360 .uid = 0,
3361 .min_time_ms = 1000, 3361 .min_time_us = 1000000,
3362 .min_pending_time_ms = 2000, 3362 .min_pending_time_us = 2000000,
3363 .max_pending_time_ms = 3000, 3363 .max_pending_time_us = 3000000,
3364 }, 3364 },
3365 }; 3365 };
3366 struct incfs_set_read_timeouts_args srt = { 3366 struct incfs_set_read_timeouts_args srt = {
@@ -3402,11 +3402,11 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
3402 TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0); 3402 TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0);
3403 TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get)); 3403 TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get));
3404 TESTEQUAL(purt_get[0].uid, purt_set[0].uid); 3404 TESTEQUAL(purt_get[0].uid, purt_set[0].uid);
3405 TESTEQUAL(purt_get[0].min_time_ms, purt_set[0].min_time_ms); 3405 TESTEQUAL(purt_get[0].min_time_us, purt_set[0].min_time_us);
3406 TESTEQUAL(purt_get[0].min_pending_time_ms, 3406 TESTEQUAL(purt_get[0].min_pending_time_us,
3407 purt_set[0].min_pending_time_ms); 3407 purt_set[0].min_pending_time_us);
3408 TESTEQUAL(purt_get[0].max_pending_time_ms, 3408 TESTEQUAL(purt_get[0].max_pending_time_us,
3409 purt_set[0].max_pending_time_ms); 3409 purt_set[0].max_pending_time_us);
3410 3410
3411 /* Still 1000 in UID 2 */ 3411 /* Still 1000 in UID 2 */
3412 TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0); 3412 TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
@@ -3421,7 +3421,7 @@ static int per_uid_read_timeouts_test(const char *mount_dir)
3421 TESTEQUAL(is_close(&start, 1000), 0); 3421 TESTEQUAL(is_close(&start, 1000), 0);
3422 3422
3423 /* Set it to default */ 3423 /* Set it to default */
3424 purt_set[0].max_pending_time_ms = UINT32_MAX; 3424 purt_set[0].max_pending_time_us = UINT32_MAX;
3425 TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0); 3425 TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
3426 TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0); 3426 TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3427 TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1); 3427 TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);