Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c18f2a95 authored by Paul Lawrence's avatar Paul Lawrence
Browse files

ANDROID: Incremental fs: Change per UID timeouts to microseconds



Bug: 174495152
Test: incfs_test passes
Signed-off-by: default avatarPaul Lawrence <paullawrence@google.com>
Change-Id: Id76d2fec83a0eb7b70ad85f1fac81bf319563a66
parent 82e433b1
Loading
Loading
Loading
Loading
+32 −16
Original line number Diff line number Diff line
@@ -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;

+2 −2
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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;
			}
+16 −9
Original line number Diff line number Diff line
@@ -198,6 +198,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:
@@ -407,9 +409,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;

@@ -420,18 +422,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);
}

+11 −11
Original line number Diff line number Diff line
@@ -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;
};

/*
Loading