struct io_tctx_node *node;
int ret;
+ mutex_lock(&ctx->uring_lock);
+ io_terminate_zcrx(ctx);
+ mutex_unlock(&ctx->uring_lock);
+
/*
* If we're doing polled IO and end up having requests being
* submitted async (out-of-line), then completions can come in while
}
}
-static void zcrx_unregister(struct io_zcrx_ifq *ifq)
+static void zcrx_unregister_user(struct io_zcrx_ifq *ifq)
{
if (refcount_dec_and_test(&ifq->user_refs)) {
io_close_queue(ifq);
io_zcrx_scrub(ifq);
}
+}
+
+static void zcrx_unregister(struct io_zcrx_ifq *ifq)
+{
+ zcrx_unregister_user(ifq);
io_put_zcrx_ifq(ifq);
}
return &area->nia.niovs[niov_idx];
}
+static inline bool is_zcrx_entry_marked(struct io_ring_ctx *ctx, unsigned long id)
+{
+ return xa_get_mark(&ctx->zcrx_ctxs, id, XA_MARK_0);
+}
+
+static inline void set_zcrx_entry_mark(struct io_ring_ctx *ctx, unsigned long id)
+{
+ xa_set_mark(&ctx->zcrx_ctxs, id, XA_MARK_0);
+}
+
+void io_terminate_zcrx(struct io_ring_ctx *ctx)
+{
+ struct io_zcrx_ifq *ifq;
+ unsigned long id = 0;
+
+ lockdep_assert_held(&ctx->uring_lock);
+
+ while (1) {
+ scoped_guard(mutex, &ctx->mmap_lock)
+ ifq = xa_find(&ctx->zcrx_ctxs, &id, ULONG_MAX, XA_PRESENT);
+ if (!ifq)
+ break;
+ if (WARN_ON_ONCE(is_zcrx_entry_marked(ctx, id)))
+ break;
+ set_zcrx_entry_mark(ctx, id);
+ id++;
+ zcrx_unregister_user(ifq);
+ }
+}
+
void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx)
{
struct io_zcrx_ifq *ifq;
unsigned long id = 0;
ifq = xa_find(&ctx->zcrx_ctxs, &id, ULONG_MAX, XA_PRESENT);
- if (ifq)
+ if (ifq) {
+ if (WARN_ON_ONCE(!is_zcrx_entry_marked(ctx, id))) {
+ ifq = NULL;
+ break;
+ }
xa_erase(&ctx->zcrx_ctxs, id);
+ }
}
if (!ifq)
break;
- zcrx_unregister(ifq);
+ io_put_zcrx_ifq(ifq);
}
xa_destroy(&ctx->zcrx_ctxs);
int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
struct io_uring_zcrx_ifq_reg __user *arg);
void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx);
+void io_terminate_zcrx(struct io_ring_ctx *ctx);
int io_zcrx_recv(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
struct socket *sock, unsigned int flags,
unsigned issue_flags, unsigned int *len);
static inline void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx)
{
}
+static inline void io_terminate_zcrx(struct io_ring_ctx *ctx)
+{
+}
static inline int io_zcrx_recv(struct io_kiocb *req, struct io_zcrx_ifq *ifq,
struct socket *sock, unsigned int flags,
unsigned issue_flags, unsigned int *len)