* [PATCH 1/2] io_uring: abstract out task work running
2020-07-02 23:06 [PATCHSET 5.9 0/2] io_uring task_work cleanups Jens Axboe
@ 2020-07-02 23:06 ` Jens Axboe
2020-07-02 23:06 ` [PATCH 2/2] io_uring: use new io_req_task_work_add() helper throughout Jens Axboe
1 sibling, 0 replies; 3+ messages in thread
From: Jens Axboe @ 2020-07-02 23:06 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, Oleg Nesterov
Provide a helper to run task_work instead of checking and running
manually in a bunch of different spots. While doing so, also move the
task run state setting where we run the task work. Then we can move it
out of the callback helpers. This also helps ensure we only do this once
per task_work list run, not per task_work item.
Suggested-by: Oleg Nesterov <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
---
fs/io_uring.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index a0c86c726ae3..982f49096580 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1714,7 +1714,6 @@ static void __io_req_task_submit(struct io_kiocb *req)
{
struct io_ring_ctx *ctx = req->ctx;
- __set_current_state(TASK_RUNNING);
if (!__io_sq_thread_acquire_mm(ctx)) {
mutex_lock(&ctx->uring_lock);
__io_queue_sqe(req, NULL, NULL);
@@ -1899,6 +1898,17 @@ static int io_put_kbuf(struct io_kiocb *req)
return cflags;
}
+static inline bool io_run_task_work(void)
+{
+ if (current->task_works) {
+ __set_current_state(TASK_RUNNING);
+ task_work_run();
+ return true;
+ }
+
+ return false;
+}
+
static void io_iopoll_queue(struct list_head *again)
{
struct io_kiocb *req;
@@ -2079,8 +2089,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
*/
if (!(++iters & 7)) {
mutex_unlock(&ctx->uring_lock);
- if (current->task_works)
- task_work_run();
+ io_run_task_work();
mutex_lock(&ctx->uring_lock);
}
@@ -2176,8 +2185,6 @@ static void io_rw_resubmit(struct callback_head *cb)
struct io_ring_ctx *ctx = req->ctx;
int err;
- __set_current_state(TASK_RUNNING);
-
err = io_sq_thread_acquire_mm(ctx, req);
if (io_resubmit_prep(req, err)) {
@@ -6353,8 +6360,7 @@ static int io_sq_thread(void *data)
if (!list_empty(&ctx->poll_list) || need_resched() ||
(!time_after(jiffies, timeout) && ret != -EBUSY &&
!percpu_ref_is_dying(&ctx->refs))) {
- if (current->task_works)
- task_work_run();
+ io_run_task_work();
cond_resched();
continue;
}
@@ -6386,8 +6392,7 @@ static int io_sq_thread(void *data)
finish_wait(&ctx->sqo_wait, &wait);
break;
}
- if (current->task_works) {
- task_work_run();
+ if (io_run_task_work()) {
finish_wait(&ctx->sqo_wait, &wait);
continue;
}
@@ -6412,8 +6417,7 @@ static int io_sq_thread(void *data)
timeout = jiffies + ctx->sq_thread_idle;
}
- if (current->task_works)
- task_work_run();
+ io_run_task_work();
io_sq_thread_drop_mm(ctx);
revert_creds(old_cred);
@@ -6478,9 +6482,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
do {
if (io_cqring_events(ctx, false) >= min_events)
return 0;
- if (!current->task_works)
+ if (!io_run_task_work())
break;
- task_work_run();
} while (1);
if (sig) {
@@ -6502,8 +6505,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
prepare_to_wait_exclusive(&ctx->wait, &iowq.wq,
TASK_INTERRUPTIBLE);
/* make sure we run task_work before checking for signals */
- if (current->task_works)
- task_work_run();
+ if (io_run_task_work())
+ continue;
if (signal_pending(current)) {
ret = -ERESTARTSYS;
break;
@@ -7938,8 +7941,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
int submitted = 0;
struct fd f;
- if (current->task_works)
- task_work_run();
+ io_run_task_work();
if (flags & ~(IORING_ENTER_GETEVENTS | IORING_ENTER_SQ_WAKEUP))
return -EINVAL;
--
2.27.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] io_uring: use new io_req_task_work_add() helper throughout
2020-07-02 23:06 [PATCHSET 5.9 0/2] io_uring task_work cleanups Jens Axboe
2020-07-02 23:06 ` [PATCH 1/2] io_uring: abstract out task work running Jens Axboe
@ 2020-07-02 23:06 ` Jens Axboe
1 sibling, 0 replies; 3+ messages in thread
From: Jens Axboe @ 2020-07-02 23:06 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe
Since we now have that in the 5.9 branch, convert the existing users of
task_work_add() to use this new helper.
Signed-off-by: Jens Axboe <[email protected]>
---
fs/io_uring.c | 62 +++++++++++++++++++++++++--------------------------
1 file changed, 30 insertions(+), 32 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 982f49096580..51132f9bdbcc 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1689,6 +1689,22 @@ static struct io_kiocb *io_req_find_next(struct io_kiocb *req)
return __io_req_find_next(req);
}
+static int io_req_task_work_add(struct io_kiocb *req, struct callback_head *cb,
+ int notify)
+{
+ const bool is_sqthread = (req->ctx->flags & IORING_SETUP_SQPOLL) != 0;
+ struct task_struct *tsk = req->task;
+ int ret;
+
+ if (is_sqthread)
+ notify = 0;
+
+ ret = task_work_add(tsk, cb, notify);
+ if (!ret)
+ wake_up_process(tsk);
+ return ret;
+}
+
static void __io_req_task_cancel(struct io_kiocb *req, int error)
{
struct io_ring_ctx *ctx = req->ctx;
@@ -1732,18 +1748,19 @@ static void io_req_task_submit(struct callback_head *cb)
static void io_req_task_queue(struct io_kiocb *req)
{
- struct task_struct *tsk = req->task;
int ret;
init_task_work(&req->task_work, io_req_task_submit);
- ret = task_work_add(tsk, &req->task_work, true);
+ ret = io_req_task_work_add(req, &req->task_work, TWA_RESUME);
if (unlikely(ret)) {
+ struct task_struct *tsk;
+
init_task_work(&req->task_work, io_req_task_cancel);
tsk = io_wq_get_task(req->ctx->io_wq);
- task_work_add(tsk, &req->task_work, true);
+ task_work_add(tsk, &req->task_work, 0);
+ wake_up_process(tsk);
}
- wake_up_process(tsk);
}
static void io_queue_next(struct io_kiocb *req)
@@ -2197,19 +2214,15 @@ static void io_rw_resubmit(struct callback_head *cb)
static bool io_rw_reissue(struct io_kiocb *req, long res)
{
#ifdef CONFIG_BLOCK
- struct task_struct *tsk;
int ret;
if ((res != -EAGAIN && res != -EOPNOTSUPP) || io_wq_current_is_worker())
return false;
- tsk = req->task;
init_task_work(&req->task_work, io_rw_resubmit);
- ret = task_work_add(tsk, &req->task_work, true);
- if (!ret) {
- wake_up_process(tsk);
+ ret = io_req_task_work_add(req, &req->task_work, TWA_RESUME);
+ if (!ret)
return true;
- }
#endif
return false;
}
@@ -2909,7 +2922,6 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode,
struct io_kiocb *req = wait->private;
struct io_async_rw *rw = &req->io->rw;
struct wait_page_key *key = arg;
- struct task_struct *tsk;
int ret;
wpq = container_of(wait, struct wait_page_queue, wait);
@@ -2923,15 +2935,16 @@ static int io_async_buf_func(struct wait_queue_entry *wait, unsigned mode,
init_task_work(&rw->task_work, io_async_buf_retry);
/* submit ref gets dropped, acquire a new one */
refcount_inc(&req->refs);
- tsk = req->task;
- ret = task_work_add(tsk, &rw->task_work, true);
+ ret = io_req_task_work_add(req, &rw->task_work, TWA_RESUME);
if (unlikely(ret)) {
+ struct task_struct *tsk;
+
/* queue just for cancelation */
init_task_work(&rw->task_work, io_async_buf_cancel);
tsk = io_wq_get_task(req->ctx->io_wq);
- task_work_add(tsk, &rw->task_work, true);
+ task_work_add(tsk, &rw->task_work, 0);
+ wake_up_process(tsk);
}
- wake_up_process(tsk);
return 1;
}
@@ -4424,25 +4437,9 @@ struct io_poll_table {
int error;
};
-static int io_req_task_work_add(struct io_kiocb *req, struct callback_head *cb,
- int notify)
-{
- struct task_struct *tsk = req->task;
- int ret;
-
- if (req->ctx->flags & IORING_SETUP_SQPOLL)
- notify = 0;
-
- ret = task_work_add(tsk, cb, notify);
- if (!ret)
- wake_up_process(tsk);
- return ret;
-}
-
static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
__poll_t mask, task_work_func_t func)
{
- struct task_struct *tsk;
int ret;
/* for instances that support it check for an event match first: */
@@ -4453,7 +4450,6 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
list_del_init(&poll->wait.entry);
- tsk = req->task;
req->result = mask;
init_task_work(&req->task_work, func);
/*
@@ -4464,6 +4460,8 @@ static int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *poll,
*/
ret = io_req_task_work_add(req, &req->task_work, TWA_SIGNAL);
if (unlikely(ret)) {
+ struct task_struct *tsk;
+
WRITE_ONCE(poll->canceled, true);
tsk = io_wq_get_task(req->ctx->io_wq);
task_work_add(tsk, &req->task_work, 0);
--
2.27.0
^ permalink raw reply related [flat|nested] 3+ messages in thread