diff options
author | Jens Axboe <axboe@kernel.dk> | 2021-10-29 15:36:45 +0300 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2021-10-29 18:49:33 +0300 |
commit | f75d118349be055d47407b4ba4ceb98e6437e472 (patch) | |
tree | a215817815a3f606191b6a73327df1f516bf9b0c | |
parent | 3884b83dff245e41def99ceacca8ed2056baf0a8 (diff) | |
download | linux-f75d118349be055d47407b4ba4ceb98e6437e472.tar.xz |
io_uring: harder fdinfo sq/cq ring iterating
The ring iteration is racy, which isn't necessarily a problem except it
can cause us to iterate the whole thing. That isn't desired or ideal,
and it can lead to excessive runtimes of reading fdinfo.
Cap the iteration at tail - head OR the ring size. While in there, clean
up the ring masking and just dump the raw values along with the masks.
That provides more useful debug info.
Fixes: 83f84356bc8f ("io_uring: add more uring info to fdinfo for debug")
Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | fs/io_uring.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index d001cd7a6c51..c887e4e19e9e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -10056,12 +10056,11 @@ static __cold void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct io_overflow_cqe *ocqe; struct io_rings *r = ctx->rings; unsigned int sq_mask = ctx->sq_entries - 1, cq_mask = ctx->cq_entries - 1; - unsigned int cached_sq_head = ctx->cached_sq_head; - unsigned int cached_cq_tail = ctx->cached_cq_tail; unsigned int sq_head = READ_ONCE(r->sq.head); unsigned int sq_tail = READ_ONCE(r->sq.tail); unsigned int cq_head = READ_ONCE(r->cq.head); unsigned int cq_tail = READ_ONCE(r->cq.tail); + unsigned int sq_entries, cq_entries; bool has_lock; unsigned int i; @@ -10071,29 +10070,37 @@ static __cold void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, * and sq_tail and cq_head are changed by userspace. But it's ok since * we usually use these info when it is stuck. */ - seq_printf(m, "SqHead:\t%u\n", sq_head & sq_mask); - seq_printf(m, "SqTail:\t%u\n", sq_tail & sq_mask); - seq_printf(m, "CachedSqHead:\t%u\n", cached_sq_head & sq_mask); - seq_printf(m, "CqHead:\t%u\n", cq_head & cq_mask); - seq_printf(m, "CqTail:\t%u\n", cq_tail & cq_mask); - seq_printf(m, "CachedCqTail:\t%u\n", cached_cq_tail & cq_mask); - seq_printf(m, "SQEs:\t%u\n", sq_tail - cached_sq_head); - for (i = cached_sq_head; i < sq_tail; i++) { - unsigned int sq_idx = READ_ONCE(ctx->sq_array[i & sq_mask]); - - if (likely(sq_idx <= sq_mask)) { - struct io_uring_sqe *sqe = &ctx->sq_sqes[sq_idx]; - - seq_printf(m, "%5u: opcode:%d, fd:%d, flags:%x, user_data:%llu\n", - sq_idx, sqe->opcode, sqe->fd, sqe->flags, sqe->user_data); - } + seq_printf(m, "SqMask:\t\t0x%x\n", sq_mask); + seq_printf(m, "SqHead:\t%u\n", sq_head); + seq_printf(m, "SqTail:\t%u\n", sq_tail); + seq_printf(m, "CachedSqHead:\t%u\n", ctx->cached_sq_head); + seq_printf(m, "CqMask:\t0x%x\n", cq_mask); + seq_printf(m, "CqHead:\t%u\n", cq_head); + seq_printf(m, "CqTail:\t%u\n", cq_tail); + seq_printf(m, "CachedCqTail:\t%u\n", ctx->cached_cq_tail); + seq_printf(m, "SQEs:\t%u\n", sq_tail - ctx->cached_sq_head); + sq_entries = min(sq_tail - sq_head, ctx->sq_entries); + for (i = 0; i < sq_entries; i++) { + unsigned int entry = i + sq_head; + unsigned int sq_idx = READ_ONCE(ctx->sq_array[entry & sq_mask]); + struct io_uring_sqe *sqe = &ctx->sq_sqes[sq_idx]; + + if (sq_idx > sq_mask) + continue; + sqe = &ctx->sq_sqes[sq_idx]; + seq_printf(m, "%5u: opcode:%d, fd:%d, flags:%x, user_data:%llu\n", + sq_idx, sqe->opcode, sqe->fd, sqe->flags, + sqe->user_data); } - seq_printf(m, "CQEs:\t%u\n", cached_cq_tail - cq_head); - for (i = cq_head; i < cached_cq_tail; i++) { - struct io_uring_cqe *cqe = &r->cqes[i & cq_mask]; + seq_printf(m, "CQEs:\t%u\n", cq_tail - cq_head); + cq_entries = min(cq_tail - cq_head, ctx->cq_entries); + for (i = 0; i < cq_entries; i++) { + unsigned int entry = i + cq_head; + struct io_uring_cqe *cqe = &r->cqes[entry & cq_mask]; seq_printf(m, "%5u: user_data:%llu, res:%d, flag:%x\n", - i & cq_mask, cqe->user_data, cqe->res, cqe->flags); + entry & cq_mask, cqe->user_data, cqe->res, + cqe->flags); } /* |