Skip to content

Commit c200376

Browse files
committed
Merge tag 'io_uring-5.6-2020-03-07' of git://git.kernel.dk/linux-block
Pull io_uring fixes from Jens Axboe: "Here are a few io_uring fixes that should go into this release. This contains: - Removal of (now) unused io_wq_flush() and associated flag (Pavel) - Fix cancelation lockup with linked timeouts (Pavel) - Fix for potential use-after-free when freeing percpu ref for fixed file sets - io-wq cancelation fixups (Pavel)" * tag 'io_uring-5.6-2020-03-07' of git://git.kernel.dk/linux-block: io_uring: fix lockup with timeouts io_uring: free fixed_file_data after RCU grace period io-wq: remove io_wq_flush and IO_WQ_WORK_INTERNAL io-wq: fix IO_WQ_WORK_NO_CANCEL cancellation
2 parents 5dfcc13 + f0e20b8 commit c200376

File tree

3 files changed

+38
-47
lines changed

3 files changed

+38
-47
lines changed

fs/io-wq.c

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ static void io_worker_handle_work(struct io_worker *worker)
502502
if (worker->mm)
503503
work->flags |= IO_WQ_WORK_HAS_MM;
504504

505-
if (wq->get_work && !(work->flags & IO_WQ_WORK_INTERNAL)) {
505+
if (wq->get_work) {
506506
put_work = work;
507507
wq->get_work(work);
508508
}
@@ -747,6 +747,17 @@ static bool io_wq_can_queue(struct io_wqe *wqe, struct io_wqe_acct *acct,
747747
return true;
748748
}
749749

750+
static void io_run_cancel(struct io_wq_work *work)
751+
{
752+
do {
753+
struct io_wq_work *old_work = work;
754+
755+
work->flags |= IO_WQ_WORK_CANCEL;
756+
work->func(&work);
757+
work = (work == old_work) ? NULL : work;
758+
} while (work);
759+
}
760+
750761
static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)
751762
{
752763
struct io_wqe_acct *acct = io_work_get_acct(wqe, work);
@@ -760,8 +771,7 @@ static void io_wqe_enqueue(struct io_wqe *wqe, struct io_wq_work *work)
760771
* It's close enough to not be an issue, fork() has the same delay.
761772
*/
762773
if (unlikely(!io_wq_can_queue(wqe, acct, work))) {
763-
work->flags |= IO_WQ_WORK_CANCEL;
764-
work->func(&work);
774+
io_run_cancel(work);
765775
return;
766776
}
767777

@@ -900,8 +910,7 @@ static enum io_wq_cancel io_wqe_cancel_cb_work(struct io_wqe *wqe,
900910
spin_unlock_irqrestore(&wqe->lock, flags);
901911

902912
if (found) {
903-
work->flags |= IO_WQ_WORK_CANCEL;
904-
work->func(&work);
913+
io_run_cancel(work);
905914
return IO_WQ_CANCEL_OK;
906915
}
907916

@@ -976,8 +985,7 @@ static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe,
976985
spin_unlock_irqrestore(&wqe->lock, flags);
977986

978987
if (found) {
979-
work->flags |= IO_WQ_WORK_CANCEL;
980-
work->func(&work);
988+
io_run_cancel(work);
981989
return IO_WQ_CANCEL_OK;
982990
}
983991

@@ -1049,42 +1057,6 @@ enum io_wq_cancel io_wq_cancel_pid(struct io_wq *wq, pid_t pid)
10491057
return ret;
10501058
}
10511059

1052-
struct io_wq_flush_data {
1053-
struct io_wq_work work;
1054-
struct completion done;
1055-
};
1056-
1057-
static void io_wq_flush_func(struct io_wq_work **workptr)
1058-
{
1059-
struct io_wq_work *work = *workptr;
1060-
struct io_wq_flush_data *data;
1061-
1062-
data = container_of(work, struct io_wq_flush_data, work);
1063-
complete(&data->done);
1064-
}
1065-
1066-
/*
1067-
* Doesn't wait for previously queued work to finish. When this completes,
1068-
* it just means that previously queued work was started.
1069-
*/
1070-
void io_wq_flush(struct io_wq *wq)
1071-
{
1072-
struct io_wq_flush_data data;
1073-
int node;
1074-
1075-
for_each_node(node) {
1076-
struct io_wqe *wqe = wq->wqes[node];
1077-
1078-
if (!node_online(node))
1079-
continue;
1080-
init_completion(&data.done);
1081-
INIT_IO_WORK(&data.work, io_wq_flush_func);
1082-
data.work.flags |= IO_WQ_WORK_INTERNAL;
1083-
io_wqe_enqueue(wqe, &data.work);
1084-
wait_for_completion(&data.done);
1085-
}
1086-
}
1087-
10881060
struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
10891061
{
10901062
int ret = -ENOMEM, node;

fs/io-wq.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ enum {
88
IO_WQ_WORK_HAS_MM = 2,
99
IO_WQ_WORK_HASHED = 4,
1010
IO_WQ_WORK_UNBOUND = 32,
11-
IO_WQ_WORK_INTERNAL = 64,
1211
IO_WQ_WORK_CB = 128,
1312
IO_WQ_WORK_NO_CANCEL = 256,
1413
IO_WQ_WORK_CONCURRENT = 512,
@@ -100,7 +99,6 @@ void io_wq_destroy(struct io_wq *wq);
10099

101100
void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work);
102101
void io_wq_enqueue_hashed(struct io_wq *wq, struct io_wq_work *work, void *val);
103-
void io_wq_flush(struct io_wq *wq);
104102

105103
void io_wq_cancel_all(struct io_wq *wq);
106104
enum io_wq_cancel io_wq_cancel_work(struct io_wq *wq, struct io_wq_work *cwork);

fs/io_uring.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ struct fixed_file_data {
191191
struct llist_head put_llist;
192192
struct work_struct ref_work;
193193
struct completion done;
194+
struct rcu_head rcu;
194195
};
195196

196197
struct io_ring_ctx {
@@ -999,6 +1000,7 @@ static void io_kill_timeout(struct io_kiocb *req)
9991000
if (ret != -1) {
10001001
atomic_inc(&req->ctx->cq_timeouts);
10011002
list_del_init(&req->list);
1003+
req->flags |= REQ_F_COMP_LOCKED;
10021004
io_cqring_fill_event(req, 0);
10031005
io_put_req(req);
10041006
}
@@ -5329,6 +5331,26 @@ static void io_file_ref_kill(struct percpu_ref *ref)
53295331
complete(&data->done);
53305332
}
53315333

5334+
static void __io_file_ref_exit_and_free(struct rcu_head *rcu)
5335+
{
5336+
struct fixed_file_data *data = container_of(rcu, struct fixed_file_data,
5337+
rcu);
5338+
percpu_ref_exit(&data->refs);
5339+
kfree(data);
5340+
}
5341+
5342+
static void io_file_ref_exit_and_free(struct rcu_head *rcu)
5343+
{
5344+
/*
5345+
* We need to order our exit+free call against the potentially
5346+
* existing call_rcu() for switching to atomic. One way to do that
5347+
* is to have this rcu callback queue the final put and free, as we
5348+
* could otherwise have a pre-existing atomic switch complete _after_
5349+
* the free callback we queued.
5350+
*/
5351+
call_rcu(rcu, __io_file_ref_exit_and_free);
5352+
}
5353+
53325354
static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
53335355
{
53345356
struct fixed_file_data *data = ctx->file_data;
@@ -5341,14 +5363,13 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
53415363
flush_work(&data->ref_work);
53425364
wait_for_completion(&data->done);
53435365
io_ring_file_ref_flush(data);
5344-
percpu_ref_exit(&data->refs);
53455366

53465367
__io_sqe_files_unregister(ctx);
53475368
nr_tables = DIV_ROUND_UP(ctx->nr_user_files, IORING_MAX_FILES_TABLE);
53485369
for (i = 0; i < nr_tables; i++)
53495370
kfree(data->table[i].files);
53505371
kfree(data->table);
5351-
kfree(data);
5372+
call_rcu(&data->rcu, io_file_ref_exit_and_free);
53525373
ctx->file_data = NULL;
53535374
ctx->nr_user_files = 0;
53545375
return 0;

0 commit comments

Comments
 (0)