Skip to content

Commit 7df778b

Browse files
isilenceaxboe
authored andcommitted
io_uring: make OP_CLOSE consistent with direct open
From recently open/accept are now able to manipulate fixed file table, but it's inconsistent that close can't. Close the gap, keep API same as with open/accept, i.e. via sqe->file_slot. Signed-off-by: Pavel Begunkov <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 9f3a2cb commit 7df778b

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

fs/io_uring.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ struct io_poll_update {
502502
struct io_close {
503503
struct file *file;
504504
int fd;
505+
u32 file_slot;
505506
};
506507

507508
struct io_timeout_data {
@@ -1098,6 +1099,8 @@ static int io_req_prep_async(struct io_kiocb *req);
10981099

10991100
static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
11001101
unsigned int issue_flags, u32 slot_index);
1102+
static int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags);
1103+
11011104
static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer);
11021105

11031106
static struct kmem_cache *req_cachep;
@@ -4591,12 +4594,16 @@ static int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
45914594
if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
45924595
return -EINVAL;
45934596
if (sqe->ioprio || sqe->off || sqe->addr || sqe->len ||
4594-
sqe->rw_flags || sqe->buf_index || sqe->splice_fd_in)
4597+
sqe->rw_flags || sqe->buf_index)
45954598
return -EINVAL;
45964599
if (req->flags & REQ_F_FIXED_FILE)
45974600
return -EBADF;
45984601

45994602
req->close.fd = READ_ONCE(sqe->fd);
4603+
req->close.file_slot = READ_ONCE(sqe->file_index);
4604+
if (req->close.file_slot && req->close.fd)
4605+
return -EINVAL;
4606+
46004607
return 0;
46014608
}
46024609

@@ -4608,6 +4615,11 @@ static int io_close(struct io_kiocb *req, unsigned int issue_flags)
46084615
struct file *file = NULL;
46094616
int ret = -EBADF;
46104617

4618+
if (req->close.file_slot) {
4619+
ret = io_close_fixed(req, issue_flags);
4620+
goto err;
4621+
}
4622+
46114623
spin_lock(&files->file_lock);
46124624
fdt = files_fdtable(files);
46134625
if (close->fd >= fdt->max_fds) {
@@ -8401,6 +8413,44 @@ static int io_install_fixed_file(struct io_kiocb *req, struct file *file,
84018413
return ret;
84028414
}
84038415

8416+
static int io_close_fixed(struct io_kiocb *req, unsigned int issue_flags)
8417+
{
8418+
unsigned int offset = req->close.file_slot - 1;
8419+
struct io_ring_ctx *ctx = req->ctx;
8420+
struct io_fixed_file *file_slot;
8421+
struct file *file;
8422+
int ret, i;
8423+
8424+
io_ring_submit_lock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));
8425+
ret = -ENXIO;
8426+
if (unlikely(!ctx->file_data))
8427+
goto out;
8428+
ret = -EINVAL;
8429+
if (offset >= ctx->nr_user_files)
8430+
goto out;
8431+
ret = io_rsrc_node_switch_start(ctx);
8432+
if (ret)
8433+
goto out;
8434+
8435+
i = array_index_nospec(offset, ctx->nr_user_files);
8436+
file_slot = io_fixed_file_slot(&ctx->file_table, i);
8437+
ret = -EBADF;
8438+
if (!file_slot->file_ptr)
8439+
goto out;
8440+
8441+
file = (struct file *)(file_slot->file_ptr & FFS_MASK);
8442+
ret = io_queue_rsrc_removal(ctx->file_data, offset, ctx->rsrc_node, file);
8443+
if (ret)
8444+
goto out;
8445+
8446+
file_slot->file_ptr = 0;
8447+
io_rsrc_node_switch(ctx, ctx->file_data);
8448+
ret = 0;
8449+
out:
8450+
io_ring_submit_unlock(ctx, !(issue_flags & IO_URING_F_NONBLOCK));
8451+
return ret;
8452+
}
8453+
84048454
static int __io_sqe_files_update(struct io_ring_ctx *ctx,
84058455
struct io_uring_rsrc_update2 *up,
84068456
unsigned nr_args)

0 commit comments

Comments
 (0)