Skip to content

Commit 86799cd

Browse files
committed
Merge tag 'io_uring-5.16-2021-11-27' of git://git.kernel.dk/linux-block
Pull more io_uring fixes from Jens Axboe: "The locking fixup that was applied earlier this rc has both a deadlock and IRQ safety issue, let's get that ironed out before -rc3. This contains: - Link traversal locking fix (Pavel) - Cancelation fix (Pavel) - Relocate cond_resched() for huge buffer chain freeing, avoiding a softlockup warning (Ye) - Fix timespec validation (Ye)" * tag 'io_uring-5.16-2021-11-27' of git://git.kernel.dk/linux-block: io_uring: Fix undefined-behaviour in io_issue_sqe io_uring: fix soft lockup when call __io_remove_buffers io_uring: fix link traversal locking io_uring: fail cancellation for EXITING tasks
2 parents 650c8ed + f6223ff commit 86799cd

File tree

1 file changed

+50
-23
lines changed

1 file changed

+50
-23
lines changed

fs/io_uring.c

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,7 @@ static void io_refs_resurrect(struct percpu_ref *ref, struct completion *compl)
12781278

12791279
static bool io_match_task(struct io_kiocb *head, struct task_struct *task,
12801280
bool cancel_all)
1281+
__must_hold(&req->ctx->timeout_lock)
12811282
{
12821283
struct io_kiocb *req;
12831284

@@ -1293,6 +1294,44 @@ static bool io_match_task(struct io_kiocb *head, struct task_struct *task,
12931294
return false;
12941295
}
12951296

1297+
static bool io_match_linked(struct io_kiocb *head)
1298+
{
1299+
struct io_kiocb *req;
1300+
1301+
io_for_each_link(req, head) {
1302+
if (req->flags & REQ_F_INFLIGHT)
1303+
return true;
1304+
}
1305+
return false;
1306+
}
1307+
1308+
/*
1309+
* As io_match_task() but protected against racing with linked timeouts.
1310+
* User must not hold timeout_lock.
1311+
*/
1312+
static bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task,
1313+
bool cancel_all)
1314+
{
1315+
bool matched;
1316+
1317+
if (task && head->task != task)
1318+
return false;
1319+
if (cancel_all)
1320+
return true;
1321+
1322+
if (head->flags & REQ_F_LINK_TIMEOUT) {
1323+
struct io_ring_ctx *ctx = head->ctx;
1324+
1325+
/* protect against races with linked timeouts */
1326+
spin_lock_irq(&ctx->timeout_lock);
1327+
matched = io_match_linked(head);
1328+
spin_unlock_irq(&ctx->timeout_lock);
1329+
} else {
1330+
matched = io_match_linked(head);
1331+
}
1332+
return matched;
1333+
}
1334+
12961335
static inline bool req_has_async_data(struct io_kiocb *req)
12971336
{
12981337
return req->flags & REQ_F_ASYNC_DATA;
@@ -4327,6 +4366,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf,
43274366
kfree(nxt);
43284367
if (++i == nbufs)
43294368
return i;
4369+
cond_resched();
43304370
}
43314371
i++;
43324372
kfree(buf);
@@ -5699,17 +5739,15 @@ static __cold bool io_poll_remove_all(struct io_ring_ctx *ctx,
56995739
int posted = 0, i;
57005740

57015741
spin_lock(&ctx->completion_lock);
5702-
spin_lock_irq(&ctx->timeout_lock);
57035742
for (i = 0; i < (1U << ctx->cancel_hash_bits); i++) {
57045743
struct hlist_head *list;
57055744

57065745
list = &ctx->cancel_hash[i];
57075746
hlist_for_each_entry_safe(req, tmp, list, hash_node) {
5708-
if (io_match_task(req, tsk, cancel_all))
5747+
if (io_match_task_safe(req, tsk, cancel_all))
57095748
posted += io_poll_remove_one(req);
57105749
}
57115750
}
5712-
spin_unlock_irq(&ctx->timeout_lock);
57135751
spin_unlock(&ctx->completion_lock);
57145752

57155753
if (posted)
@@ -6158,6 +6196,9 @@ static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
61586196
if (get_timespec64(&data->ts, u64_to_user_ptr(sqe->addr)))
61596197
return -EFAULT;
61606198

6199+
if (data->ts.tv_sec < 0 || data->ts.tv_nsec < 0)
6200+
return -EINVAL;
6201+
61616202
data->mode = io_translate_timeout_mode(flags);
61626203
hrtimer_init(&data->timer, io_timeout_get_clock(data), data->mode);
61636204

@@ -6882,10 +6923,11 @@ static inline struct file *io_file_get(struct io_ring_ctx *ctx,
68826923
static void io_req_task_link_timeout(struct io_kiocb *req, bool *locked)
68836924
{
68846925
struct io_kiocb *prev = req->timeout.prev;
6885-
int ret;
6926+
int ret = -ENOENT;
68866927

68876928
if (prev) {
6888-
ret = io_try_cancel_userdata(req, prev->user_data);
6929+
if (!(req->task->flags & PF_EXITING))
6930+
ret = io_try_cancel_userdata(req, prev->user_data);
68896931
io_req_complete_post(req, ret ?: -ETIME, 0);
68906932
io_put_req(prev);
68916933
} else {
@@ -9257,10 +9299,8 @@ static void io_destroy_buffers(struct io_ring_ctx *ctx)
92579299
struct io_buffer *buf;
92589300
unsigned long index;
92599301

9260-
xa_for_each(&ctx->io_buffers, index, buf) {
9302+
xa_for_each(&ctx->io_buffers, index, buf)
92619303
__io_remove_buffers(ctx, buf, index, -1U);
9262-
cond_resched();
9263-
}
92649304
}
92659305

92669306
static void io_req_caches_free(struct io_ring_ctx *ctx)
@@ -9564,19 +9604,8 @@ static bool io_cancel_task_cb(struct io_wq_work *work, void *data)
95649604
{
95659605
struct io_kiocb *req = container_of(work, struct io_kiocb, work);
95669606
struct io_task_cancel *cancel = data;
9567-
bool ret;
9568-
9569-
if (!cancel->all && (req->flags & REQ_F_LINK_TIMEOUT)) {
9570-
struct io_ring_ctx *ctx = req->ctx;
95719607

9572-
/* protect against races with linked timeouts */
9573-
spin_lock_irq(&ctx->timeout_lock);
9574-
ret = io_match_task(req, cancel->task, cancel->all);
9575-
spin_unlock_irq(&ctx->timeout_lock);
9576-
} else {
9577-
ret = io_match_task(req, cancel->task, cancel->all);
9578-
}
9579-
return ret;
9608+
return io_match_task_safe(req, cancel->task, cancel->all);
95809609
}
95819610

95829611
static __cold bool io_cancel_defer_files(struct io_ring_ctx *ctx,
@@ -9587,14 +9616,12 @@ static __cold bool io_cancel_defer_files(struct io_ring_ctx *ctx,
95879616
LIST_HEAD(list);
95889617

95899618
spin_lock(&ctx->completion_lock);
9590-
spin_lock_irq(&ctx->timeout_lock);
95919619
list_for_each_entry_reverse(de, &ctx->defer_list, list) {
9592-
if (io_match_task(de->req, task, cancel_all)) {
9620+
if (io_match_task_safe(de->req, task, cancel_all)) {
95939621
list_cut_position(&list, &ctx->defer_list, &de->list);
95949622
break;
95959623
}
95969624
}
9597-
spin_unlock_irq(&ctx->timeout_lock);
95989625
spin_unlock(&ctx->completion_lock);
95999626
if (list_empty(&list))
96009627
return false;

0 commit comments

Comments
 (0)