public inbox for [email protected]
 help / color / mirror / Atom feed
* [PATCH for-6.4 00/10] some rsrc fixes and clean ups
@ 2023-04-13 14:28 Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 01/10] io_uring/rsrc: use nospec'ed indexes Pavel Begunkov
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Patch 1 is a simple fix for using indexes w/o array_index_nospec()
protection.

Patches 2-5 are fixing a file / buffer table unregistration issue
when the ring is configured with DEFER_TASKRUN.

The rest are clean ups on top.


Pavel Begunkov (10):
  io_uring/rsrc: use nospec'ed indexes
  io_uring/rsrc: remove io_rsrc_node::done
  io_uring/rsrc: refactor io_rsrc_ref_quiesce
  io_uring/rsrc: use wq for quiescing
  io_uring/rsrc: fix DEFER_TASKRUN rsrc quiesce
  io_uring/rsrc: remove rsrc_data refs
  io_uring/rsrc: inline switch_start fast path
  io_uring/rsrc: clean up __io_sqe_buffers_update()
  io_uring/rsrc: simplify single file node switching
  io_uring/rsrc: refactor io_queue_rsrc_removal

 include/linux/io_uring_types.h |  2 +
 io_uring/filetable.c           | 11 ++---
 io_uring/io_uring.c            |  5 +-
 io_uring/rsrc.c                | 90 ++++++++++++++--------------------
 io_uring/rsrc.h                | 13 +++--
 5 files changed, 53 insertions(+), 68 deletions(-)

-- 
2.40.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 01/10] io_uring/rsrc: use nospec'ed indexes
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 02/10] io_uring/rsrc: remove io_rsrc_node::done Pavel Begunkov
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

We use array_index_nospec() for registered buffer indexes, but don't use
it while poking into rsrc tags, fix that.

Fixes: 634d00df5e1cf ("io_uring: add full-fledged dynamic buffers support")
Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 11058e20bdcc..3c1538b8c8f4 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -517,7 +517,7 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
 		}
 
 		ctx->user_bufs[i] = imu;
-		*io_get_tag_slot(ctx->buf_data, offset) = tag;
+		*io_get_tag_slot(ctx->buf_data, i) = tag;
 	}
 
 	if (needs_switch)
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 02/10] io_uring/rsrc: remove io_rsrc_node::done
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 01/10] io_uring/rsrc: use nospec'ed indexes Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 03/10] io_uring/rsrc: refactor io_rsrc_ref_quiesce Pavel Begunkov
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Kill io_rsrc_node::node and check refs instead, it's set when the nodes
refcount hits zero, and it won't change afterwards.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 5 +----
 io_uring/rsrc.h | 1 -
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 3c1538b8c8f4..5fc9d10743e0 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -191,14 +191,12 @@ void io_rsrc_node_ref_zero(struct io_rsrc_node *node)
 {
 	struct io_ring_ctx *ctx = node->rsrc_data->ctx;
 
-	node->done = true;
 	while (!list_empty(&ctx->rsrc_ref_list)) {
 		node = list_first_entry(&ctx->rsrc_ref_list,
 					    struct io_rsrc_node, node);
 		/* recycle ref nodes in order */
-		if (!node->done)
+		if (node->refs)
 			break;
-
 		list_del(&node->node);
 		__io_rsrc_put_work(node);
 	}
@@ -222,7 +220,6 @@ struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx)
 	ref_node->refs = 1;
 	INIT_LIST_HEAD(&ref_node->node);
 	INIT_LIST_HEAD(&ref_node->item_list);
-	ref_node->done = false;
 	ref_node->inline_items = 0;
 	return ref_node;
 }
diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h
index 17dfe180208f..88adcb0b7963 100644
--- a/io_uring/rsrc.h
+++ b/io_uring/rsrc.h
@@ -48,7 +48,6 @@ struct io_rsrc_node {
 	struct list_head		node;
 	struct llist_node		llist;
 	int				refs;
-	bool				done;
 
 	/*
 	 * Keeps a list of struct io_rsrc_put to be completed. Each entry
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 03/10] io_uring/rsrc: refactor io_rsrc_ref_quiesce
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 01/10] io_uring/rsrc: use nospec'ed indexes Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 02/10] io_uring/rsrc: remove io_rsrc_node::done Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 04/10] io_uring/rsrc: use wq for quiescing Pavel Begunkov
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Refactor io_rsrc_ref_quiesce() by moving the first mutex_unlock(),
so we don't have to have a second mutex_unlock() further in the loop.
It prepares us to the next patch.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 5fc9d10743e0..d7e7528f7159 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -272,8 +272,8 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 		return 0;
 
 	data->quiesce = true;
-	mutex_unlock(&ctx->uring_lock);
 	do {
+		mutex_unlock(&ctx->uring_lock);
 		ret = io_run_task_work_sig(ctx);
 		if (ret < 0) {
 			mutex_lock(&ctx->uring_lock);
@@ -285,18 +285,10 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 			}
 			break;
 		}
-		ret = wait_for_completion_interruptible(&data->done);
-		if (!ret) {
-			mutex_lock(&ctx->uring_lock);
-			if (!data->refs)
-				break;
-			/*
-			 * it has been revived by another thread while
-			 * we were unlocked
-			 */
-			mutex_unlock(&ctx->uring_lock);
-		}
-	} while (1);
+		wait_for_completion_interruptible(&data->done);
+		mutex_lock(&ctx->uring_lock);
+		ret = 0;
+	} while (data->refs);
 	data->quiesce = false;
 
 	return ret;
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 04/10] io_uring/rsrc: use wq for quiescing
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (2 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 03/10] io_uring/rsrc: refactor io_rsrc_ref_quiesce Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 05/10] io_uring/rsrc: fix DEFER_TASKRUN rsrc quiesce Pavel Begunkov
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Replace completions with waitqueues for rsrc data quiesce, the main
wakeup condition is when data refs hit zero. Note that data refs are
only changes under ->uring_lock, so we prepare before mutex_unlock()
reacquire it after taking the lock back. This change will be needed
in the next patch.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 include/linux/io_uring_types.h |  1 +
 io_uring/io_uring.c            |  1 +
 io_uring/rsrc.c                | 18 ++++++++++++------
 io_uring/rsrc.h                |  1 -
 4 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
index 40cab420b1bd..5c9645319770 100644
--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -333,6 +333,7 @@ struct io_ring_ctx {
 	/* protected by ->uring_lock */
 	struct list_head		rsrc_ref_list;
 	struct io_alloc_cache		rsrc_node_cache;
+	struct wait_queue_head		rsrc_quiesce_wq;
 
 	struct list_head		io_buffers_pages;
 
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 9083a8466ebf..3c1c8c788b7b 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -321,6 +321,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
 	mutex_init(&ctx->uring_lock);
 	init_waitqueue_head(&ctx->cq_wait);
 	init_waitqueue_head(&ctx->poll_wq);
+	init_waitqueue_head(&ctx->rsrc_quiesce_wq);
 	spin_lock_init(&ctx->completion_lock);
 	spin_lock_init(&ctx->timeout_lock);
 	INIT_WQ_LIST(&ctx->iopoll_list);
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index d7e7528f7159..f9ce4076c73d 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -158,6 +158,7 @@ static void io_rsrc_put_work_one(struct io_rsrc_data *rsrc_data,
 static void __io_rsrc_put_work(struct io_rsrc_node *ref_node)
 {
 	struct io_rsrc_data *rsrc_data = ref_node->rsrc_data;
+	struct io_ring_ctx *ctx = rsrc_data->ctx;
 	struct io_rsrc_put *prsrc, *tmp;
 
 	if (ref_node->inline_items)
@@ -171,13 +172,13 @@ static void __io_rsrc_put_work(struct io_rsrc_node *ref_node)
 
 	io_rsrc_node_destroy(rsrc_data->ctx, ref_node);
 	if (io_put_rsrc_data_ref(rsrc_data))
-		complete(&rsrc_data->done);
+		wake_up_all(&ctx->rsrc_quiesce_wq);
 }
 
 void io_wait_rsrc_data(struct io_rsrc_data *data)
 {
-	if (data && !io_put_rsrc_data_ref(data))
-		wait_for_completion(&data->done);
+	if (data)
+		WARN_ON_ONCE(!io_put_rsrc_data_ref(data));
 }
 
 void io_rsrc_node_destroy(struct io_ring_ctx *ctx, struct io_rsrc_node *node)
@@ -257,6 +258,7 @@ int io_rsrc_node_switch_start(struct io_ring_ctx *ctx)
 __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 				      struct io_ring_ctx *ctx)
 {
+	DEFINE_WAIT(we);
 	int ret;
 
 	/* As we may drop ->uring_lock, other task may have started quiesce */
@@ -273,7 +275,9 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 
 	data->quiesce = true;
 	do {
+		prepare_to_wait(&ctx->rsrc_quiesce_wq, &we, TASK_INTERRUPTIBLE);
 		mutex_unlock(&ctx->uring_lock);
+
 		ret = io_run_task_work_sig(ctx);
 		if (ret < 0) {
 			mutex_lock(&ctx->uring_lock);
@@ -285,12 +289,15 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 			}
 			break;
 		}
-		wait_for_completion_interruptible(&data->done);
+
+		schedule();
+		__set_current_state(TASK_RUNNING);
 		mutex_lock(&ctx->uring_lock);
 		ret = 0;
 	} while (data->refs);
-	data->quiesce = false;
 
+	finish_wait(&ctx->rsrc_quiesce_wq, &we);
+	data->quiesce = false;
 	return ret;
 }
 
@@ -366,7 +373,6 @@ __cold static int io_rsrc_data_alloc(struct io_ring_ctx *ctx,
 				goto fail;
 		}
 	}
-	init_completion(&data->done);
 	*pdata = data;
 	return 0;
 fail:
diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h
index 88adcb0b7963..d93ba4e9742a 100644
--- a/io_uring/rsrc.h
+++ b/io_uring/rsrc.h
@@ -35,7 +35,6 @@ struct io_rsrc_data {
 	u64				**tags;
 	unsigned int			nr;
 	rsrc_put_fn			*do_put;
-	struct completion		done;
 	int				refs;
 	bool				quiesce;
 };
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 05/10] io_uring/rsrc: fix DEFER_TASKRUN rsrc quiesce
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (3 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 04/10] io_uring/rsrc: use wq for quiescing Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 06/10] io_uring/rsrc: remove rsrc_data refs Pavel Begunkov
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

For io_rsrc_ref_quiesce() to progress it should execute all task_work
items, including deferred ones. However, currently nobody would wake us,
and so let's set ctx->cq_wait_nr, so io_req_local_work_add() would wake
us up.

Fixes: c0e0d6ba25f18 ("io_uring: add IORING_SETUP_DEFER_TASKRUN")
Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index f9ce4076c73d..e634ef384724 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -273,6 +273,11 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 	if (io_put_rsrc_data_ref(data))
 		return 0;
 
+	if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) {
+		atomic_set(&ctx->cq_wait_nr, 1);
+		smp_mb();
+	}
+
 	data->quiesce = true;
 	do {
 		prepare_to_wait(&ctx->rsrc_quiesce_wq, &we, TASK_INTERRUPTIBLE);
@@ -298,6 +303,10 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 
 	finish_wait(&ctx->rsrc_quiesce_wq, &we);
 	data->quiesce = false;
+	if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) {
+		atomic_set(&ctx->cq_wait_nr, 0);
+		smp_mb();
+	}
 	return ret;
 }
 
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 06/10] io_uring/rsrc: remove rsrc_data refs
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (4 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 05/10] io_uring/rsrc: fix DEFER_TASKRUN rsrc quiesce Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 07/10] io_uring/rsrc: inline switch_start fast path Pavel Begunkov
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Instead of waiting for rsrc_data->refs to be downed to zero, check
whether there are rsrc nodes queued for completion, that's easier then
maintaining references.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 include/linux/io_uring_types.h |  1 +
 io_uring/io_uring.c            |  4 ++--
 io_uring/rsrc.c                | 32 ++++++++------------------------
 io_uring/rsrc.h                |  2 --
 4 files changed, 11 insertions(+), 28 deletions(-)

diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
index 5c9645319770..1b2a20a42413 100644
--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -334,6 +334,7 @@ struct io_ring_ctx {
 	struct list_head		rsrc_ref_list;
 	struct io_alloc_cache		rsrc_node_cache;
 	struct wait_queue_head		rsrc_quiesce_wq;
+	unsigned			rsrc_quiesce;
 
 	struct list_head		io_buffers_pages;
 
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 3c1c8c788b7b..3d43df8f1e4e 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2831,8 +2831,8 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
 {
 	io_sq_thread_finish(ctx);
 	/* __io_rsrc_put_work() may need uring_lock to progress, wait w/o it */
-	io_wait_rsrc_data(ctx->buf_data);
-	io_wait_rsrc_data(ctx->file_data);
+	if (WARN_ON_ONCE(!list_empty(&ctx->rsrc_ref_list)))
+		return;
 
 	mutex_lock(&ctx->uring_lock);
 	if (ctx->buf_data)
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index e634ef384724..5415a18844e0 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -31,11 +31,6 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
 #define IORING_MAX_FIXED_FILES	(1U << 20)
 #define IORING_MAX_REG_BUFFERS	(1U << 14)
 
-static inline bool io_put_rsrc_data_ref(struct io_rsrc_data *rsrc_data)
-{
-	return !--rsrc_data->refs;
-}
-
 int __io_account_mem(struct user_struct *user, unsigned long nr_pages)
 {
 	unsigned long page_limit, cur_pages, new_pages;
@@ -158,7 +153,6 @@ static void io_rsrc_put_work_one(struct io_rsrc_data *rsrc_data,
 static void __io_rsrc_put_work(struct io_rsrc_node *ref_node)
 {
 	struct io_rsrc_data *rsrc_data = ref_node->rsrc_data;
-	struct io_ring_ctx *ctx = rsrc_data->ctx;
 	struct io_rsrc_put *prsrc, *tmp;
 
 	if (ref_node->inline_items)
@@ -171,14 +165,6 @@ static void __io_rsrc_put_work(struct io_rsrc_node *ref_node)
 	}
 
 	io_rsrc_node_destroy(rsrc_data->ctx, ref_node);
-	if (io_put_rsrc_data_ref(rsrc_data))
-		wake_up_all(&ctx->rsrc_quiesce_wq);
-}
-
-void io_wait_rsrc_data(struct io_rsrc_data *data)
-{
-	if (data)
-		WARN_ON_ONCE(!io_put_rsrc_data_ref(data));
 }
 
 void io_rsrc_node_destroy(struct io_ring_ctx *ctx, struct io_rsrc_node *node)
@@ -201,6 +187,8 @@ void io_rsrc_node_ref_zero(struct io_rsrc_node *node)
 		list_del(&node->node);
 		__io_rsrc_put_work(node);
 	}
+	if (list_empty(&ctx->rsrc_ref_list) && unlikely(ctx->rsrc_quiesce))
+		wake_up_all(&ctx->rsrc_quiesce_wq);
 }
 
 struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx)
@@ -235,7 +223,6 @@ void io_rsrc_node_switch(struct io_ring_ctx *ctx,
 	if (WARN_ON_ONCE(!backup))
 		return;
 
-	data_to_kill->refs++;
 	node->rsrc_data = data_to_kill;
 	list_add_tail(&node->node, &ctx->rsrc_ref_list);
 	/* put master ref */
@@ -269,8 +256,7 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 		return ret;
 	io_rsrc_node_switch(ctx, data);
 
-	/* kill initial ref */
-	if (io_put_rsrc_data_ref(data))
+	if (list_empty(&ctx->rsrc_ref_list))
 		return 0;
 
 	if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) {
@@ -278,6 +264,7 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 		smp_mb();
 	}
 
+	ctx->rsrc_quiesce++;
 	data->quiesce = true;
 	do {
 		prepare_to_wait(&ctx->rsrc_quiesce_wq, &we, TASK_INTERRUPTIBLE);
@@ -286,12 +273,8 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 		ret = io_run_task_work_sig(ctx);
 		if (ret < 0) {
 			mutex_lock(&ctx->uring_lock);
-			if (!data->refs) {
+			if (list_empty(&ctx->rsrc_ref_list))
 				ret = 0;
-			} else {
-				/* restore the master reference */
-				data->refs++;
-			}
 			break;
 		}
 
@@ -299,10 +282,12 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
 		__set_current_state(TASK_RUNNING);
 		mutex_lock(&ctx->uring_lock);
 		ret = 0;
-	} while (data->refs);
+	} while (!list_empty(&ctx->rsrc_ref_list));
 
 	finish_wait(&ctx->rsrc_quiesce_wq, &we);
 	data->quiesce = false;
+	ctx->rsrc_quiesce--;
+
 	if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) {
 		atomic_set(&ctx->cq_wait_nr, 0);
 		smp_mb();
@@ -371,7 +356,6 @@ __cold static int io_rsrc_data_alloc(struct io_ring_ctx *ctx,
 	data->nr = nr;
 	data->ctx = ctx;
 	data->do_put = do_put;
-	data->refs = 1;
 	if (utags) {
 		ret = -EFAULT;
 		for (i = 0; i < nr; i++) {
diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h
index d93ba4e9742a..5dd2fcb28069 100644
--- a/io_uring/rsrc.h
+++ b/io_uring/rsrc.h
@@ -35,7 +35,6 @@ struct io_rsrc_data {
 	u64				**tags;
 	unsigned int			nr;
 	rsrc_put_fn			*do_put;
-	int				refs;
 	bool				quiesce;
 };
 
@@ -69,7 +68,6 @@ struct io_mapped_ubuf {
 void io_rsrc_put_tw(struct callback_head *cb);
 void io_rsrc_node_ref_zero(struct io_rsrc_node *node);
 void io_rsrc_put_work(struct work_struct *work);
-void io_wait_rsrc_data(struct io_rsrc_data *data);
 void io_rsrc_node_destroy(struct io_ring_ctx *ctx, struct io_rsrc_node *ref_node);
 int io_rsrc_node_switch_start(struct io_ring_ctx *ctx);
 struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx);
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 07/10] io_uring/rsrc: inline switch_start fast path
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (5 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 06/10] io_uring/rsrc: remove rsrc_data refs Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 08/10] io_uring/rsrc: clean up __io_sqe_buffers_update() Pavel Begunkov
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Inline the part of io_rsrc_node_switch_start() that checks whether the
cache is empty or not, as most of the times it will have some number of
entries in there.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 12 +++++-------
 io_uring/rsrc.h |  9 ++++++++-
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 5415a18844e0..bfa0b382c6c6 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -230,15 +230,13 @@ void io_rsrc_node_switch(struct io_ring_ctx *ctx,
 	ctx->rsrc_node = backup;
 }
 
-int io_rsrc_node_switch_start(struct io_ring_ctx *ctx)
+int __io_rsrc_node_switch_start(struct io_ring_ctx *ctx)
 {
-	if (io_alloc_cache_empty(&ctx->rsrc_node_cache)) {
-		struct io_rsrc_node *node = kzalloc(sizeof(*node), GFP_KERNEL);
+	struct io_rsrc_node *node = kzalloc(sizeof(*node), GFP_KERNEL);
 
-		if (!node)
-			return -ENOMEM;
-		io_alloc_cache_put(&ctx->rsrc_node_cache, &node->cache);
-	}
+	if (!node)
+		return -ENOMEM;
+	io_alloc_cache_put(&ctx->rsrc_node_cache, &node->cache);
 	return 0;
 }
 
diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h
index 5dd2fcb28069..732496afed4c 100644
--- a/io_uring/rsrc.h
+++ b/io_uring/rsrc.h
@@ -69,7 +69,7 @@ void io_rsrc_put_tw(struct callback_head *cb);
 void io_rsrc_node_ref_zero(struct io_rsrc_node *node);
 void io_rsrc_put_work(struct work_struct *work);
 void io_rsrc_node_destroy(struct io_ring_ctx *ctx, struct io_rsrc_node *ref_node);
-int io_rsrc_node_switch_start(struct io_ring_ctx *ctx);
+int __io_rsrc_node_switch_start(struct io_ring_ctx *ctx);
 struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx);
 int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
 			  struct io_rsrc_node *node, void *rsrc);
@@ -111,6 +111,13 @@ static inline int io_scm_file_account(struct io_ring_ctx *ctx,
 	return __io_scm_file_account(ctx, file);
 }
 
+static inline int io_rsrc_node_switch_start(struct io_ring_ctx *ctx)
+{
+	if (unlikely(io_alloc_cache_empty(&ctx->rsrc_node_cache)))
+		return __io_rsrc_node_switch_start(ctx);
+	return 0;
+}
+
 int io_register_files_update(struct io_ring_ctx *ctx, void __user *arg,
 			     unsigned nr_args);
 int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 08/10] io_uring/rsrc: clean up __io_sqe_buffers_update()
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (6 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 07/10] io_uring/rsrc: inline switch_start fast path Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 09/10] io_uring/rsrc: simplify single file node switching Pavel Begunkov
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

Inline offset variable, so we don't use it without subjecting it to
array_index_nospec() first.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index bfa0b382c6c6..38f0c9ce67a7 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -469,7 +469,6 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
 
 	for (done = 0; done < nr_args; done++) {
 		struct io_mapped_ubuf *imu;
-		int offset = up->offset + done;
 		u64 tag = 0;
 
 		err = io_copy_iov(ctx, &iov, iovs, done);
@@ -490,7 +489,7 @@ static int __io_sqe_buffers_update(struct io_ring_ctx *ctx,
 		if (err)
 			break;
 
-		i = array_index_nospec(offset, ctx->nr_user_bufs);
+		i = array_index_nospec(up->offset + done, ctx->nr_user_bufs);
 		if (ctx->user_bufs[i] != ctx->dummy_ubuf) {
 			err = io_queue_rsrc_removal(ctx->buf_data, i,
 						    ctx->rsrc_node, ctx->user_bufs[i]);
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 09/10] io_uring/rsrc: simplify single file node switching
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (7 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 08/10] io_uring/rsrc: clean up __io_sqe_buffers_update() Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-13 14:28 ` [PATCH 10/10] io_uring/rsrc: refactor io_queue_rsrc_removal Pavel Begunkov
  2023-04-15 20:46 ` [PATCH for-6.4 00/10] some rsrc fixes and clean ups Jens Axboe
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

At maximum io_install_fixed_file() removes only one file,
so no need to keep needs_switch state and we can call
io_rsrc_node_switch() right after removal.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/filetable.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/io_uring/filetable.c b/io_uring/filetable.c
index b80614e7d605..6255fa255ae2 100644
--- a/io_uring/filetable.c
+++ b/io_uring/filetable.c
@@ -64,7 +64,6 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
 				 u32 slot_index)
 	__must_hold(&req->ctx->uring_lock)
 {
-	bool needs_switch = false;
 	struct io_fixed_file *file_slot;
 	int ret;
 
@@ -83,16 +82,17 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
 
 		ret = io_rsrc_node_switch_start(ctx);
 		if (ret)
-			goto err;
+			return ret;
 
 		old_file = (struct file *)(file_slot->file_ptr & FFS_MASK);
 		ret = io_queue_rsrc_removal(ctx->file_data, slot_index,
 					    ctx->rsrc_node, old_file);
 		if (ret)
-			goto err;
+			return ret;
+
 		file_slot->file_ptr = 0;
 		io_file_bitmap_clear(&ctx->file_table, slot_index);
-		needs_switch = true;
+		io_rsrc_node_switch(ctx, ctx->file_data);
 	}
 
 	ret = io_scm_file_account(ctx, file);
@@ -101,9 +101,6 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
 		io_fixed_file_set(file_slot, file);
 		io_file_bitmap_set(&ctx->file_table, slot_index);
 	}
-err:
-	if (needs_switch)
-		io_rsrc_node_switch(ctx, ctx->file_data);
 	return ret;
 }
 
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 10/10] io_uring/rsrc: refactor io_queue_rsrc_removal
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (8 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 09/10] io_uring/rsrc: simplify single file node switching Pavel Begunkov
@ 2023-04-13 14:28 ` Pavel Begunkov
  2023-04-15 20:46 ` [PATCH for-6.4 00/10] some rsrc fixes and clean ups Jens Axboe
  10 siblings, 0 replies; 12+ messages in thread
From: Pavel Begunkov @ 2023-04-13 14:28 UTC (permalink / raw)
  To: io-uring; +Cc: Jens Axboe, asml.silence

We can queue up a rsrc into a list in io_queue_rsrc_removal()
while allocating io_rsrc_put and so simplify the function.

Signed-off-by: Pavel Begunkov <[email protected]>
---
 io_uring/rsrc.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 38f0c9ce67a7..db58a51d19da 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -685,7 +685,6 @@ int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
 {
 	u64 *tag_slot = io_get_tag_slot(data, idx);
 	struct io_rsrc_put *prsrc;
-	bool inline_item = true;
 
 	if (!node->inline_items) {
 		prsrc = &node->item;
@@ -694,14 +693,12 @@ int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
 		prsrc = kzalloc(sizeof(*prsrc), GFP_KERNEL);
 		if (!prsrc)
 			return -ENOMEM;
-		inline_item = false;
+		list_add(&prsrc->list, &node->item_list);
 	}
 
 	prsrc->tag = *tag_slot;
 	*tag_slot = 0;
 	prsrc->rsrc = rsrc;
-	if (!inline_item)
-		list_add(&prsrc->list, &node->item_list);
 	return 0;
 }
 
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH for-6.4 00/10] some rsrc fixes and clean ups
  2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
                   ` (9 preceding siblings ...)
  2023-04-13 14:28 ` [PATCH 10/10] io_uring/rsrc: refactor io_queue_rsrc_removal Pavel Begunkov
@ 2023-04-15 20:46 ` Jens Axboe
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Axboe @ 2023-04-15 20:46 UTC (permalink / raw)
  To: io-uring, Pavel Begunkov


On Thu, 13 Apr 2023 15:28:04 +0100, Pavel Begunkov wrote:
> Patch 1 is a simple fix for using indexes w/o array_index_nospec()
> protection.
> 
> Patches 2-5 are fixing a file / buffer table unregistration issue
> when the ring is configured with DEFER_TASKRUN.
> 
> The rest are clean ups on top.
> 
> [...]

Applied, thanks!

[01/10] io_uring/rsrc: use nospec'ed indexes
        commit: 953c37e066f05a3dca2d74643574b8dfe8a83983
[02/10] io_uring/rsrc: remove io_rsrc_node::done
        commit: c732ea242d565c8281c4b017929fc62a246d81b9
[03/10] io_uring/rsrc: refactor io_rsrc_ref_quiesce
        commit: eef81fcaa61e1bc6b7735be65f41bbf1a8efd133
[04/10] io_uring/rsrc: use wq for quiescing
        commit: 4ea15b56f0810f0d8795d475db1bb74b3a7c1b2f
[05/10] io_uring/rsrc: fix DEFER_TASKRUN rsrc quiesce
        commit: 7d481e0356334eb2de254414769b4bed4b2a8827
[06/10] io_uring/rsrc: remove rsrc_data refs
        commit: 0b222eeb6514ba6c3457b667fa4f3645032e1fc9
[07/10] io_uring/rsrc: inline switch_start fast path
        commit: 2f2af35f8e5a1ed552ed02e47277d50092a2b9f6
[08/10] io_uring/rsrc: clean up __io_sqe_buffers_update()
        commit: 9a57fffedc0ee078418a7793ab29cd3864205340
[09/10] io_uring/rsrc: simplify single file node switching
        commit: c87fd583f3b5ef770af33893394ea37c7a10b5b8
[10/10] io_uring/rsrc: refactor io_queue_rsrc_removal
        commit: c899a5d7d0eca054546b63e95c94b1e609516f84

Best regards,
-- 
Jens Axboe




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-04-15 20:46 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-13 14:28 [PATCH for-6.4 00/10] some rsrc fixes and clean ups Pavel Begunkov
2023-04-13 14:28 ` [PATCH 01/10] io_uring/rsrc: use nospec'ed indexes Pavel Begunkov
2023-04-13 14:28 ` [PATCH 02/10] io_uring/rsrc: remove io_rsrc_node::done Pavel Begunkov
2023-04-13 14:28 ` [PATCH 03/10] io_uring/rsrc: refactor io_rsrc_ref_quiesce Pavel Begunkov
2023-04-13 14:28 ` [PATCH 04/10] io_uring/rsrc: use wq for quiescing Pavel Begunkov
2023-04-13 14:28 ` [PATCH 05/10] io_uring/rsrc: fix DEFER_TASKRUN rsrc quiesce Pavel Begunkov
2023-04-13 14:28 ` [PATCH 06/10] io_uring/rsrc: remove rsrc_data refs Pavel Begunkov
2023-04-13 14:28 ` [PATCH 07/10] io_uring/rsrc: inline switch_start fast path Pavel Begunkov
2023-04-13 14:28 ` [PATCH 08/10] io_uring/rsrc: clean up __io_sqe_buffers_update() Pavel Begunkov
2023-04-13 14:28 ` [PATCH 09/10] io_uring/rsrc: simplify single file node switching Pavel Begunkov
2023-04-13 14:28 ` [PATCH 10/10] io_uring/rsrc: refactor io_queue_rsrc_removal Pavel Begunkov
2023-04-15 20:46 ` [PATCH for-6.4 00/10] some rsrc fixes and clean ups Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox