Skip to content

Commit dc3e24b

Browse files
committed
Merge tag 'io_uring-5.11-2021-01-01' of git://git.kernel.dk/linux-block
Pull io_uring fixes from Jens Axboe: "A few fixes that should go into 5.11, all marked for stable as well: - Fix issue around identity COW'ing and users that share a ring across processes - Fix a hang associated with unregistering fixed files (Pavel) - Move the 'process is exiting' cancelation a bit earlier, so task_works aren't affected by it (Pavel)" * tag 'io_uring-5.11-2021-01-01' of git://git.kernel.dk/linux-block: kernel/io_uring: cancel io_uring before task works io_uring: fix io_sqe_files_unregister() hangs io_uring: add a helper for setting a ref node io_uring: don't assume mm is constant across submits
2 parents cedd186 + b1b6b5a commit dc3e24b

File tree

3 files changed

+43
-21
lines changed

3 files changed

+43
-21
lines changed

fs/file.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include <linux/rcupdate.h>
2222
#include <linux/close_range.h>
2323
#include <net/sock.h>
24-
#include <linux/io_uring.h>
2524

2625
unsigned int sysctl_nr_open __read_mostly = 1024*1024;
2726
unsigned int sysctl_nr_open_min = BITS_PER_LONG;
@@ -428,7 +427,6 @@ void exit_files(struct task_struct *tsk)
428427
struct files_struct * files = tsk->files;
429428

430429
if (files) {
431-
io_uring_files_cancel(files);
432430
task_lock(tsk);
433431
tsk->files = NULL;
434432
task_unlock(tsk);

fs/io_uring.c

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,10 @@ enum io_mem_account {
992992
ACCT_PINNED,
993993
};
994994

995+
static void destroy_fixed_file_ref_node(struct fixed_file_ref_node *ref_node);
996+
static struct fixed_file_ref_node *alloc_fixed_file_ref_node(
997+
struct io_ring_ctx *ctx);
998+
995999
static void __io_complete_rw(struct io_kiocb *req, long res, long res2,
9961000
struct io_comp_state *cs);
9971001
static void io_cqring_fill_event(struct io_kiocb *req, long res);
@@ -1501,6 +1505,13 @@ static bool io_grab_identity(struct io_kiocb *req)
15011505
spin_unlock_irq(&ctx->inflight_lock);
15021506
req->work.flags |= IO_WQ_WORK_FILES;
15031507
}
1508+
if (!(req->work.flags & IO_WQ_WORK_MM) &&
1509+
(def->work_flags & IO_WQ_WORK_MM)) {
1510+
if (id->mm != current->mm)
1511+
return false;
1512+
mmgrab(id->mm);
1513+
req->work.flags |= IO_WQ_WORK_MM;
1514+
}
15041515

15051516
return true;
15061517
}
@@ -1525,13 +1536,6 @@ static void io_prep_async_work(struct io_kiocb *req)
15251536
req->work.flags |= IO_WQ_WORK_UNBOUND;
15261537
}
15271538

1528-
/* ->mm can never change on us */
1529-
if (!(req->work.flags & IO_WQ_WORK_MM) &&
1530-
(def->work_flags & IO_WQ_WORK_MM)) {
1531-
mmgrab(id->mm);
1532-
req->work.flags |= IO_WQ_WORK_MM;
1533-
}
1534-
15351539
/* if we fail grabbing identity, we must COW, regrab, and retry */
15361540
if (io_grab_identity(req))
15371541
return;
@@ -7231,14 +7235,28 @@ static void io_file_ref_kill(struct percpu_ref *ref)
72317235
complete(&data->done);
72327236
}
72337237

7238+
static void io_sqe_files_set_node(struct fixed_file_data *file_data,
7239+
struct fixed_file_ref_node *ref_node)
7240+
{
7241+
spin_lock_bh(&file_data->lock);
7242+
file_data->node = ref_node;
7243+
list_add_tail(&ref_node->node, &file_data->ref_list);
7244+
spin_unlock_bh(&file_data->lock);
7245+
percpu_ref_get(&file_data->refs);
7246+
}
7247+
72347248
static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
72357249
{
72367250
struct fixed_file_data *data = ctx->file_data;
7237-
struct fixed_file_ref_node *ref_node = NULL;
7251+
struct fixed_file_ref_node *backup_node, *ref_node = NULL;
72387252
unsigned nr_tables, i;
7253+
int ret;
72397254

72407255
if (!data)
72417256
return -ENXIO;
7257+
backup_node = alloc_fixed_file_ref_node(ctx);
7258+
if (!backup_node)
7259+
return -ENOMEM;
72427260

72437261
spin_lock_bh(&data->lock);
72447262
ref_node = data->node;
@@ -7250,7 +7268,18 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
72507268

72517269
/* wait for all refs nodes to complete */
72527270
flush_delayed_work(&ctx->file_put_work);
7253-
wait_for_completion(&data->done);
7271+
do {
7272+
ret = wait_for_completion_interruptible(&data->done);
7273+
if (!ret)
7274+
break;
7275+
ret = io_run_task_work_sig();
7276+
if (ret < 0) {
7277+
percpu_ref_resurrect(&data->refs);
7278+
reinit_completion(&data->done);
7279+
io_sqe_files_set_node(data, backup_node);
7280+
return ret;
7281+
}
7282+
} while (1);
72547283

72557284
__io_sqe_files_unregister(ctx);
72567285
nr_tables = DIV_ROUND_UP(ctx->nr_user_files, IORING_MAX_FILES_TABLE);
@@ -7261,6 +7290,7 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
72617290
kfree(data);
72627291
ctx->file_data = NULL;
72637292
ctx->nr_user_files = 0;
7293+
destroy_fixed_file_ref_node(backup_node);
72647294
return 0;
72657295
}
72667296

@@ -7758,11 +7788,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
77587788
return PTR_ERR(ref_node);
77597789
}
77607790

7761-
file_data->node = ref_node;
7762-
spin_lock_bh(&file_data->lock);
7763-
list_add_tail(&ref_node->node, &file_data->ref_list);
7764-
spin_unlock_bh(&file_data->lock);
7765-
percpu_ref_get(&file_data->refs);
7791+
io_sqe_files_set_node(file_data, ref_node);
77667792
return ret;
77677793
out_fput:
77687794
for (i = 0; i < ctx->nr_user_files; i++) {
@@ -7918,11 +7944,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
79187944

79197945
if (needs_switch) {
79207946
percpu_ref_kill(&data->node->refs);
7921-
spin_lock_bh(&data->lock);
7922-
list_add_tail(&ref_node->node, &data->ref_list);
7923-
data->node = ref_node;
7924-
spin_unlock_bh(&data->lock);
7925-
percpu_ref_get(&ctx->file_data->refs);
7947+
io_sqe_files_set_node(data, ref_node);
79267948
} else
79277949
destroy_fixed_file_ref_node(ref_node);
79287950

kernel/exit.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include <linux/random.h>
6464
#include <linux/rcuwait.h>
6565
#include <linux/compat.h>
66+
#include <linux/io_uring.h>
6667

6768
#include <linux/uaccess.h>
6869
#include <asm/unistd.h>
@@ -776,6 +777,7 @@ void __noreturn do_exit(long code)
776777
schedule();
777778
}
778779

780+
io_uring_files_cancel(tsk->files);
779781
exit_signals(tsk); /* sets PF_EXITING */
780782

781783
/* sync mm's RSS info before statistics gathering */

0 commit comments

Comments
 (0)