Skip to content

Commit 1339f24

Browse files
committed
io_uring: allow allocated fixed files for openat/openat2
If the application passes in IORING_FILE_INDEX_ALLOC as the file_slot, then that's a hint to allocate a fixed file descriptor rather than have one be passed in directly. This can be useful for having io_uring manage the direct descriptor space. Normal open direct requests will complete with 0 for success, and < 0 in case of error. If io_uring is asked to allocated the direct descriptor, then the direct descriptor is returned in case of success. Reviewed-by: Hao Xu <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent b70b8e3 commit 1339f24

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

fs/io_uring.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4697,7 +4697,7 @@ static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
46974697
return __io_openat_prep(req, sqe);
46984698
}
46994699

4700-
static int __maybe_unused io_file_bitmap_get(struct io_ring_ctx *ctx)
4700+
static int io_file_bitmap_get(struct io_ring_ctx *ctx)
47014701
{
47024702
struct io_file_table *table = &ctx->file_table;
47034703
unsigned long nr = ctx->nr_user_files;
@@ -4722,6 +4722,36 @@ static int __maybe_unused io_file_bitmap_get(struct io_ring_ctx *ctx)
47224722
return -ENFILE;
47234723
}
47244724

4725+
static int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags,
4726+
struct file *file, unsigned int file_slot)
4727+
{
4728+
bool alloc_slot = file_slot == IORING_FILE_INDEX_ALLOC;
4729+
struct io_ring_ctx *ctx = req->ctx;
4730+
int ret;
4731+
4732+
if (alloc_slot) {
4733+
io_ring_submit_lock(ctx, issue_flags);
4734+
ret = io_file_bitmap_get(ctx);
4735+
if (unlikely(ret < 0)) {
4736+
io_ring_submit_unlock(ctx, issue_flags);
4737+
return ret;
4738+
}
4739+
4740+
file_slot = ret;
4741+
} else {
4742+
file_slot--;
4743+
}
4744+
4745+
ret = io_install_fixed_file(req, file, issue_flags, file_slot);
4746+
if (alloc_slot) {
4747+
io_ring_submit_unlock(ctx, issue_flags);
4748+
if (!ret)
4749+
return file_slot;
4750+
}
4751+
4752+
return ret;
4753+
}
4754+
47254755
static int io_openat2(struct io_kiocb *req, unsigned int issue_flags)
47264756
{
47274757
struct open_flags op;
@@ -4777,8 +4807,8 @@ static int io_openat2(struct io_kiocb *req, unsigned int issue_flags)
47774807
if (!fixed)
47784808
fd_install(ret, file);
47794809
else
4780-
ret = io_install_fixed_file(req, file, issue_flags,
4781-
req->open.file_slot - 1);
4810+
ret = io_fixed_fd_install(req, issue_flags, file,
4811+
req->open.file_slot);
47824812
err:
47834813
putname(req->open.filename);
47844814
req->flags &= ~REQ_F_NEED_CLEANUP;

include/uapi/linux/io_uring.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ struct io_uring_sqe {
6363
__u64 __pad2[2];
6464
};
6565

66+
/*
67+
* If sqe->file_index is set to this for opcodes that instantiate a new
68+
* direct descriptor (like openat/openat2/accept), then io_uring will allocate
69+
* an available direct descriptor instead of having the application pass one
70+
* in. The picked direct descriptor will be returned in cqe->res, or -ENFILE
71+
* if the space is full.
72+
*/
73+
#define IORING_FILE_INDEX_ALLOC (~0U)
74+
6675
enum {
6776
IOSQE_FIXED_FILE_BIT,
6877
IOSQE_IO_DRAIN_BIT,

0 commit comments

Comments
 (0)