Skip to content

Commit 9c7b0ba

Browse files
isilenceaxboe
authored andcommitted
io_uring: auto-removal for direct open/accept
It might be inconvenient that direct open/accept deviates from the update semantics and fails if the slot is taken instead of removing a file sitting there. Implement this auto-removal. Note that removal might need to allocate and so may fail. However, if an empty slot is specified, it's guaraneed to not fail on the fd installation side for valid userspace programs. It's needed for users who can't tolerate such failures, e.g. accept where the other end never retries. Suggested-by: Franz-B. Tuneke <franz-bernhard.tuneke@tu-dortmund.de> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Link: https://lore.kernel.org/r/c896f14ea46b0eaa6c09d93149e665c2c37979b4.1631632300.git.asml.silence@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 44df58d commit 9c7b0ba

File tree

1 file changed

+34
-18
lines changed

1 file changed

+34
-18
lines changed

fs/io_uring.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8287,11 +8287,27 @@ static int io_sqe_file_register(struct io_ring_ctx *ctx, struct file *file,
82878287
#endif
82888288
}
82898289

8290+
static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
8291+
struct io_rsrc_node *node, void *rsrc)
8292+
{
8293+
struct io_rsrc_put *prsrc;
8294+
8295+
prsrc = kzalloc(sizeof(*prsrc), GFP_KERNEL);
8296+
if (!prsrc)
8297+
return -ENOMEM;
8298+
8299+
prsrc->tag = *io_get_tag_slot(data, idx);
8300+
prsrc->rsrc = rsrc;
8301+
list_add(&prsrc->list, &node->rsrc_list);
8302+
return 0;
8303+
}
8304+
82908305
static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
82918306
unsigned int issue_flags, u32 slot_index)
82928307
{
82938308
struct io_ring_ctx *ctx = req->ctx;
82948309
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
8310+
bool needs_switch = false;
82958311
struct io_fixed_file *file_slot;
82968312
int ret = -EBADF;
82978313

@@ -8307,9 +8323,22 @@ static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
83078323

83088324
slot_index = array_index_nospec(slot_index, ctx->nr_user_files);
83098325
file_slot = io_fixed_file_slot(&ctx->file_table, slot_index);
8310-
ret = -EBADF;
8311-
if (file_slot->file_ptr)
8312-
goto err;
8326+
8327+
if (file_slot->file_ptr) {
8328+
struct file *old_file;
8329+
8330+
ret = io_rsrc_node_switch_start(ctx);
8331+
if (ret)
8332+
goto err;
8333+
8334+
old_file = (struct file *)(file_slot->file_ptr & FFS_MASK);
8335+
ret = io_queue_rsrc_removal(ctx->file_data, slot_index,
8336+
ctx->rsrc_node, old_file);
8337+
if (ret)
8338+
goto err;
8339+
file_slot->file_ptr = 0;
8340+
needs_switch = true;
8341+
}
83138342

83148343
*io_get_tag_slot(ctx->file_data, slot_index) = 0;
83158344
io_fixed_file_set(file_slot, file);
@@ -8321,27 +8350,14 @@ static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
83218350

83228351
ret = 0;
83238352
err:
8353+
if (needs_switch)
8354+
io_rsrc_node_switch(ctx, ctx->file_data);
83248355
io_ring_submit_unlock(ctx, !force_nonblock);
83258356
if (ret)
83268357
fput(file);
83278358
return ret;
83288359
}
83298360

8330-
static int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
8331-
struct io_rsrc_node *node, void *rsrc)
8332-
{
8333-
struct io_rsrc_put *prsrc;
8334-
8335-
prsrc = kzalloc(sizeof(*prsrc), GFP_KERNEL);
8336-
if (!prsrc)
8337-
return -ENOMEM;
8338-
8339-
prsrc->tag = *io_get_tag_slot(data, idx);
8340-
prsrc->rsrc = rsrc;
8341-
list_add(&prsrc->list, &node->rsrc_list);
8342-
return 0;
8343-
}
8344-
83458361
static int __io_sqe_files_update(struct io_ring_ctx *ctx,
83468362
struct io_uring_rsrc_update2 *up,
83478363
unsigned nr_args)

0 commit comments

Comments
 (0)