* [PATCH 1/8] io_uring: close a small race gap for files cancel
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 2/8] io_uring: further deduplicate #CQ events calc Pavel Begunkov
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring; +Cc: stable
The purpose of io_uring_cancel_files() is to wait for all requests
matching ->files to go/be cancelled. We should first drop files of a
request in io_req_drop_files() and only then make it undiscoverable for
io_uring_cancel_files.
First drop, then delete from list. It's ok to leave req->id->files
dangling, because it's not dereferenced by cancellation code, only
compared against. It would potentially go to sleep and be awaken by
following in io_req_drop_files() wake_up().
Fixes: 0f2122045b946 ("io_uring: don't rely on weak ->files references")
Cc: <[email protected]> # 5.5+
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 8cf6f22afc5e..b74957856e68 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -6098,15 +6098,15 @@ static void io_req_drop_files(struct io_kiocb *req)
struct io_uring_task *tctx = req->task->io_uring;
unsigned long flags;
+ put_files_struct(req->work.identity->files);
+ put_nsproxy(req->work.identity->nsproxy);
spin_lock_irqsave(&ctx->inflight_lock, flags);
list_del(&req->inflight_entry);
- if (atomic_read(&tctx->in_idle))
- wake_up(&tctx->wait);
spin_unlock_irqrestore(&ctx->inflight_lock, flags);
req->flags &= ~REQ_F_INFLIGHT;
- put_files_struct(req->work.identity->files);
- put_nsproxy(req->work.identity->nsproxy);
req->work.flags &= ~IO_WQ_WORK_FILES;
+ if (atomic_read(&tctx->in_idle))
+ wake_up(&tctx->wait);
}
static void __io_clean_op(struct io_kiocb *req)
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/8] io_uring: further deduplicate #CQ events calc
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
2020-12-18 13:12 ` [PATCH 1/8] io_uring: close a small race gap for files cancel Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 3/8] io_uring: account per-task #requests with files Pavel Begunkov
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
Apparently, there is one more place hand coded calculation of number of
CQ events in the ring. Use __io_cqring_events() helper in
io_get_cqring() as well. Naturally, assembly stays identical.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index b74957856e68..1401c1444e77 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1664,21 +1664,25 @@ static inline bool io_sqring_full(struct io_ring_ctx *ctx)
return READ_ONCE(r->sq.tail) - ctx->cached_sq_head == r->sq_ring_entries;
}
+static inline unsigned int __io_cqring_events(struct io_ring_ctx *ctx)
+{
+ return ctx->cached_cq_tail - READ_ONCE(ctx->rings->cq.head);
+}
+
static struct io_uring_cqe *io_get_cqring(struct io_ring_ctx *ctx)
{
struct io_rings *rings = ctx->rings;
unsigned tail;
- tail = ctx->cached_cq_tail;
/*
* writes to the cq entry need to come after reading head; the
* control dependency is enough as we're using WRITE_ONCE to
* fill the cq entry
*/
- if (tail - READ_ONCE(rings->cq.head) == rings->cq_ring_entries)
+ if (__io_cqring_events(ctx) == rings->cq_ring_entries)
return NULL;
- ctx->cached_cq_tail++;
+ tail = ctx->cached_cq_tail++;
return &rings->cqes[tail & ctx->cq_mask];
}
@@ -1693,11 +1697,6 @@ static inline bool io_should_trigger_evfd(struct io_ring_ctx *ctx)
return io_wq_current_is_worker();
}
-static inline unsigned __io_cqring_events(struct io_ring_ctx *ctx)
-{
- return ctx->cached_cq_tail - READ_ONCE(ctx->rings->cq.head);
-}
-
static void io_cqring_ev_posted(struct io_ring_ctx *ctx)
{
if (waitqueue_active(&ctx->wait))
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/8] io_uring: account per-task #requests with files
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
2020-12-18 13:12 ` [PATCH 1/8] io_uring: close a small race gap for files cancel Pavel Begunkov
2020-12-18 13:12 ` [PATCH 2/8] io_uring: further deduplicate #CQ events calc Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 4/8] io_uring: explicitly pass tctx into del_task_file Pavel Begunkov
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
Similarly as we keep tctx->inflight add tctx->inflight_files tracking
number of requests with ->files set. That's a preparation patch, so it's
kept unused for now. Also, as it's not as hot as ->inflight use atomics.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 27 +++++++++++++++++++--------
include/linux/io_uring.h | 1 +
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 1401c1444e77..3a3177739b13 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1497,6 +1497,7 @@ static bool io_grab_identity(struct io_kiocb *req)
req->flags |= REQ_F_INFLIGHT;
spin_lock_irq(&ctx->inflight_lock);
+ atomic_inc(¤t->io_uring->inflight_files);
list_add(&req->inflight_entry, &ctx->inflight_list);
spin_unlock_irq(&ctx->inflight_lock);
req->work.flags |= IO_WQ_WORK_FILES;
@@ -6101,6 +6102,7 @@ static void io_req_drop_files(struct io_kiocb *req)
put_nsproxy(req->work.identity->nsproxy);
spin_lock_irqsave(&ctx->inflight_lock, flags);
list_del(&req->inflight_entry);
+ atomic_dec(&tctx->inflight_files);
spin_unlock_irqrestore(&ctx->inflight_lock, flags);
req->flags &= ~REQ_F_INFLIGHT;
req->work.flags &= ~IO_WQ_WORK_FILES;
@@ -8012,6 +8014,7 @@ static int io_uring_alloc_task_context(struct task_struct *task)
init_waitqueue_head(&tctx->wait);
tctx->last = NULL;
atomic_set(&tctx->in_idle, 0);
+ atomic_set(&tctx->inflight_files, 0);
tctx->sqpoll = false;
io_init_identity(&tctx->__identity);
tctx->identity = &tctx->__identity;
@@ -8927,13 +8930,17 @@ void __io_uring_files_cancel(struct files_struct *files)
atomic_dec(&tctx->in_idle);
}
-static s64 tctx_inflight(struct io_uring_task *tctx)
+static s64 tctx_inflight(struct io_uring_task *tctx, bool files)
{
unsigned long index;
struct file *file;
s64 inflight;
- inflight = percpu_counter_sum(&tctx->inflight);
+ if (files)
+ inflight = atomic_read(&tctx->inflight_files);
+ else
+ inflight = percpu_counter_sum(&tctx->inflight);
+
if (!tctx->sqpoll)
return inflight;
@@ -8943,12 +8950,16 @@ static s64 tctx_inflight(struct io_uring_task *tctx)
*/
xa_for_each(&tctx->xa, index, file) {
struct io_ring_ctx *ctx = file->private_data;
+ struct io_uring_task *sqpoll_tctx;
- if (ctx->flags & IORING_SETUP_SQPOLL) {
- struct io_uring_task *__tctx = ctx->sqo_task->io_uring;
+ if (!(ctx->flags & IORING_SETUP_SQPOLL))
+ continue;
- inflight += percpu_counter_sum(&__tctx->inflight);
- }
+ sqpoll_tctx = ctx->sqo_task->io_uring;
+ if (files)
+ inflight += atomic_read(&sqpoll_tctx->inflight_files);
+ else
+ inflight += percpu_counter_sum(&sqpoll_tctx->inflight);
}
return inflight;
@@ -8969,7 +8980,7 @@ void __io_uring_task_cancel(void)
do {
/* read completions before cancelations */
- inflight = tctx_inflight(tctx);
+ inflight = tctx_inflight(tctx, false);
if (!inflight)
break;
__io_uring_files_cancel(NULL);
@@ -8980,7 +8991,7 @@ void __io_uring_task_cancel(void)
* If we've seen completions, retry. This avoids a race where
* a completion comes in before we did prepare_to_wait().
*/
- if (inflight != tctx_inflight(tctx))
+ if (inflight != tctx_inflight(tctx, false))
continue;
schedule();
} while (1);
diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h
index 35b2d845704d..e1ff6f235d03 100644
--- a/include/linux/io_uring.h
+++ b/include/linux/io_uring.h
@@ -28,6 +28,7 @@ struct io_uring_task {
struct wait_queue_head wait;
struct file *last;
struct percpu_counter inflight;
+ atomic_t inflight_files;
struct io_identity __identity;
struct io_identity *identity;
atomic_t in_idle;
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/8] io_uring: explicitly pass tctx into del_task_file
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
` (2 preceding siblings ...)
2020-12-18 13:12 ` [PATCH 3/8] io_uring: account per-task #requests with files Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 5/8] io_uring: draft files cancel based on inflight cnt Pavel Begunkov
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
Pass tctx to io_uring_del_task_file() from above. No functional changes.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 3a3177739b13..1794ad4bfa39 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -8882,10 +8882,9 @@ static int io_uring_add_task_file(struct io_ring_ctx *ctx, struct file *file)
/*
* Remove this io_uring_file -> task mapping.
*/
-static void io_uring_del_task_file(struct file *file)
+static void io_uring_del_task_file(struct io_uring_task *tctx,
+ struct file *file)
{
- struct io_uring_task *tctx = current->io_uring;
-
if (tctx->last == file)
tctx->last = NULL;
file = xa_erase(&tctx->xa, (unsigned long)file);
@@ -8907,7 +8906,7 @@ static void io_uring_attempt_task_drop(struct file *file)
*/
if (fatal_signal_pending(current) || (current->flags & PF_EXITING) ||
atomic_long_read(&file->f_count) == 2)
- io_uring_del_task_file(file);
+ io_uring_del_task_file(current->io_uring, file);
}
void __io_uring_files_cancel(struct files_struct *files)
@@ -8924,7 +8923,7 @@ void __io_uring_files_cancel(struct files_struct *files)
io_uring_cancel_task_requests(ctx, files);
if (files)
- io_uring_del_task_file(file);
+ io_uring_del_task_file(tctx, file);
}
atomic_dec(&tctx->in_idle);
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/8] io_uring: draft files cancel based on inflight cnt
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
` (3 preceding siblings ...)
2020-12-18 13:12 ` [PATCH 4/8] io_uring: explicitly pass tctx into del_task_file Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 6/8] io_uring: remove old files cancel mechanism Pavel Begunkov
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
Do same thing for files cancellation as we do for task cancellations, in
particular keep trying to cancel while corresponding inflight counters
are not zero.
It's a preparation patch, io_uring_try_task_cancel still guarantees to
kill all requests matching files at first attempt. It also deduplicate a
bit those two functions allowing exporting only __io_uring_task_cancel()
from them to the core.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 29 +++++++++++++++--------------
include/linux/io_uring.h | 12 +++++-------
2 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 1794ad4bfa39..d20a2a96c3f8 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -8909,7 +8909,7 @@ static void io_uring_attempt_task_drop(struct file *file)
io_uring_del_task_file(current->io_uring, file);
}
-void __io_uring_files_cancel(struct files_struct *files)
+static void io_uring_try_task_cancel(struct files_struct *files)
{
struct io_uring_task *tctx = current->io_uring;
struct file *file;
@@ -8917,15 +8917,8 @@ void __io_uring_files_cancel(struct files_struct *files)
/* make sure overflow events are dropped */
atomic_inc(&tctx->in_idle);
-
- xa_for_each(&tctx->xa, index, file) {
- struct io_ring_ctx *ctx = file->private_data;
-
- io_uring_cancel_task_requests(ctx, files);
- if (files)
- io_uring_del_task_file(tctx, file);
- }
-
+ xa_for_each(&tctx->xa, index, file)
+ io_uring_cancel_task_requests(file->private_data, files);
atomic_dec(&tctx->in_idle);
}
@@ -8968,7 +8961,7 @@ static s64 tctx_inflight(struct io_uring_task *tctx, bool files)
* Find any io_uring fd that this task has registered or done IO on, and cancel
* requests.
*/
-void __io_uring_task_cancel(void)
+void __io_uring_task_cancel(struct files_struct *files)
{
struct io_uring_task *tctx = current->io_uring;
DEFINE_WAIT(wait);
@@ -8979,10 +8972,10 @@ void __io_uring_task_cancel(void)
do {
/* read completions before cancelations */
- inflight = tctx_inflight(tctx, false);
+ inflight = tctx_inflight(tctx, !!files);
if (!inflight)
break;
- __io_uring_files_cancel(NULL);
+ io_uring_try_task_cancel(files);
prepare_to_wait(&tctx->wait, &wait, TASK_UNINTERRUPTIBLE);
@@ -8990,13 +8983,21 @@ void __io_uring_task_cancel(void)
* If we've seen completions, retry. This avoids a race where
* a completion comes in before we did prepare_to_wait().
*/
- if (inflight != tctx_inflight(tctx, false))
+ if (inflight != tctx_inflight(tctx, !!files))
continue;
schedule();
} while (1);
finish_wait(&tctx->wait, &wait);
atomic_dec(&tctx->in_idle);
+
+ if (files) {
+ struct file *file;
+ unsigned long index;
+
+ xa_for_each(&tctx->xa, index, file)
+ io_uring_del_task_file(tctx, file);
+ }
}
static int io_uring_flush(struct file *file, void *data)
diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h
index e1ff6f235d03..282f02bd04a5 100644
--- a/include/linux/io_uring.h
+++ b/include/linux/io_uring.h
@@ -37,19 +37,17 @@ struct io_uring_task {
#if defined(CONFIG_IO_URING)
struct sock *io_uring_get_socket(struct file *file);
-void __io_uring_task_cancel(void);
-void __io_uring_files_cancel(struct files_struct *files);
+void __io_uring_task_cancel(struct files_struct *files);
void __io_uring_free(struct task_struct *tsk);
-static inline void io_uring_task_cancel(void)
+static inline void io_uring_files_cancel(struct files_struct *files)
{
if (current->io_uring && !xa_empty(¤t->io_uring->xa))
- __io_uring_task_cancel();
+ __io_uring_task_cancel(files);
}
-static inline void io_uring_files_cancel(struct files_struct *files)
+static inline void io_uring_task_cancel(void)
{
- if (current->io_uring && !xa_empty(¤t->io_uring->xa))
- __io_uring_files_cancel(files);
+ io_uring_files_cancel(NULL);
}
static inline void io_uring_free(struct task_struct *tsk)
{
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/8] io_uring: remove old files cancel mechanism
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
` (4 preceding siblings ...)
2020-12-18 13:12 ` [PATCH 5/8] io_uring: draft files cancel based on inflight cnt Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 7/8] io_uring: cleanup task cancel Pavel Begunkov
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
files cancellation is now based on counters, remove the old way we were
doing that with keeping a list of such requests.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 65 +++++++--------------------------------------------
1 file changed, 9 insertions(+), 56 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index d20a2a96c3f8..4bf709d9db32 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -379,7 +379,6 @@ struct io_ring_ctx {
bool poll_multi_file;
spinlock_t inflight_lock;
- struct list_head inflight_list;
} ____cacheline_aligned_in_smp;
struct delayed_work file_put_work;
@@ -719,10 +718,7 @@ struct io_kiocb {
struct io_kiocb *link;
struct percpu_ref *fixed_file_refs;
- /*
- * 1. used with ctx->iopoll_list with reads/writes
- * 2. to track reqs with ->files (see io_op_def::file_table)
- */
+ /* ctx->iopoll_list, tracks rw requests for iopoll_list */
struct list_head inflight_entry;
struct callback_head task_work;
/* for polled requests, i.e. IORING_OP_POLL_ADD and async armed poll */
@@ -1308,7 +1304,6 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
INIT_LIST_HEAD(&ctx->defer_list);
INIT_LIST_HEAD(&ctx->timeout_list);
spin_lock_init(&ctx->inflight_lock);
- INIT_LIST_HEAD(&ctx->inflight_list);
INIT_DELAYED_WORK(&ctx->file_put_work, io_file_put_work);
init_llist_head(&ctx->file_put_llist);
return ctx;
@@ -1498,7 +1493,6 @@ static bool io_grab_identity(struct io_kiocb *req)
spin_lock_irq(&ctx->inflight_lock);
atomic_inc(¤t->io_uring->inflight_files);
- list_add(&req->inflight_entry, &ctx->inflight_list);
spin_unlock_irq(&ctx->inflight_lock);
req->work.flags |= IO_WQ_WORK_FILES;
}
@@ -6101,7 +6095,6 @@ static void io_req_drop_files(struct io_kiocb *req)
put_files_struct(req->work.identity->files);
put_nsproxy(req->work.identity->nsproxy);
spin_lock_irqsave(&ctx->inflight_lock, flags);
- list_del(&req->inflight_entry);
atomic_dec(&tctx->inflight_files);
spin_unlock_irqrestore(&ctx->inflight_lock, flags);
req->flags &= ~REQ_F_INFLIGHT;
@@ -8739,48 +8732,12 @@ static void io_cancel_defer_files(struct io_ring_ctx *ctx,
}
}
-static void io_uring_cancel_files(struct io_ring_ctx *ctx,
- struct task_struct *task,
- struct files_struct *files)
-{
- while (!list_empty_careful(&ctx->inflight_list)) {
- struct io_task_cancel cancel = { .task = task, .files = files };
- struct io_kiocb *req;
- DEFINE_WAIT(wait);
- bool found = false;
-
- spin_lock_irq(&ctx->inflight_lock);
- list_for_each_entry(req, &ctx->inflight_list, inflight_entry) {
- if (req->task != task ||
- req->work.identity->files != files)
- continue;
- found = true;
- break;
- }
- if (found)
- prepare_to_wait(&task->io_uring->wait, &wait,
- TASK_UNINTERRUPTIBLE);
- spin_unlock_irq(&ctx->inflight_lock);
-
- /* We need to keep going until we don't find a matching req */
- if (!found)
- break;
-
- io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, &cancel, true);
- io_poll_remove_all(ctx, task, files);
- io_kill_timeouts(ctx, task, files);
- /* cancellations _may_ trigger task work */
- io_run_task_work();
- schedule();
- finish_wait(&task->io_uring->wait, &wait);
- }
-}
-
static void __io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
- struct task_struct *task)
+ struct task_struct *task,
+ struct files_struct *files)
{
while (1) {
- struct io_task_cancel cancel = { .task = task, .files = NULL, };
+ struct io_task_cancel cancel = { .task = task, .files = files };
enum io_wq_cancel cret;
bool ret = false;
@@ -8789,18 +8746,18 @@ static void __io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
ret = true;
/* SQPOLL thread does its own polling */
- if (!(ctx->flags & IORING_SETUP_SQPOLL)) {
+ if (!(ctx->flags & IORING_SETUP_SQPOLL) && !files) {
while (!list_empty_careful(&ctx->iopoll_list)) {
io_iopoll_try_reap_events(ctx);
ret = true;
}
}
- ret |= io_poll_remove_all(ctx, task, NULL);
- ret |= io_kill_timeouts(ctx, task, NULL);
+ ret |= io_poll_remove_all(ctx, task, files);
+ ret |= io_kill_timeouts(ctx, task, files);
+ io_run_task_work();
if (!ret)
break;
- io_run_task_work();
cond_resched();
}
}
@@ -8825,11 +8782,7 @@ static void io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
io_ring_submit_lock(ctx, (ctx->flags & IORING_SETUP_IOPOLL));
io_cqring_overflow_flush(ctx, true, task, files);
io_ring_submit_unlock(ctx, (ctx->flags & IORING_SETUP_IOPOLL));
-
- if (!files)
- __io_uring_cancel_task_requests(ctx, task);
- else
- io_uring_cancel_files(ctx, task, files);
+ __io_uring_cancel_task_requests(ctx, task, files);
if ((ctx->flags & IORING_SETUP_SQPOLL) && ctx->sq_data) {
atomic_dec(&task->io_uring->in_idle);
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/8] io_uring: cleanup task cancel
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
` (5 preceding siblings ...)
2020-12-18 13:12 ` [PATCH 6/8] io_uring: remove old files cancel mechanism Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 13:12 ` [PATCH 8/8] io_uring: kill not used anymore inflight_lock Pavel Begunkov
2020-12-18 15:16 ` [PATCH 0/8] a fix + cancellation unification Jens Axboe
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
There is no use of io_uring_try_task_cancel(), inline it, kill extra
in_idle inc/dec as it's already done by __io_uring_task_cancel(), and do
a bit of renaming.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 25 ++++++-------------------
1 file changed, 6 insertions(+), 19 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 4bf709d9db32..134ea0e3373d 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -8767,8 +8767,8 @@ static void __io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
* hard links. These persist even for failure of cancelations, hence keep
* looping until none are found.
*/
-static void io_uring_cancel_task_requests(struct io_ring_ctx *ctx,
- struct files_struct *files)
+static void io_uring_try_task_cancel(struct io_ring_ctx *ctx,
+ struct files_struct *files)
{
struct task_struct *task = current;
@@ -8862,19 +8862,6 @@ static void io_uring_attempt_task_drop(struct file *file)
io_uring_del_task_file(current->io_uring, file);
}
-static void io_uring_try_task_cancel(struct files_struct *files)
-{
- struct io_uring_task *tctx = current->io_uring;
- struct file *file;
- unsigned long index;
-
- /* make sure overflow events are dropped */
- atomic_inc(&tctx->in_idle);
- xa_for_each(&tctx->xa, index, file)
- io_uring_cancel_task_requests(file->private_data, files);
- atomic_dec(&tctx->in_idle);
-}
-
static s64 tctx_inflight(struct io_uring_task *tctx, bool files)
{
unsigned long index;
@@ -8917,6 +8904,8 @@ static s64 tctx_inflight(struct io_uring_task *tctx, bool files)
void __io_uring_task_cancel(struct files_struct *files)
{
struct io_uring_task *tctx = current->io_uring;
+ unsigned long index;
+ struct file *file;
DEFINE_WAIT(wait);
s64 inflight;
@@ -8928,7 +8917,8 @@ void __io_uring_task_cancel(struct files_struct *files)
inflight = tctx_inflight(tctx, !!files);
if (!inflight)
break;
- io_uring_try_task_cancel(files);
+ xa_for_each(&tctx->xa, index, file)
+ io_uring_try_task_cancel(file->private_data, files);
prepare_to_wait(&tctx->wait, &wait, TASK_UNINTERRUPTIBLE);
@@ -8945,9 +8935,6 @@ void __io_uring_task_cancel(struct files_struct *files)
atomic_dec(&tctx->in_idle);
if (files) {
- struct file *file;
- unsigned long index;
-
xa_for_each(&tctx->xa, index, file)
io_uring_del_task_file(tctx, file);
}
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 8/8] io_uring: kill not used anymore inflight_lock
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
` (6 preceding siblings ...)
2020-12-18 13:12 ` [PATCH 7/8] io_uring: cleanup task cancel Pavel Begunkov
@ 2020-12-18 13:12 ` Pavel Begunkov
2020-12-18 15:16 ` [PATCH 0/8] a fix + cancellation unification Jens Axboe
8 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 13:12 UTC (permalink / raw)
To: Jens Axboe, io-uring
ctx->inflight_lock now doesn't protect anything that should be protected
-- tctx->inflight_files is atomic, and inflight list is gone. Time to
eradicate it.
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 134ea0e3373d..a678920b1c8d 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -377,8 +377,6 @@ struct io_ring_ctx {
struct hlist_head *cancel_hash;
unsigned cancel_hash_bits;
bool poll_multi_file;
-
- spinlock_t inflight_lock;
} ____cacheline_aligned_in_smp;
struct delayed_work file_put_work;
@@ -1303,7 +1301,6 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
INIT_LIST_HEAD(&ctx->iopoll_list);
INIT_LIST_HEAD(&ctx->defer_list);
INIT_LIST_HEAD(&ctx->timeout_list);
- spin_lock_init(&ctx->inflight_lock);
INIT_DELAYED_WORK(&ctx->file_put_work, io_file_put_work);
init_llist_head(&ctx->file_put_llist);
return ctx;
@@ -1433,7 +1430,6 @@ static bool io_grab_identity(struct io_kiocb *req)
{
const struct io_op_def *def = &io_op_defs[req->opcode];
struct io_identity *id = req->work.identity;
- struct io_ring_ctx *ctx = req->ctx;
if (def->work_flags & IO_WQ_WORK_FSIZE) {
if (id->fsize != rlimit(RLIMIT_FSIZE))
@@ -1491,9 +1487,7 @@ static bool io_grab_identity(struct io_kiocb *req)
get_nsproxy(id->nsproxy);
req->flags |= REQ_F_INFLIGHT;
- spin_lock_irq(&ctx->inflight_lock);
atomic_inc(¤t->io_uring->inflight_files);
- spin_unlock_irq(&ctx->inflight_lock);
req->work.flags |= IO_WQ_WORK_FILES;
}
@@ -6088,15 +6082,11 @@ static int io_req_defer(struct io_kiocb *req, const struct io_uring_sqe *sqe)
static void io_req_drop_files(struct io_kiocb *req)
{
- struct io_ring_ctx *ctx = req->ctx;
struct io_uring_task *tctx = req->task->io_uring;
- unsigned long flags;
put_files_struct(req->work.identity->files);
put_nsproxy(req->work.identity->nsproxy);
- spin_lock_irqsave(&ctx->inflight_lock, flags);
atomic_dec(&tctx->inflight_files);
- spin_unlock_irqrestore(&ctx->inflight_lock, flags);
req->flags &= ~REQ_F_INFLIGHT;
req->work.flags &= ~IO_WQ_WORK_FILES;
if (atomic_read(&tctx->in_idle))
--
2.24.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 0/8] a fix + cancellation unification
2020-12-18 13:12 [PATCH 0/8] a fix + cancellation unification Pavel Begunkov
` (7 preceding siblings ...)
2020-12-18 13:12 ` [PATCH 8/8] io_uring: kill not used anymore inflight_lock Pavel Begunkov
@ 2020-12-18 15:16 ` Jens Axboe
2020-12-18 15:22 ` Pavel Begunkov
8 siblings, 1 reply; 11+ messages in thread
From: Jens Axboe @ 2020-12-18 15:16 UTC (permalink / raw)
To: Pavel Begunkov, io-uring
On 12/18/20 6:12 AM, Pavel Begunkov wrote:
> I suggest for 1/8 to go for current, and the rest are for next.
> Patches 2-8 finally unify how we do task and files cancellation removing
> boilerplate and making it easier to understand overall. As a bonus to it
> ->inflight_entry is now used only for iopoll, probably can be put into a
> union with something and save 16B of io_kiocb if that would be needed.
I've added 1/8 to the 5.11 mix for now, I'll get back to the other ones.
--
Jens Axboe
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/8] a fix + cancellation unification
2020-12-18 15:16 ` [PATCH 0/8] a fix + cancellation unification Jens Axboe
@ 2020-12-18 15:22 ` Pavel Begunkov
0 siblings, 0 replies; 11+ messages in thread
From: Pavel Begunkov @ 2020-12-18 15:22 UTC (permalink / raw)
To: Jens Axboe, io-uring
On 18/12/2020 15:16, Jens Axboe wrote:
> On 12/18/20 6:12 AM, Pavel Begunkov wrote:
>> I suggest for 1/8 to go for current, and the rest are for next.
>> Patches 2-8 finally unify how we do task and files cancellation removing
>> boilerplate and making it easier to understand overall. As a bonus to it
>> ->inflight_entry is now used only for iopoll, probably can be put into a
>> union with something and save 16B of io_kiocb if that would be needed.
>
> I've added 1/8 to the 5.11 mix for now, I'll get back to the other ones.
Sure, I'll keep track of the rest. Thanks
--
Pavel Begunkov
^ permalink raw reply [flat|nested] 11+ messages in thread