mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
io_uring-6.2-2023-01-13
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmPBsL8QHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgplLXD/9kmbwSseR8sm8s6rB3mZcfgN4vvkRDa5Kg r5bj32sOl2o37szObGI53MneFcCpdOszA2R3AHqUoj7ZQsyPlt59OIpKtdBlp6xv ACX1weBnxMTtdMZ90Mp/GxGLZuvSifbfL4z5YgbRRKnGorz3prmfRkKuO51DcJes mhoPGTDUsAmxoU261LzuHI7DtD69We8yBzj58p21NF8DvBI3NtuWWhOI+EGs2CDr aqilG5LxOYBKuEY660KhWKMAXwVbVkyLak4eIh4iax0R0Um/SKXnRMIRI3L1QZoP eqGtF4zGJGM+47RUnl6GF59/IsyRZR04GJlZ5ma8aqqZNh4oj8E6A+hpgczJ0025 QM4hG+NwqXeNpMjN0PwDypo3WoYjyIhaMoEyCT7dmVzj62y3pm3DDaZDnzUlQF5w 8YvoSPwyCzWHWFDGEZp6WRYn2YfoiE+L48euknADmTL5FwUOs1J5OUK0v8BcAYLO tqJ8Q8emx15ZTzHeI+Z9lDYIuYKBU9XuO8ugfbss/Xx2tQMDeHe6BIaujhwam6c4 BWyAIViXgWKpIIDB3Emsu3lStc3PJ1WLbBdw4ja0nwhCRB7IeclzZf1IZHTT4xsQ eg5EK2QORLrlY9keCoFhqfT4guSYQptBlwPuxhHM2gcrxXegR6294hBoPVSd1be5 g5NK0rrSWA== =9C0J -----END PGP SIGNATURE----- Merge tag 'io_uring-6.2-2023-01-13' of git://git.kernel.dk/linux Pull io_uring fixes from Jens Axboe: "A fix for a regression that happened last week, rest is fixes that will be headed to stable as well. In detail: - Fix for a regression added with the leak fix from last week (me) - In writing a test case for that leak, inadvertently discovered a case where we a poll request can race. So fix that up and mark it for stable, and also ensure that fdinfo covers both the poll tables that we have. The latter was an oversight when the split poll table were added (me) - Fix for a lockdep reported issue with IOPOLL (Pavel)" * tag 'io_uring-6.2-2023-01-13' of git://git.kernel.dk/linux: io_uring: lock overflowing for IOPOLL io_uring/poll: attempt request issue after racy poll wakeup io_uring/fdinfo: include locked hash table in fdinfo output io_uring/poll: add hash if ready poll request can't complete inline io_uring/io-wq: only free worker if it was allocated for creation
This commit is contained in:
commit
2ce7592df9
@ -170,12 +170,11 @@ static __cold void __io_uring_show_fdinfo(struct io_ring_ctx *ctx,
|
||||
xa_for_each(&ctx->personalities, index, cred)
|
||||
io_uring_show_cred(m, index, cred);
|
||||
}
|
||||
if (has_lock)
|
||||
mutex_unlock(&ctx->uring_lock);
|
||||
|
||||
seq_puts(m, "PollList:\n");
|
||||
for (i = 0; i < (1U << ctx->cancel_table.hash_bits); i++) {
|
||||
struct io_hash_bucket *hb = &ctx->cancel_table.hbs[i];
|
||||
struct io_hash_bucket *hbl = &ctx->cancel_table_locked.hbs[i];
|
||||
struct io_kiocb *req;
|
||||
|
||||
spin_lock(&hb->lock);
|
||||
@ -183,8 +182,17 @@ static __cold void __io_uring_show_fdinfo(struct io_ring_ctx *ctx,
|
||||
seq_printf(m, " op=%d, task_works=%d\n", req->opcode,
|
||||
task_work_pending(req->task));
|
||||
spin_unlock(&hb->lock);
|
||||
|
||||
if (!has_lock)
|
||||
continue;
|
||||
hlist_for_each_entry(req, &hbl->list, hash_node)
|
||||
seq_printf(m, " op=%d, task_works=%d\n", req->opcode,
|
||||
task_work_pending(req->task));
|
||||
}
|
||||
|
||||
if (has_lock)
|
||||
mutex_unlock(&ctx->uring_lock);
|
||||
|
||||
seq_puts(m, "CqOverflowList:\n");
|
||||
spin_lock(&ctx->completion_lock);
|
||||
list_for_each_entry(ocqe, &ctx->cq_overflow_list, list) {
|
||||
|
@ -1230,7 +1230,12 @@ static void io_wq_cancel_tw_create(struct io_wq *wq)
|
||||
|
||||
worker = container_of(cb, struct io_worker, create_work);
|
||||
io_worker_cancel_cb(worker);
|
||||
kfree(worker);
|
||||
/*
|
||||
* Only the worker continuation helper has worker allocated and
|
||||
* hence needs freeing.
|
||||
*/
|
||||
if (cb->func == create_worker_cont)
|
||||
kfree(worker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,21 +223,22 @@ enum {
|
||||
IOU_POLL_DONE = 0,
|
||||
IOU_POLL_NO_ACTION = 1,
|
||||
IOU_POLL_REMOVE_POLL_USE_RES = 2,
|
||||
IOU_POLL_REISSUE = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* All poll tw should go through this. Checks for poll events, manages
|
||||
* references, does rewait, etc.
|
||||
*
|
||||
* Returns a negative error on failure. IOU_POLL_NO_ACTION when no action require,
|
||||
* which is either spurious wakeup or multishot CQE is served.
|
||||
* IOU_POLL_DONE when it's done with the request, then the mask is stored in req->cqe.res.
|
||||
* IOU_POLL_REMOVE_POLL_USE_RES indicates to remove multishot poll and that the result
|
||||
* is stored in req->cqe.
|
||||
* Returns a negative error on failure. IOU_POLL_NO_ACTION when no action
|
||||
* require, which is either spurious wakeup or multishot CQE is served.
|
||||
* IOU_POLL_DONE when it's done with the request, then the mask is stored in
|
||||
* req->cqe.res. IOU_POLL_REMOVE_POLL_USE_RES indicates to remove multishot
|
||||
* poll and that the result is stored in req->cqe.
|
||||
*/
|
||||
static int io_poll_check_events(struct io_kiocb *req, bool *locked)
|
||||
{
|
||||
int v, ret;
|
||||
int v;
|
||||
|
||||
/* req->task == current here, checking PF_EXITING is safe */
|
||||
if (unlikely(req->task->flags & PF_EXITING))
|
||||
@ -276,10 +277,15 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
|
||||
if (!req->cqe.res) {
|
||||
struct poll_table_struct pt = { ._key = req->apoll_events };
|
||||
req->cqe.res = vfs_poll(req->file, &pt) & req->apoll_events;
|
||||
/*
|
||||
* We got woken with a mask, but someone else got to
|
||||
* it first. The above vfs_poll() doesn't add us back
|
||||
* to the waitqueue, so if we get nothing back, we
|
||||
* should be safe and attempt a reissue.
|
||||
*/
|
||||
if (unlikely(!req->cqe.res))
|
||||
return IOU_POLL_REISSUE;
|
||||
}
|
||||
|
||||
if ((unlikely(!req->cqe.res)))
|
||||
continue;
|
||||
if (req->apoll_events & EPOLLONESHOT)
|
||||
return IOU_POLL_DONE;
|
||||
|
||||
@ -294,7 +300,7 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
|
||||
return IOU_POLL_REMOVE_POLL_USE_RES;
|
||||
}
|
||||
} else {
|
||||
ret = io_poll_issue(req, locked);
|
||||
int ret = io_poll_issue(req, locked);
|
||||
if (ret == IOU_STOP_MULTISHOT)
|
||||
return IOU_POLL_REMOVE_POLL_USE_RES;
|
||||
if (ret < 0)
|
||||
@ -330,6 +336,9 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
|
||||
|
||||
poll = io_kiocb_to_cmd(req, struct io_poll);
|
||||
req->cqe.res = mangle_poll(req->cqe.res & poll->events);
|
||||
} else if (ret == IOU_POLL_REISSUE) {
|
||||
io_req_task_submit(req, locked);
|
||||
return;
|
||||
} else if (ret != IOU_POLL_REMOVE_POLL_USE_RES) {
|
||||
req->cqe.res = ret;
|
||||
req_set_fail(req);
|
||||
@ -342,7 +351,7 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
|
||||
|
||||
if (ret == IOU_POLL_REMOVE_POLL_USE_RES)
|
||||
io_req_task_complete(req, locked);
|
||||
else if (ret == IOU_POLL_DONE)
|
||||
else if (ret == IOU_POLL_DONE || ret == IOU_POLL_REISSUE)
|
||||
io_req_task_submit(req, locked);
|
||||
else
|
||||
io_req_defer_failed(req, ret);
|
||||
@ -533,6 +542,14 @@ static bool io_poll_can_finish_inline(struct io_kiocb *req,
|
||||
return pt->owning || io_poll_get_ownership(req);
|
||||
}
|
||||
|
||||
static void io_poll_add_hash(struct io_kiocb *req)
|
||||
{
|
||||
if (req->flags & REQ_F_HASH_LOCKED)
|
||||
io_poll_req_insert_locked(req);
|
||||
else
|
||||
io_poll_req_insert(req);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 when it's handed over for polling. The caller owns the requests if
|
||||
* it returns non-zero, but otherwise should not touch it. Negative values
|
||||
@ -591,18 +608,17 @@ static int __io_arm_poll_handler(struct io_kiocb *req,
|
||||
|
||||
if (mask &&
|
||||
((poll->events & (EPOLLET|EPOLLONESHOT)) == (EPOLLET|EPOLLONESHOT))) {
|
||||
if (!io_poll_can_finish_inline(req, ipt))
|
||||
if (!io_poll_can_finish_inline(req, ipt)) {
|
||||
io_poll_add_hash(req);
|
||||
return 0;
|
||||
}
|
||||
io_poll_remove_entries(req);
|
||||
ipt->result_mask = mask;
|
||||
/* no one else has access to the req, forget about the ref */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (req->flags & REQ_F_HASH_LOCKED)
|
||||
io_poll_req_insert_locked(req);
|
||||
else
|
||||
io_poll_req_insert(req);
|
||||
io_poll_add_hash(req);
|
||||
|
||||
if (mask && (poll->events & EPOLLET) &&
|
||||
io_poll_can_finish_inline(req, ipt)) {
|
||||
|
@ -1062,7 +1062,11 @@ int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin)
|
||||
continue;
|
||||
|
||||
req->cqe.flags = io_put_kbuf(req, 0);
|
||||
io_fill_cqe_req(req->ctx, req);
|
||||
if (unlikely(!__io_fill_cqe_req(ctx, req))) {
|
||||
spin_lock(&ctx->completion_lock);
|
||||
io_req_cqe_overflow(req);
|
||||
spin_unlock(&ctx->completion_lock);
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!nr_events))
|
||||
|
Loading…
Reference in New Issue
Block a user