diff options
Diffstat (limited to 'io_uring/sqpoll.c')
| -rw-r--r-- | io_uring/sqpoll.c | 65 | 
1 files changed, 45 insertions, 20 deletions
diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c index a3f11349ce06..e22f072c7d5f 100644 --- a/io_uring/sqpoll.c +++ b/io_uring/sqpoll.c @@ -11,6 +11,7 @@  #include <linux/audit.h>  #include <linux/security.h>  #include <linux/cpuset.h> +#include <linux/sched/cputime.h>  #include <linux/io_uring.h>  #include <uapi/linux/io_uring.h> @@ -169,7 +170,38 @@ static inline bool io_sqd_events_pending(struct io_sq_data *sqd)  	return READ_ONCE(sqd->state);  } -static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries) +struct io_sq_time { +	bool started; +	u64 usec; +}; + +u64 io_sq_cpu_usec(struct task_struct *tsk) +{ +	u64 utime, stime; + +	task_cputime_adjusted(tsk, &utime, &stime); +	do_div(stime, 1000); +	return stime; +} + +static void io_sq_update_worktime(struct io_sq_data *sqd, struct io_sq_time *ist) +{ +	if (!ist->started) +		return; +	ist->started = false; +	sqd->work_time += io_sq_cpu_usec(current) - ist->usec; +} + +static void io_sq_start_worktime(struct io_sq_time *ist) +{ +	if (ist->started) +		return; +	ist->started = true; +	ist->usec = io_sq_cpu_usec(current); +} + +static int __io_sq_thread(struct io_ring_ctx *ctx, struct io_sq_data *sqd, +			  bool cap_entries, struct io_sq_time *ist)  {  	unsigned int to_submit;  	int ret = 0; @@ -182,6 +214,8 @@ static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries)  	if (to_submit || !wq_list_empty(&ctx->iopoll_list)) {  		const struct cred *creds = NULL; +		io_sq_start_worktime(ist); +  		if (ctx->sq_creds != current_cred())  			creds = override_creds(ctx->sq_creds); @@ -255,23 +289,11 @@ static bool io_sq_tw_pending(struct llist_node *retry_list)  	return retry_list || !llist_empty(&tctx->task_list);  } -static void io_sq_update_worktime(struct io_sq_data *sqd, struct rusage *start) -{ -	struct rusage end; - -	getrusage(current, RUSAGE_SELF, &end); -	end.ru_stime.tv_sec -= start->ru_stime.tv_sec; -	end.ru_stime.tv_usec -= start->ru_stime.tv_usec; - -	sqd->work_time += end.ru_stime.tv_usec + end.ru_stime.tv_sec * 1000000; -} -  static int io_sq_thread(void *data)  {  	struct llist_node *retry_list = NULL;  	struct io_sq_data *sqd = data;  	struct io_ring_ctx *ctx; -	struct rusage start;  	unsigned long timeout = 0;  	char buf[TASK_COMM_LEN] = {};  	DEFINE_WAIT(wait); @@ -309,6 +331,7 @@ static int io_sq_thread(void *data)  	mutex_lock(&sqd->lock);  	while (1) {  		bool cap_entries, sqt_spin = false; +		struct io_sq_time ist = { };  		if (io_sqd_events_pending(sqd) || signal_pending(current)) {  			if (io_sqd_handle_event(sqd)) @@ -317,9 +340,8 @@ static int io_sq_thread(void *data)  		}  		cap_entries = !list_is_singular(&sqd->ctx_list); -		getrusage(current, RUSAGE_SELF, &start);  		list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { -			int ret = __io_sq_thread(ctx, cap_entries); +			int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist);  			if (!sqt_spin && (ret > 0 || !wq_list_empty(&ctx->iopoll_list)))  				sqt_spin = true; @@ -327,15 +349,18 @@ static int io_sq_thread(void *data)  		if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE))  			sqt_spin = true; -		list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) -			if (io_napi(ctx)) +		list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { +			if (io_napi(ctx)) { +				io_sq_start_worktime(&ist);  				io_napi_sqpoll_busy_poll(ctx); +			} +		} + +		io_sq_update_worktime(sqd, &ist);  		if (sqt_spin || !time_after(jiffies, timeout)) { -			if (sqt_spin) { -				io_sq_update_worktime(sqd, &start); +			if (sqt_spin)  				timeout = jiffies + sqd->sq_thread_idle; -			}  			if (unlikely(need_resched())) {  				mutex_unlock(&sqd->lock);  				cond_resched();  | 
