Skip to content

Commit b60c8dc

Browse files
isilenceaxboe
authored andcommitted
io_uring: preparation for rsrc tagging
We need a way to notify userspace when a lazily removed resource actually died out. This will be done by associating a tag, which is u64 exactly like req->user_data, with each rsrc (e.g. buffer of file). A CQE will be posted once a resource is actually put down. Tag 0 is a special value set by default, for whcih it don't generate an CQE, so providing the old behaviour. Don't expose it to the userspace yet, but prepare internally, allocate buffers, add all posting hooks, etc. Signed-off-by: Pavel Begunkov <[email protected]> Link: https://lore.kernel.org/r/2e6beec5eabe7216bb61fb93cdf5aaf65812a9b0.1619356238.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <[email protected]>
1 parent d4d19c1 commit b60c8dc

File tree

1 file changed

+30
-4
lines changed

1 file changed

+30
-4
lines changed

fs/io_uring.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ struct io_fixed_file {
214214

215215
struct io_rsrc_put {
216216
struct list_head list;
217+
u64 tag;
217218
union {
218219
void *rsrc;
219220
struct file *file;
@@ -239,6 +240,7 @@ typedef void (rsrc_put_fn)(struct io_ring_ctx *ctx, struct io_rsrc_put *prsrc);
239240
struct io_rsrc_data {
240241
struct io_ring_ctx *ctx;
241242

243+
u64 *tags;
242244
rsrc_put_fn *do_put;
243245
atomic_t refs;
244246
struct completion done;
@@ -7117,18 +7119,26 @@ static int io_rsrc_ref_quiesce(struct io_rsrc_data *data, struct io_ring_ctx *ct
71177119

71187120
static void io_rsrc_data_free(struct io_rsrc_data *data)
71197121
{
7122+
kvfree(data->tags);
71207123
kfree(data);
71217124
}
71227125

71237126
static struct io_rsrc_data *io_rsrc_data_alloc(struct io_ring_ctx *ctx,
7124-
rsrc_put_fn *do_put)
7127+
rsrc_put_fn *do_put,
7128+
unsigned nr)
71257129
{
71267130
struct io_rsrc_data *data;
71277131

71287132
data = kzalloc(sizeof(*data), GFP_KERNEL);
71297133
if (!data)
71307134
return NULL;
71317135

7136+
data->tags = kvcalloc(nr, sizeof(*data->tags), GFP_KERNEL);
7137+
if (!data->tags) {
7138+
kfree(data);
7139+
return NULL;
7140+
}
7141+
71327142
atomic_set(&data->refs, 1);
71337143
data->ctx = ctx;
71347144
data->do_put = do_put;
@@ -7493,6 +7503,20 @@ static void __io_rsrc_put_work(struct io_rsrc_node *ref_node)
74937503

74947504
list_for_each_entry_safe(prsrc, tmp, &ref_node->rsrc_list, list) {
74957505
list_del(&prsrc->list);
7506+
7507+
if (prsrc->tag) {
7508+
bool lock_ring = ctx->flags & IORING_SETUP_IOPOLL;
7509+
unsigned long flags;
7510+
7511+
io_ring_submit_lock(ctx, lock_ring);
7512+
spin_lock_irqsave(&ctx->completion_lock, flags);
7513+
io_cqring_fill_event(ctx, prsrc->tag, 0, 0);
7514+
io_commit_cqring(ctx);
7515+
spin_unlock_irqrestore(&ctx->completion_lock, flags);
7516+
io_cqring_ev_posted(ctx);
7517+
io_ring_submit_unlock(ctx, lock_ring);
7518+
}
7519+
74967520
rsrc_data->do_put(ctx, prsrc);
74977521
kfree(prsrc);
74987522
}
@@ -7582,7 +7606,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
75827606
if (ret)
75837607
return ret;
75847608

7585-
file_data = io_rsrc_data_alloc(ctx, io_rsrc_file_put);
7609+
file_data = io_rsrc_data_alloc(ctx, io_rsrc_file_put, nr_args);
75867610
if (!file_data)
75877611
return -ENOMEM;
75887612
ctx->file_data = file_data;
@@ -7683,7 +7707,7 @@ static int io_sqe_file_register(struct io_ring_ctx *ctx, struct file *file,
76837707
#endif
76847708
}
76857709

7686-
static int io_queue_rsrc_removal(struct io_rsrc_data *data,
7710+
static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
76877711
struct io_rsrc_node *node, void *rsrc)
76887712
{
76897713
struct io_rsrc_put *prsrc;
@@ -7692,6 +7716,7 @@ static int io_queue_rsrc_removal(struct io_rsrc_data *data,
76927716
if (!prsrc)
76937717
return -ENOMEM;
76947718

7719+
prsrc->tag = data->tags[idx];
76957720
prsrc->rsrc = rsrc;
76967721
list_add(&prsrc->list, &node->rsrc_list);
76977722
return 0;
@@ -7732,7 +7757,8 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
77327757

77337758
if (file_slot->file_ptr) {
77347759
file = (struct file *)(file_slot->file_ptr & FFS_MASK);
7735-
err = io_queue_rsrc_removal(data, ctx->rsrc_node, file);
7760+
err = io_queue_rsrc_removal(data, up->offset + done,
7761+
ctx->rsrc_node, file);
77367762
if (err)
77377763
break;
77387764
file_slot->file_ptr = 0;

0 commit comments

Comments
 (0)