Commit e3391589 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'io_uring-6.10-20240607' of git://git.kernel.dk/linux

Pull io_uring fixes from Jens Axboe:

 - Fix a locking order issue with setting max async thread workers
   (Hagar)

 - Fix for a NULL pointer dereference for failed async flagged requests
   using ring provided buffers. This doesn't affect the current kernel,
   but it does affect older kernels, and is being queued up for 6.10
   just to make the stable process easier (me)

 - Fix for NAPI timeout calculations for how long to busy poll, and
   subsequently how much to sleep post that if a wait timeout is passed
   in (me)

 - Fix for a regression in this release cycle, where we could end up
   using a partially unitialized match value for io-wq (Su)

* tag 'io_uring-6.10-20240607' of git://git.kernel.dk/linux:
  io_uring: fix possible deadlock in io_register_iowq_max_workers()
  io_uring/io-wq: avoid garbage value of 'match' in io_wq_enqueue()
  io_uring/napi: fix timeout calculation
  io_uring: check for non-NULL file pointer in io_file_can_poll()
parents 07978330 73254a29
......@@ -927,7 +927,11 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)
{
struct io_wq_acct *acct = io_work_get_acct(wq, work);
unsigned long work_flags = work->flags;
struct io_cb_cancel_data match;
struct io_cb_cancel_data match = {
.fn = io_wq_work_match_item,
.data = work,
.cancel_all = false,
};
bool do_create;
/*
......@@ -965,10 +969,6 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work)
raw_spin_unlock(&wq->lock);
/* fatal condition, failed to create the first worker */
match.fn = io_wq_work_match_item,
match.data = work,
match.cancel_all = false,
io_acct_cancel_pending_work(wq, acct, &match);
}
}
......
......@@ -433,7 +433,7 @@ static inline bool io_file_can_poll(struct io_kiocb *req)
{
if (req->flags & REQ_F_CAN_POLL)
return true;
if (file_can_poll(req->file)) {
if (req->file && file_can_poll(req->file)) {
req->flags |= REQ_F_CAN_POLL;
return true;
}
......
......@@ -261,12 +261,14 @@ int io_unregister_napi(struct io_ring_ctx *ctx, void __user *arg)
}
/*
* __io_napi_adjust_timeout() - Add napi id to the busy poll list
* __io_napi_adjust_timeout() - adjust busy loop timeout
* @ctx: pointer to io-uring context structure
* @iowq: pointer to io wait queue
* @ts: pointer to timespec or NULL
*
* Adjust the busy loop timeout according to timespec and busy poll timeout.
* If the specified NAPI timeout is bigger than the wait timeout, then adjust
* the NAPI timeout accordingly.
*/
void __io_napi_adjust_timeout(struct io_ring_ctx *ctx, struct io_wait_queue *iowq,
struct timespec64 *ts)
......@@ -274,16 +276,16 @@ void __io_napi_adjust_timeout(struct io_ring_ctx *ctx, struct io_wait_queue *iow
unsigned int poll_to = READ_ONCE(ctx->napi_busy_poll_to);
if (ts) {
struct timespec64 poll_to_ts = ns_to_timespec64(1000 * (s64)poll_to);
if (timespec64_compare(ts, &poll_to_ts) > 0) {
*ts = timespec64_sub(*ts, poll_to_ts);
} else {
u64 to = timespec64_to_ns(ts);
do_div(to, 1000);
ts->tv_sec = 0;
ts->tv_nsec = 0;
struct timespec64 poll_to_ts;
poll_to_ts = ns_to_timespec64(1000 * (s64)poll_to);
if (timespec64_compare(ts, &poll_to_ts) < 0) {
s64 poll_to_ns = timespec64_to_ns(ts);
if (poll_to_ns > 0) {
u64 val = poll_to_ns + 999;
do_div(val, (s64) 1000);
poll_to = val;
}
}
}
......
......@@ -355,8 +355,10 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
}
if (sqd) {
mutex_unlock(&ctx->uring_lock);
mutex_unlock(&sqd->lock);
io_put_sq_data(sqd);
mutex_lock(&ctx->uring_lock);
}
if (copy_to_user(arg, new_count, sizeof(new_count)))
......@@ -380,8 +382,10 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
return 0;
err:
if (sqd) {
mutex_unlock(&ctx->uring_lock);
mutex_unlock(&sqd->lock);
io_put_sq_data(sqd);
mutex_lock(&ctx->uring_lock);
}
return ret;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment