Loading fs/io_uring.c +63 −6 Original line number Diff line number Diff line Loading @@ -707,6 +707,11 @@ static const struct io_op_def io_op_defs[] = { .needs_file = 1, .unbound_nonreg_file = 1, }, { /* IORING_OP_OPENAT2 */ .needs_file = 1, .fd_non_neg = 1, }, }; static void io_wq_submit_work(struct io_wq_work **workptr); Loading Loading @@ -2487,11 +2492,46 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return 0; } static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct open_how __user *how; const char __user *fname; size_t len; int ret; if (sqe->ioprio || sqe->buf_index) return -EINVAL; req->open.dfd = READ_ONCE(sqe->fd); fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); how = u64_to_user_ptr(READ_ONCE(sqe->addr2)); len = READ_ONCE(sqe->len); if (len < OPEN_HOW_SIZE_VER0) return -EINVAL; ret = copy_struct_from_user(&req->open.how, sizeof(req->open.how), how, len); if (ret) return ret; if (!(req->open.how.flags & O_PATH) && force_o_largefile()) req->open.how.flags |= O_LARGEFILE; req->open.filename = getname(fname); if (IS_ERR(req->open.filename)) { ret = PTR_ERR(req->open.filename); req->open.filename = NULL; return ret; } return 0; } static int io_openat2(struct io_kiocb *req, struct io_kiocb **nxt, bool force_nonblock) { struct open_flags op; struct open_how how; struct file *file; int ret; Loading @@ -2500,12 +2540,11 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, return -EAGAIN; } how = build_open_how(req->open.how.flags, req->open.how.mode); ret = build_open_flags(&how, &op); ret = build_open_flags(&req->open.how, &op); if (ret) goto err; ret = get_unused_fd_flags(how.flags); ret = get_unused_fd_flags(req->open.how.flags); if (ret < 0) goto err; Loading @@ -2526,6 +2565,13 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, return 0; } static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, bool force_nonblock) { req->open.how = build_open_how(req->open.how.flags, req->open.how.mode); return io_openat2(req, nxt, force_nonblock); } static int io_madvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { #if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU) Loading Loading @@ -3984,6 +4030,9 @@ static int io_req_defer_prep(struct io_kiocb *req, case IORING_OP_MADVISE: ret = io_madvise_prep(req, sqe); break; case IORING_OP_OPENAT2: ret = io_openat2_prep(req, sqe); break; default: printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", req->opcode); Loading Loading @@ -4204,6 +4253,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, } ret = io_madvise(req, nxt, force_nonblock); break; case IORING_OP_OPENAT2: if (sqe) { ret = io_openat2_prep(req, sqe); if (ret) break; } ret = io_openat2(req, nxt, force_nonblock); break; default: ret = -EINVAL; break; Loading include/uapi/linux/io_uring.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ enum { IORING_OP_MADVISE, IORING_OP_SEND, IORING_OP_RECV, IORING_OP_OPENAT2, /* this goes last, obviously */ IORING_OP_LAST, Loading Loading
fs/io_uring.c +63 −6 Original line number Diff line number Diff line Loading @@ -707,6 +707,11 @@ static const struct io_op_def io_op_defs[] = { .needs_file = 1, .unbound_nonreg_file = 1, }, { /* IORING_OP_OPENAT2 */ .needs_file = 1, .fd_non_neg = 1, }, }; static void io_wq_submit_work(struct io_wq_work **workptr); Loading Loading @@ -2487,11 +2492,46 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return 0; } static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct open_how __user *how; const char __user *fname; size_t len; int ret; if (sqe->ioprio || sqe->buf_index) return -EINVAL; req->open.dfd = READ_ONCE(sqe->fd); fname = u64_to_user_ptr(READ_ONCE(sqe->addr)); how = u64_to_user_ptr(READ_ONCE(sqe->addr2)); len = READ_ONCE(sqe->len); if (len < OPEN_HOW_SIZE_VER0) return -EINVAL; ret = copy_struct_from_user(&req->open.how, sizeof(req->open.how), how, len); if (ret) return ret; if (!(req->open.how.flags & O_PATH) && force_o_largefile()) req->open.how.flags |= O_LARGEFILE; req->open.filename = getname(fname); if (IS_ERR(req->open.filename)) { ret = PTR_ERR(req->open.filename); req->open.filename = NULL; return ret; } return 0; } static int io_openat2(struct io_kiocb *req, struct io_kiocb **nxt, bool force_nonblock) { struct open_flags op; struct open_how how; struct file *file; int ret; Loading @@ -2500,12 +2540,11 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, return -EAGAIN; } how = build_open_how(req->open.how.flags, req->open.how.mode); ret = build_open_flags(&how, &op); ret = build_open_flags(&req->open.how, &op); if (ret) goto err; ret = get_unused_fd_flags(how.flags); ret = get_unused_fd_flags(req->open.how.flags); if (ret < 0) goto err; Loading @@ -2526,6 +2565,13 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, return 0; } static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, bool force_nonblock) { req->open.how = build_open_how(req->open.how.flags, req->open.how.mode); return io_openat2(req, nxt, force_nonblock); } static int io_madvise_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { #if defined(CONFIG_ADVISE_SYSCALLS) && defined(CONFIG_MMU) Loading Loading @@ -3984,6 +4030,9 @@ static int io_req_defer_prep(struct io_kiocb *req, case IORING_OP_MADVISE: ret = io_madvise_prep(req, sqe); break; case IORING_OP_OPENAT2: ret = io_openat2_prep(req, sqe); break; default: printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n", req->opcode); Loading Loading @@ -4204,6 +4253,14 @@ static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe, } ret = io_madvise(req, nxt, force_nonblock); break; case IORING_OP_OPENAT2: if (sqe) { ret = io_openat2_prep(req, sqe); if (ret) break; } ret = io_openat2(req, nxt, force_nonblock); break; default: ret = -EINVAL; break; Loading
include/uapi/linux/io_uring.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ enum { IORING_OP_MADVISE, IORING_OP_SEND, IORING_OP_RECV, IORING_OP_OPENAT2, /* this goes last, obviously */ IORING_OP_LAST, Loading