io_uring: disable drain with cqe skip
Current IOSQE_IO_DRAIN implementation doesn't work well with CQE skipping and it's not allowed, otherwise some requests might be not executed until the ring is destroyed and the userspace would hang. Let's fail all drain requests after seeing IOSQE_CQE_SKIP_SUCCESS at least once. All drained requests prior to that will get run normally, so there should be no stalls. However, even though such mixing wouldn't lead to issues at the moment, it's still not allowed as the behaviour may change. Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/bcf7164f8bf3eb54b7bb7b4fd119907fa4d4d43b.1636559119.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Родитель
3d4aeb9f98
Коммит
5562a8d71a
|
@ -106,10 +106,10 @@
|
|||
#define IORING_MAX_REG_BUFFERS (1U << 14)
|
||||
|
||||
#define SQE_COMMON_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_LINK | \
|
||||
IOSQE_IO_HARDLINK | IOSQE_ASYNC | \
|
||||
IOSQE_CQE_SKIP_SUCCESS)
|
||||
IOSQE_IO_HARDLINK | IOSQE_ASYNC)
|
||||
|
||||
#define SQE_VALID_FLAGS (SQE_COMMON_FLAGS|IOSQE_BUFFER_SELECT|IOSQE_IO_DRAIN)
|
||||
#define SQE_VALID_FLAGS (SQE_COMMON_FLAGS | IOSQE_BUFFER_SELECT | \
|
||||
IOSQE_IO_DRAIN | IOSQE_CQE_SKIP_SUCCESS)
|
||||
|
||||
#define IO_REQ_CLEAN_FLAGS (REQ_F_BUFFER_SELECTED | REQ_F_NEED_CLEANUP | \
|
||||
REQ_F_POLLED | REQ_F_INFLIGHT | REQ_F_CREDS | \
|
||||
|
@ -339,6 +339,7 @@ struct io_ring_ctx {
|
|||
unsigned int restricted: 1;
|
||||
unsigned int off_timeout_used: 1;
|
||||
unsigned int drain_active: 1;
|
||||
unsigned int drain_disabled: 1;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
/* submission data */
|
||||
|
@ -7127,8 +7128,13 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
|
|||
if ((sqe_flags & IOSQE_BUFFER_SELECT) &&
|
||||
!io_op_defs[opcode].buffer_select)
|
||||
return -EOPNOTSUPP;
|
||||
if (sqe_flags & IOSQE_IO_DRAIN)
|
||||
if (sqe_flags & IOSQE_CQE_SKIP_SUCCESS)
|
||||
ctx->drain_disabled = true;
|
||||
if (sqe_flags & IOSQE_IO_DRAIN) {
|
||||
if (ctx->drain_disabled)
|
||||
return -EOPNOTSUPP;
|
||||
io_init_req_drain(req);
|
||||
}
|
||||
}
|
||||
if (unlikely(ctx->restricted || ctx->drain_active || ctx->drain_next)) {
|
||||
if (ctx->restricted && !io_check_restriction(ctx, req, sqe_flags))
|
||||
|
|
Загрузка…
Ссылка в новой задаче