Commit 0aa69d53 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.5/io_uring-2023-06-23' of git://git.kernel.dk/linux

Pull io_uring updates from Jens Axboe:
 "Nothing major in this release, just a bunch of cleanups and some
  optimizations around networking mostly.

   - clean up file request flags handling (Christoph)

   - clean up request freeing and CQ locking (Pavel)

   - support for using pre-registering the io_uring fd at setup time
     (Josh)

   - Add support for user allocated ring memory, rather than having the
     kernel allocate it. Mostly for packing rings into a huge page (me)

   - avoid an unnecessary double retry on receive (me)

   - maintain ordering for task_work, which also improves performance
     (me)

   - misc cleanups/fixes (Pavel, me)"

* tag 'for-6.5/io_uring-2023-06-23' of git://git.kernel.dk/linux: (39 commits)
  io_uring: merge conditional unlock flush helpers
  io_uring: make io_cq_unlock_post static
  io_uring: inline __io_cq_unlock
  io_uring: fix acquire/release annotations
  io_uring: kill io_cq_unlock()
  io_uring: remove IOU_F_TWQ_FORCE_NORMAL
  io_uring: don't batch task put on reqs free
  io_uring: move io_clean_op()
  io_uring: inline io_dismantle_req()
  io_uring: remove io_free_req_tw
  io_uring: open code io_put_req_find_next
  io_uring: add helpers to decode the fixed file file_ptr
  io_uring: use io_file_from_index in io_msg_grab_file
  io_uring: use io_file_from_index in __io_sync_cancel
  io_uring: return REQ_F_ flags from io_file_get_flags
  io_uring: remove io_req_ffs_set
  io_uring: remove a confusing comment above io_file_get_flags
  io_uring: remove the mode variable in io_file_get_flags
  io_uring: remove __io_file_supports_nowait
  io_uring: wait interruptibly for request completions on exit
  ...
parents 3eccc0c8 c98c81a4
...@@ -481,7 +481,7 @@ static int blkdev_open(struct inode *inode, struct file *filp) ...@@ -481,7 +481,7 @@ static int blkdev_open(struct inode *inode, struct file *filp)
* during an unstable branch. * during an unstable branch.
*/ */
filp->f_flags |= O_LARGEFILE; filp->f_flags |= O_LARGEFILE;
filp->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC; filp->f_mode |= FMODE_BUF_RASYNC;
if (filp->f_flags & O_NDELAY) if (filp->f_flags & O_NDELAY)
filp->f_mode |= FMODE_NDELAY; filp->f_mode |= FMODE_NDELAY;
...@@ -494,6 +494,9 @@ static int blkdev_open(struct inode *inode, struct file *filp) ...@@ -494,6 +494,9 @@ static int blkdev_open(struct inode *inode, struct file *filp)
if (IS_ERR(bdev)) if (IS_ERR(bdev))
return PTR_ERR(bdev); return PTR_ERR(bdev);
if (bdev_nowait(bdev))
filp->f_mode |= FMODE_NOWAIT;
filp->private_data = bdev; filp->private_data = bdev;
filp->f_mapping = bdev->bd_inode->i_mapping; filp->f_mapping = bdev->bd_inode->i_mapping;
filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping); filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
......
...@@ -521,7 +521,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req, ...@@ -521,7 +521,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
if (cookie != NULL && blk_rq_is_poll(req)) if (cookie != NULL && blk_rq_is_poll(req))
nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED); nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED);
else else
io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb); io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
return RQ_END_IO_FREE; return RQ_END_IO_FREE;
} }
...@@ -543,7 +543,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req, ...@@ -543,7 +543,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
if (cookie != NULL && blk_rq_is_poll(req)) if (cookie != NULL && blk_rq_is_poll(req))
nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED); nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED);
else else
io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_meta_cb); io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_meta_cb);
return RQ_END_IO_NONE; return RQ_END_IO_NONE;
} }
......
...@@ -46,13 +46,23 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw, ...@@ -46,13 +46,23 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
struct iov_iter *iter, void *ioucmd); struct iov_iter *iter, void *ioucmd);
void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2, void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2,
unsigned issue_flags); unsigned issue_flags);
void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned));
struct sock *io_uring_get_socket(struct file *file); struct sock *io_uring_get_socket(struct file *file);
void __io_uring_cancel(bool cancel_all); void __io_uring_cancel(bool cancel_all);
void __io_uring_free(struct task_struct *tsk); void __io_uring_free(struct task_struct *tsk);
void io_uring_unreg_ringfd(void); void io_uring_unreg_ringfd(void);
const char *io_uring_get_opcode(u8 opcode); const char *io_uring_get_opcode(u8 opcode);
void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned),
unsigned flags);
/* users should follow semantics of IOU_F_TWQ_LAZY_WAKE */
void io_uring_cmd_do_in_task_lazy(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned));
static inline void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned))
{
__io_uring_cmd_do_in_task(ioucmd, task_work_cb, 0);
}
static inline void io_uring_files_cancel(void) static inline void io_uring_files_cancel(void)
{ {
...@@ -85,6 +95,10 @@ static inline void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd, ...@@ -85,6 +95,10 @@ static inline void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned)) void (*task_work_cb)(struct io_uring_cmd *, unsigned))
{ {
} }
static inline void io_uring_cmd_do_in_task_lazy(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned))
{
}
static inline struct sock *io_uring_get_socket(struct file *file) static inline struct sock *io_uring_get_socket(struct file *file)
{ {
return NULL; return NULL;
......
...@@ -211,6 +211,16 @@ struct io_ring_ctx { ...@@ -211,6 +211,16 @@ struct io_ring_ctx {
unsigned int compat: 1; unsigned int compat: 1;
enum task_work_notify_mode notify_method; enum task_work_notify_mode notify_method;
/*
* If IORING_SETUP_NO_MMAP is used, then the below holds
* the gup'ed pages for the two rings, and the sqes.
*/
unsigned short n_ring_pages;
unsigned short n_sqe_pages;
struct page **ring_pages;
struct page **sqe_pages;
struct io_rings *rings; struct io_rings *rings;
struct task_struct *submitter_task; struct task_struct *submitter_task;
struct percpu_ref refs; struct percpu_ref refs;
......
...@@ -173,6 +173,18 @@ enum { ...@@ -173,6 +173,18 @@ enum {
*/ */
#define IORING_SETUP_DEFER_TASKRUN (1U << 13) #define IORING_SETUP_DEFER_TASKRUN (1U << 13)
/*
* Application provides the memory for the rings
*/
#define IORING_SETUP_NO_MMAP (1U << 14)
/*
* Register the ring fd in itself for use with
* IORING_REGISTER_USE_REGISTERED_RING; return a registered fd index rather
* than an fd.
*/
#define IORING_SETUP_REGISTERED_FD_ONLY (1U << 15)
enum io_uring_op { enum io_uring_op {
IORING_OP_NOP, IORING_OP_NOP,
IORING_OP_READV, IORING_OP_READV,
...@@ -406,7 +418,7 @@ struct io_sqring_offsets { ...@@ -406,7 +418,7 @@ struct io_sqring_offsets {
__u32 dropped; __u32 dropped;
__u32 array; __u32 array;
__u32 resv1; __u32 resv1;
__u64 resv2; __u64 user_addr;
}; };
/* /*
...@@ -425,7 +437,7 @@ struct io_cqring_offsets { ...@@ -425,7 +437,7 @@ struct io_cqring_offsets {
__u32 cqes; __u32 cqes;
__u32 flags; __u32 flags;
__u32 resv1; __u32 resv1;
__u64 resv2; __u64 user_addr;
}; };
/* /*
......
...@@ -216,13 +216,10 @@ static int __io_sync_cancel(struct io_uring_task *tctx, ...@@ -216,13 +216,10 @@ static int __io_sync_cancel(struct io_uring_task *tctx,
/* fixed must be grabbed every time since we drop the uring_lock */ /* fixed must be grabbed every time since we drop the uring_lock */
if ((cd->flags & IORING_ASYNC_CANCEL_FD) && if ((cd->flags & IORING_ASYNC_CANCEL_FD) &&
(cd->flags & IORING_ASYNC_CANCEL_FD_FIXED)) { (cd->flags & IORING_ASYNC_CANCEL_FD_FIXED)) {
unsigned long file_ptr;
if (unlikely(fd >= ctx->nr_user_files)) if (unlikely(fd >= ctx->nr_user_files))
return -EBADF; return -EBADF;
fd = array_index_nospec(fd, ctx->nr_user_files); fd = array_index_nospec(fd, ctx->nr_user_files);
file_ptr = io_fixed_file_slot(&ctx->file_table, fd)->file_ptr; cd->file = io_file_from_index(&ctx->file_table, fd);
cd->file = (struct file *) (file_ptr & FFS_MASK);
if (!cd->file) if (!cd->file)
return -EBADF; return -EBADF;
} }
......
...@@ -78,10 +78,8 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file, ...@@ -78,10 +78,8 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
file_slot = io_fixed_file_slot(&ctx->file_table, slot_index); file_slot = io_fixed_file_slot(&ctx->file_table, slot_index);
if (file_slot->file_ptr) { if (file_slot->file_ptr) {
struct file *old_file; ret = io_queue_rsrc_removal(ctx->file_data, slot_index,
io_slot_file(file_slot));
old_file = (struct file *)(file_slot->file_ptr & FFS_MASK);
ret = io_queue_rsrc_removal(ctx->file_data, slot_index, old_file);
if (ret) if (ret)
return ret; return ret;
...@@ -140,7 +138,6 @@ int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags, ...@@ -140,7 +138,6 @@ int io_fixed_fd_install(struct io_kiocb *req, unsigned int issue_flags,
int io_fixed_fd_remove(struct io_ring_ctx *ctx, unsigned int offset) int io_fixed_fd_remove(struct io_ring_ctx *ctx, unsigned int offset)
{ {
struct io_fixed_file *file_slot; struct io_fixed_file *file_slot;
struct file *file;
int ret; int ret;
if (unlikely(!ctx->file_data)) if (unlikely(!ctx->file_data))
...@@ -153,8 +150,8 @@ int io_fixed_fd_remove(struct io_ring_ctx *ctx, unsigned int offset) ...@@ -153,8 +150,8 @@ int io_fixed_fd_remove(struct io_ring_ctx *ctx, unsigned int offset)
if (!file_slot->file_ptr) if (!file_slot->file_ptr)
return -EBADF; return -EBADF;
file = (struct file *)(file_slot->file_ptr & FFS_MASK); ret = io_queue_rsrc_removal(ctx->file_data, offset,
ret = io_queue_rsrc_removal(ctx->file_data, offset, file); io_slot_file(file_slot));
if (ret) if (ret)
return ret; return ret;
......
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/io_uring_types.h> #include <linux/io_uring_types.h>
#define FFS_NOWAIT 0x1UL
#define FFS_ISREG 0x2UL
#define FFS_MASK ~(FFS_NOWAIT|FFS_ISREG)
bool io_alloc_file_tables(struct io_file_table *table, unsigned nr_files); bool io_alloc_file_tables(struct io_file_table *table, unsigned nr_files);
void io_free_file_tables(struct io_file_table *table); void io_free_file_tables(struct io_file_table *table);
...@@ -43,21 +39,31 @@ io_fixed_file_slot(struct io_file_table *table, unsigned i) ...@@ -43,21 +39,31 @@ io_fixed_file_slot(struct io_file_table *table, unsigned i)
return &table->files[i]; return &table->files[i];
} }
#define FFS_NOWAIT 0x1UL
#define FFS_ISREG 0x2UL
#define FFS_MASK ~(FFS_NOWAIT|FFS_ISREG)
static inline unsigned int io_slot_flags(struct io_fixed_file *slot)
{
return (slot->file_ptr & ~FFS_MASK) << REQ_F_SUPPORT_NOWAIT_BIT;
}
static inline struct file *io_slot_file(struct io_fixed_file *slot)
{
return (struct file *)(slot->file_ptr & FFS_MASK);
}
static inline struct file *io_file_from_index(struct io_file_table *table, static inline struct file *io_file_from_index(struct io_file_table *table,
int index) int index)
{ {
struct io_fixed_file *slot = io_fixed_file_slot(table, index); return io_slot_file(io_fixed_file_slot(table, index));
return (struct file *) (slot->file_ptr & FFS_MASK);
} }
static inline void io_fixed_file_set(struct io_fixed_file *file_slot, static inline void io_fixed_file_set(struct io_fixed_file *file_slot,
struct file *file) struct file *file)
{ {
unsigned long file_ptr = (unsigned long) file; file_slot->file_ptr = (unsigned long)file |
(io_file_get_flags(file) >> REQ_F_SUPPORT_NOWAIT_BIT);
file_ptr |= io_file_get_flags(file);
file_slot->file_ptr = file_ptr;
} }
static inline void io_reset_alloc_hint(struct io_ring_ctx *ctx) static inline void io_reset_alloc_hint(struct io_ring_ctx *ctx)
......
This diff is collapsed.
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
#endif #endif
enum { enum {
/* don't use deferred task_work */
IOU_F_TWQ_FORCE_NORMAL = 1,
/* /*
* A hint to not wake right away but delay until there are enough of * A hint to not wake right away but delay until there are enough of
* tw's queued to match the number of CQEs the task is waiting for. * tw's queued to match the number of CQEs the task is waiting for.
...@@ -26,7 +23,7 @@ enum { ...@@ -26,7 +23,7 @@ enum {
* Must not be used wirh requests generating more than one CQE. * Must not be used wirh requests generating more than one CQE.
* It's also ignored unless IORING_SETUP_DEFER_TASKRUN is set. * It's also ignored unless IORING_SETUP_DEFER_TASKRUN is set.
*/ */
IOU_F_TWQ_LAZY_WAKE = 2, IOU_F_TWQ_LAZY_WAKE = 1,
}; };
enum { enum {
...@@ -47,7 +44,7 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx); ...@@ -47,7 +44,7 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx);
void io_req_defer_failed(struct io_kiocb *req, s32 res); void io_req_defer_failed(struct io_kiocb *req, s32 res);
void io_req_complete_post(struct io_kiocb *req, unsigned issue_flags); void io_req_complete_post(struct io_kiocb *req, unsigned issue_flags);
bool io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags); bool io_post_aux_cqe(struct io_ring_ctx *ctx, u64 user_data, s32 res, u32 cflags);
bool io_aux_cqe(struct io_ring_ctx *ctx, bool defer, u64 user_data, s32 res, u32 cflags, bool io_aux_cqe(const struct io_kiocb *req, bool defer, s32 res, u32 cflags,
bool allow_overflow); bool allow_overflow);
void __io_commit_cqring_flush(struct io_ring_ctx *ctx); void __io_commit_cqring_flush(struct io_ring_ctx *ctx);
...@@ -57,11 +54,6 @@ struct file *io_file_get_normal(struct io_kiocb *req, int fd); ...@@ -57,11 +54,6 @@ struct file *io_file_get_normal(struct io_kiocb *req, int fd);
struct file *io_file_get_fixed(struct io_kiocb *req, int fd, struct file *io_file_get_fixed(struct io_kiocb *req, int fd,
unsigned issue_flags); unsigned issue_flags);
static inline bool io_req_ffs_set(struct io_kiocb *req)
{
return req->flags & REQ_F_FIXED_FILE;
}
void __io_req_task_work_add(struct io_kiocb *req, unsigned flags); void __io_req_task_work_add(struct io_kiocb *req, unsigned flags);
bool io_is_uring_fops(struct file *file); bool io_is_uring_fops(struct file *file);
bool io_alloc_async_data(struct io_kiocb *req); bool io_alloc_async_data(struct io_kiocb *req);
...@@ -75,6 +67,9 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd); ...@@ -75,6 +67,9 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd);
int io_uring_alloc_task_context(struct task_struct *task, int io_uring_alloc_task_context(struct task_struct *task,
struct io_ring_ctx *ctx); struct io_ring_ctx *ctx);
int io_ring_add_registered_file(struct io_uring_task *tctx, struct file *file,
int start, int end);
int io_poll_issue(struct io_kiocb *req, struct io_tw_state *ts); int io_poll_issue(struct io_kiocb *req, struct io_tw_state *ts);
int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr); int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr);
int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin); int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin);
...@@ -115,8 +110,6 @@ static inline void io_req_task_work_add(struct io_kiocb *req) ...@@ -115,8 +110,6 @@ static inline void io_req_task_work_add(struct io_kiocb *req)
#define io_for_each_link(pos, head) \ #define io_for_each_link(pos, head) \
for (pos = (head); pos; pos = pos->link) for (pos = (head); pos; pos = pos->link)
void io_cq_unlock_post(struct io_ring_ctx *ctx);
static inline struct io_uring_cqe *io_get_cqe_overflow(struct io_ring_ctx *ctx, static inline struct io_uring_cqe *io_get_cqe_overflow(struct io_ring_ctx *ctx,
bool overflow) bool overflow)
{ {
......
...@@ -162,14 +162,12 @@ static struct file *io_msg_grab_file(struct io_kiocb *req, unsigned int issue_fl ...@@ -162,14 +162,12 @@ static struct file *io_msg_grab_file(struct io_kiocb *req, unsigned int issue_fl
struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg); struct io_msg *msg = io_kiocb_to_cmd(req, struct io_msg);
struct io_ring_ctx *ctx = req->ctx; struct io_ring_ctx *ctx = req->ctx;
struct file *file = NULL; struct file *file = NULL;
unsigned long file_ptr;
int idx = msg->src_fd; int idx = msg->src_fd;
io_ring_submit_lock(ctx, issue_flags); io_ring_submit_lock(ctx, issue_flags);
if (likely(idx < ctx->nr_user_files)) { if (likely(idx < ctx->nr_user_files)) {
idx = array_index_nospec(idx, ctx->nr_user_files); idx = array_index_nospec(idx, ctx->nr_user_files);
file_ptr = io_fixed_file_slot(&ctx->file_table, idx)->file_ptr; file = io_file_from_index(&ctx->file_table, idx);
file = (struct file *) (file_ptr & FFS_MASK);
if (file) if (file)
get_file(file); get_file(file);
} }
......
...@@ -624,9 +624,15 @@ static inline void io_recv_prep_retry(struct io_kiocb *req) ...@@ -624,9 +624,15 @@ static inline void io_recv_prep_retry(struct io_kiocb *req)
* again (for multishot). * again (for multishot).
*/ */
static inline bool io_recv_finish(struct io_kiocb *req, int *ret, static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
unsigned int cflags, bool mshot_finished, struct msghdr *msg, bool mshot_finished,
unsigned issue_flags) unsigned issue_flags)
{ {
unsigned int cflags;
cflags = io_put_kbuf(req, issue_flags);
if (msg->msg_inq && msg->msg_inq != -1U)
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
if (!(req->flags & REQ_F_APOLL_MULTISHOT)) { if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
io_req_set_res(req, *ret, cflags); io_req_set_res(req, *ret, cflags);
*ret = IOU_OK; *ret = IOU_OK;
...@@ -634,10 +640,18 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret, ...@@ -634,10 +640,18 @@ static inline bool io_recv_finish(struct io_kiocb *req, int *ret,
} }
if (!mshot_finished) { if (!mshot_finished) {
if (io_aux_cqe(req->ctx, issue_flags & IO_URING_F_COMPLETE_DEFER, if (io_aux_cqe(req, issue_flags & IO_URING_F_COMPLETE_DEFER,
req->cqe.user_data, *ret, cflags | IORING_CQE_F_MORE, true)) { *ret, cflags | IORING_CQE_F_MORE, true)) {
io_recv_prep_retry(req); io_recv_prep_retry(req);
/* Known not-empty or unknown state, retry */
if (cflags & IORING_CQE_F_SOCK_NONEMPTY ||
msg->msg_inq == -1U)
return false; return false;
if (issue_flags & IO_URING_F_MULTISHOT)
*ret = IOU_ISSUE_SKIP_COMPLETE;
else
*ret = -EAGAIN;
return true;
} }
/* Otherwise stop multishot but use the current result. */ /* Otherwise stop multishot but use the current result. */
} }
...@@ -740,7 +754,6 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags) ...@@ -740,7 +754,6 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
struct io_async_msghdr iomsg, *kmsg; struct io_async_msghdr iomsg, *kmsg;
struct socket *sock; struct socket *sock;
unsigned int cflags;
unsigned flags; unsigned flags;
int ret, min_ret = 0; int ret, min_ret = 0;
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
...@@ -791,6 +804,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags) ...@@ -791,6 +804,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
flags |= MSG_DONTWAIT; flags |= MSG_DONTWAIT;
kmsg->msg.msg_get_inq = 1; kmsg->msg.msg_get_inq = 1;
kmsg->msg.msg_inq = -1U;
if (req->flags & REQ_F_APOLL_MULTISHOT) { if (req->flags & REQ_F_APOLL_MULTISHOT) {
ret = io_recvmsg_multishot(sock, sr, kmsg, flags, ret = io_recvmsg_multishot(sock, sr, kmsg, flags,
&mshot_finished); &mshot_finished);
...@@ -831,11 +845,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags) ...@@ -831,11 +845,7 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
else else
io_kbuf_recycle(req, issue_flags); io_kbuf_recycle(req, issue_flags);
cflags = io_put_kbuf(req, issue_flags); if (!io_recv_finish(req, &ret, &kmsg->msg, mshot_finished, issue_flags))
if (kmsg->msg.msg_inq)
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
if (!io_recv_finish(req, &ret, cflags, mshot_finished, issue_flags))
goto retry_multishot; goto retry_multishot;
if (mshot_finished) { if (mshot_finished) {
...@@ -854,7 +864,6 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags) ...@@ -854,7 +864,6 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
struct msghdr msg; struct msghdr msg;
struct socket *sock; struct socket *sock;
unsigned int cflags;
unsigned flags; unsigned flags;
int ret, min_ret = 0; int ret, min_ret = 0;
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
...@@ -871,6 +880,14 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags) ...@@ -871,6 +880,14 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
if (unlikely(!sock)) if (unlikely(!sock))
return -ENOTSOCK; return -ENOTSOCK;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_get_inq = 1;
msg.msg_controllen = 0;
msg.msg_iocb = NULL;
msg.msg_ubuf = NULL;
retry_multishot: retry_multishot:
if (io_do_buffer_select(req)) { if (io_do_buffer_select(req)) {
void __user *buf; void __user *buf;
...@@ -885,14 +902,8 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags) ...@@ -885,14 +902,8 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
if (unlikely(ret)) if (unlikely(ret))
goto out_free; goto out_free;
msg.msg_name = NULL; msg.msg_inq = -1U;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_get_inq = 1;
msg.msg_flags = 0; msg.msg_flags = 0;
msg.msg_controllen = 0;
msg.msg_iocb = NULL;
msg.msg_ubuf = NULL;
flags = sr->msg_flags; flags = sr->msg_flags;
if (force_nonblock) if (force_nonblock)
...@@ -932,11 +943,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags) ...@@ -932,11 +943,7 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
else else
io_kbuf_recycle(req, issue_flags); io_kbuf_recycle(req, issue_flags);
cflags = io_put_kbuf(req, issue_flags); if (!io_recv_finish(req, &ret, &msg, ret <= 0, issue_flags))
if (msg.msg_inq)
cflags |= IORING_CQE_F_SOCK_NONEMPTY;
if (!io_recv_finish(req, &ret, cflags, ret <= 0, issue_flags))
goto retry_multishot; goto retry_multishot;
return ret; return ret;
...@@ -1308,7 +1315,6 @@ int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) ...@@ -1308,7 +1315,6 @@ int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
int io_accept(struct io_kiocb *req, unsigned int issue_flags) int io_accept(struct io_kiocb *req, unsigned int issue_flags)
{ {
struct io_ring_ctx *ctx = req->ctx;
struct io_accept *accept = io_kiocb_to_cmd(req, struct io_accept); struct io_accept *accept = io_kiocb_to_cmd(req, struct io_accept);
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0; unsigned int file_flags = force_nonblock ? O_NONBLOCK : 0;
...@@ -1358,8 +1364,8 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags) ...@@ -1358,8 +1364,8 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (io_aux_cqe(ctx, issue_flags & IO_URING_F_COMPLETE_DEFER, if (io_aux_cqe(req, issue_flags & IO_URING_F_COMPLETE_DEFER, ret,
req->cqe.user_data, ret, IORING_CQE_F_MORE, true)) IORING_CQE_F_MORE, true))
goto retry; goto retry;
return -ECANCELED; return -ECANCELED;
......
...@@ -300,8 +300,8 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts) ...@@ -300,8 +300,8 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts)
__poll_t mask = mangle_poll(req->cqe.res & __poll_t mask = mangle_poll(req->cqe.res &
req->apoll_events); req->apoll_events);
if (!io_aux_cqe(req->ctx, ts->locked, req->cqe.user_data, if (!io_aux_cqe(req, ts->locked, mask,
mask, IORING_CQE_F_MORE, false)) { IORING_CQE_F_MORE, false)) {
io_req_set_res(req, mask, 0); io_req_set_res(req, mask, 0);
return IOU_POLL_REMOVE_POLL_USE_RES; return IOU_POLL_REMOVE_POLL_USE_RES;
} }
...@@ -326,7 +326,7 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts) ...@@ -326,7 +326,7 @@ static int io_poll_check_events(struct io_kiocb *req, struct io_tw_state *ts)
return IOU_POLL_NO_ACTION; return IOU_POLL_NO_ACTION;
} }
static void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts) void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts)
{ {
int ret; int ret;
......
...@@ -38,3 +38,5 @@ bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk, ...@@ -38,3 +38,5 @@ bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk,
bool cancel_all); bool cancel_all);
void io_apoll_cache_free(struct io_cache_entry *entry); void io_apoll_cache_free(struct io_cache_entry *entry);
void io_poll_task_func(struct io_kiocb *req, struct io_tw_state *ts);
...@@ -354,7 +354,6 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx, ...@@ -354,7 +354,6 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
__s32 __user *fds = u64_to_user_ptr(up->data); __s32 __user *fds = u64_to_user_ptr(up->data);
struct io_rsrc_data *data = ctx->file_data; struct io_rsrc_data *data = ctx->file_data;
struct io_fixed_file *file_slot; struct io_fixed_file *file_slot;
struct file *file;
int fd, i, err = 0; int fd, i, err = 0;
unsigned int done; unsigned int done;
...@@ -382,15 +381,16 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx, ...@@ -382,15 +381,16 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
file_slot = io_fixed_file_slot(&ctx->file_table, i); file_slot = io_fixed_file_slot(&ctx->file_table, i);
if (file_slot->file_ptr) { if (file_slot->file_ptr) {
file = (struct file *)(file_slot->file_ptr & FFS_MASK); err = io_queue_rsrc_removal(data, i,
err = io_queue_rsrc_removal(data, i, file); io_slot_file(file_slot));
if (err) if (err)
break; break;
file_slot->file_ptr = 0; file_slot->file_ptr = 0;
io_file_bitmap_clear(&ctx->file_table, i); io_file_bitmap_clear(&ctx->file_table, i);
} }
if (fd != -1) { if (fd != -1) {
file = fget(fd); struct file *file = fget(fd);
if (!file) { if (!file) {
err = -EBADF; err = -EBADF;
break; break;
......
...@@ -283,7 +283,7 @@ static inline int io_fixup_rw_res(struct io_kiocb *req, long res) ...@@ -283,7 +283,7 @@ static inline int io_fixup_rw_res(struct io_kiocb *req, long res)
return res; return res;
} }
static void io_req_rw_complete(struct io_kiocb *req, struct io_tw_state *ts) void io_req_rw_complete(struct io_kiocb *req, struct io_tw_state *ts)
{ {
io_req_io_end(req); io_req_io_end(req);
...@@ -666,8 +666,8 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode) ...@@ -666,8 +666,8 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode)
if (unlikely(!file || !(file->f_mode & mode))) if (unlikely(!file || !(file->f_mode & mode)))
return -EBADF; return -EBADF;
if (!io_req_ffs_set(req)) if (!(req->flags & REQ_F_FIXED_FILE))
req->flags |= io_file_get_flags(file) << REQ_F_SUPPORT_NOWAIT_BIT; req->flags |= io_file_get_flags(file);
kiocb->ki_flags = file->f_iocb_flags; kiocb->ki_flags = file->f_iocb_flags;
ret = kiocb_set_rw_flags(kiocb, rw->flags); ret = kiocb_set_rw_flags(kiocb, rw->flags);
......
...@@ -22,3 +22,4 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags); ...@@ -22,3 +22,4 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags);
int io_writev_prep_async(struct io_kiocb *req); int io_writev_prep_async(struct io_kiocb *req);
void io_readv_writev_cleanup(struct io_kiocb *req); void io_readv_writev_cleanup(struct io_kiocb *req);
void io_rw_fail(struct io_kiocb *req); void io_rw_fail(struct io_kiocb *req);
void io_req_rw_complete(struct io_kiocb *req, struct io_tw_state *ts);
...@@ -208,17 +208,27 @@ void io_uring_unreg_ringfd(void) ...@@ -208,17 +208,27 @@ void io_uring_unreg_ringfd(void)
} }
} }
static int io_ring_add_registered_fd(struct io_uring_task *tctx, int fd, int io_ring_add_registered_file(struct io_uring_task *tctx, struct file *file,
int start, int end) int start, int end)
{ {
struct file *file;
int offset; int offset;
for (offset = start; offset < end; offset++) { for (offset = start; offset < end; offset++) {
offset = array_index_nospec(offset, IO_RINGFD_REG_MAX); offset = array_index_nospec(offset, IO_RINGFD_REG_MAX);
if (tctx->registered_rings[offset]) if (tctx->registered_rings[offset])
continue; continue;
tctx->registered_rings[offset] = file;
return offset;
}
return -EBUSY;
}
static int io_ring_add_registered_fd(struct io_uring_task *tctx, int fd,
int start, int end)
{
struct file *file;
int offset;
file = fget(fd); file = fget(fd);
if (!file) { if (!file) {
return -EBADF; return -EBADF;
...@@ -226,11 +236,10 @@ static int io_ring_add_registered_fd(struct io_uring_task *tctx, int fd, ...@@ -226,11 +236,10 @@ static int io_ring_add_registered_fd(struct io_uring_task *tctx, int fd,
fput(file); fput(file);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
tctx->registered_rings[offset] = file; offset = io_ring_add_registered_file(tctx, file, start, end);
if (offset < 0)
fput(file);
return offset; return offset;
}
return -EBUSY;
} }
/* /*
......
...@@ -73,8 +73,8 @@ static void io_timeout_complete(struct io_kiocb *req, struct io_tw_state *ts) ...@@ -73,8 +73,8 @@ static void io_timeout_complete(struct io_kiocb *req, struct io_tw_state *ts)
if (!io_timeout_finish(timeout, data)) { if (!io_timeout_finish(timeout, data)) {
bool filled; bool filled;
filled = io_aux_cqe(ctx, ts->locked, req->cqe.user_data, -ETIME, filled = io_aux_cqe(req, ts->locked, -ETIME, IORING_CQE_F_MORE,
IORING_CQE_F_MORE, false); false);
if (filled) { if (filled) {
/* re-arm timer */ /* re-arm timer */
spin_lock_irq(&ctx->timeout_lock); spin_lock_irq(&ctx->timeout_lock);
...@@ -594,7 +594,7 @@ int io_timeout(struct io_kiocb *req, unsigned int issue_flags) ...@@ -594,7 +594,7 @@ int io_timeout(struct io_kiocb *req, unsigned int issue_flags)
goto add; goto add;
} }
tail = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts); tail = data_race(ctx->cached_cq_tail) - atomic_read(&ctx->cq_timeouts);
timeout->target_seq = tail + off; timeout->target_seq = tail + off;
/* Update the last seq here in case io_flush_timeouts() hasn't. /* Update the last seq here in case io_flush_timeouts() hasn't.
......
...@@ -20,16 +20,24 @@ static void io_uring_cmd_work(struct io_kiocb *req, struct io_tw_state *ts) ...@@ -20,16 +20,24 @@ static void io_uring_cmd_work(struct io_kiocb *req, struct io_tw_state *ts)
ioucmd->task_work_cb(ioucmd, issue_flags); ioucmd->task_work_cb(ioucmd, issue_flags);
} }
void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd, void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned)) void (*task_work_cb)(struct io_uring_cmd *, unsigned),
unsigned flags)
{ {
struct io_kiocb *req = cmd_to_io_kiocb(ioucmd); struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
ioucmd->task_work_cb = task_work_cb; ioucmd->task_work_cb = task_work_cb;
req->io_task_work.func = io_uring_cmd_work; req->io_task_work.func = io_uring_cmd_work;
io_req_task_work_add(req); __io_req_task_work_add(req, flags);
}
EXPORT_SYMBOL_GPL(__io_uring_cmd_do_in_task);
void io_uring_cmd_do_in_task_lazy(struct io_uring_cmd *ioucmd,
void (*task_work_cb)(struct io_uring_cmd *, unsigned))
{
__io_uring_cmd_do_in_task(ioucmd, task_work_cb, IOU_F_TWQ_LAZY_WAKE);
} }
EXPORT_SYMBOL_GPL(io_uring_cmd_complete_in_task); EXPORT_SYMBOL_GPL(io_uring_cmd_do_in_task_lazy);
static inline void io_req_set_cqe32_extra(struct io_kiocb *req, static inline void io_req_set_cqe32_extra(struct io_kiocb *req,
u64 extra1, u64 extra2) u64 extra1, u64 extra2)
......
...@@ -471,6 +471,7 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) ...@@ -471,6 +471,7 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
return file; return file;
} }
file->f_mode |= FMODE_NOWAIT;
sock->file = file; sock->file = file;
file->private_data = sock; file->private_data = sock;
stream_open(SOCK_INODE(sock), file); stream_open(SOCK_INODE(sock), file);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment