mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10.git
synced 2026-09-09 00:07:04 +08:00
Merge: io_uring: pull in fixes from upstream
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/2000 With these patches (and the one from MR!1989), all liburing tests pass (head commit 3756b3de4cf2e16a5a727c9feefafd7b8c026042). JIRA: https://issues.redhat.com/browse/RHEL-140845 Signed-off-by: Jeff Moyer <jmoyer@redhat.com> Approved-by: Brian Foster <bfoster@redhat.com> Approved-by: Ming Lei <ming.lei@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
|
#include <linux/blk-integrity.h>
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/mpage.h>
|
#include <linux/mpage.h>
|
||||||
#include <linux/uio.h>
|
#include <linux/uio.h>
|
||||||
@@ -684,6 +685,8 @@ static int blkdev_open(struct inode *inode, struct file *filp)
|
|||||||
|
|
||||||
if (bdev_can_atomic_write(bdev))
|
if (bdev_can_atomic_write(bdev))
|
||||||
filp->f_mode |= FMODE_CAN_ATOMIC_WRITE;
|
filp->f_mode |= FMODE_CAN_ATOMIC_WRITE;
|
||||||
|
if (blk_get_integrity(bdev->bd_disk))
|
||||||
|
filp->f_mode |= FMODE_HAS_METADATA;
|
||||||
|
|
||||||
ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
|
ret = bdev_open(bdev, mode, filp->private_data, NULL, filp);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|||||||
+2
-1
@@ -147,7 +147,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
|||||||
/* Expect random access pattern */
|
/* Expect random access pattern */
|
||||||
#define FMODE_RANDOM ((__force fmode_t)(1 << 12))
|
#define FMODE_RANDOM ((__force fmode_t)(1 << 12))
|
||||||
|
|
||||||
/* FMODE_* bit 13 */
|
/* Supports IOCB_HAS_METADATA */
|
||||||
|
#define FMODE_HAS_METADATA ((__force fmode_t)(1 << 13))
|
||||||
|
|
||||||
/* File is opened with O_PATH; almost nothing can be done with it */
|
/* File is opened with O_PATH; almost nothing can be done with it */
|
||||||
#define FMODE_PATH ((__force fmode_t)(1 << 14))
|
#define FMODE_PATH ((__force fmode_t)(1 << 14))
|
||||||
|
|||||||
@@ -415,9 +415,6 @@ struct io_ring_ctx {
|
|||||||
struct callback_head poll_wq_task_work;
|
struct callback_head poll_wq_task_work;
|
||||||
struct list_head defer_list;
|
struct list_head defer_list;
|
||||||
|
|
||||||
struct io_alloc_cache msg_cache;
|
|
||||||
spinlock_t msg_lock;
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||||
struct list_head napi_list; /* track busy poll napi_id */
|
struct list_head napi_list; /* track busy poll napi_id */
|
||||||
spinlock_t napi_lock; /* napi_list lock */
|
spinlock_t napi_lock; /* napi_list lock */
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ struct io_uring_sqe {
|
|||||||
};
|
};
|
||||||
__u32 len; /* buffer size or number of iovecs */
|
__u32 len; /* buffer size or number of iovecs */
|
||||||
union {
|
union {
|
||||||
__kernel_rwf_t rw_flags;
|
__u32 rw_flags;
|
||||||
__u32 fsync_flags;
|
__u32 fsync_flags;
|
||||||
__u16 poll_events; /* compatibility */
|
__u16 poll_events; /* compatibility */
|
||||||
__u32 poll32_events; /* word-reversed for BE */
|
__u32 poll32_events; /* word-reversed for BE */
|
||||||
|
|||||||
+2
-1
@@ -11,9 +11,10 @@ obj-$(CONFIG_IO_URING) += io_uring.o opdef.o kbuf.o rsrc.o notif.o \
|
|||||||
eventfd.o uring_cmd.o openclose.o \
|
eventfd.o uring_cmd.o openclose.o \
|
||||||
sqpoll.o xattr.o nop.o fs.o splice.o \
|
sqpoll.o xattr.o nop.o fs.o splice.o \
|
||||||
sync.o msg_ring.o advise.o openclose.o \
|
sync.o msg_ring.o advise.o openclose.o \
|
||||||
epoll.o statx.o timeout.o fdinfo.o \
|
epoll.o statx.o timeout.o \
|
||||||
cancel.o waitid.o register.o \
|
cancel.o waitid.o register.o \
|
||||||
truncate.o memmap.o alloc_cache.o
|
truncate.o memmap.o alloc_cache.o
|
||||||
obj-$(CONFIG_IO_WQ) += io-wq.o
|
obj-$(CONFIG_IO_WQ) += io-wq.o
|
||||||
obj-$(CONFIG_FUTEX) += futex.o
|
obj-$(CONFIG_FUTEX) += futex.o
|
||||||
obj-$(CONFIG_NET_RX_BUSY_POLL) += napi.o
|
obj-$(CONFIG_NET_RX_BUSY_POLL) += napi.o
|
||||||
|
obj-$(CONFIG_PROC_FS) += fdinfo.o
|
||||||
|
|||||||
+13
-45
@@ -15,37 +15,6 @@
|
|||||||
#include "cancel.h"
|
#include "cancel.h"
|
||||||
#include "rsrc.h"
|
#include "rsrc.h"
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
|
||||||
static __cold int io_uring_show_cred(struct seq_file *m, unsigned int id,
|
|
||||||
const struct cred *cred)
|
|
||||||
{
|
|
||||||
struct user_namespace *uns = seq_user_ns(m);
|
|
||||||
struct group_info *gi;
|
|
||||||
kernel_cap_t cap;
|
|
||||||
int g;
|
|
||||||
|
|
||||||
seq_printf(m, "%5d\n", id);
|
|
||||||
seq_put_decimal_ull(m, "\tUid:\t", from_kuid_munged(uns, cred->uid));
|
|
||||||
seq_put_decimal_ull(m, "\t\t", from_kuid_munged(uns, cred->euid));
|
|
||||||
seq_put_decimal_ull(m, "\t\t", from_kuid_munged(uns, cred->suid));
|
|
||||||
seq_put_decimal_ull(m, "\t\t", from_kuid_munged(uns, cred->fsuid));
|
|
||||||
seq_put_decimal_ull(m, "\n\tGid:\t", from_kgid_munged(uns, cred->gid));
|
|
||||||
seq_put_decimal_ull(m, "\t\t", from_kgid_munged(uns, cred->egid));
|
|
||||||
seq_put_decimal_ull(m, "\t\t", from_kgid_munged(uns, cred->sgid));
|
|
||||||
seq_put_decimal_ull(m, "\t\t", from_kgid_munged(uns, cred->fsgid));
|
|
||||||
seq_puts(m, "\n\tGroups:\t");
|
|
||||||
gi = cred->group_info;
|
|
||||||
for (g = 0; g < gi->ngroups; g++) {
|
|
||||||
seq_put_decimal_ull(m, g ? " " : "",
|
|
||||||
from_kgid_munged(uns, gi->gid[g]));
|
|
||||||
}
|
|
||||||
seq_puts(m, "\n\tCapEff:\t");
|
|
||||||
cap = cred->cap_effective;
|
|
||||||
seq_put_hex_ll(m, NULL, cap.val, 16);
|
|
||||||
seq_putc(m, '\n');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||||
static __cold void common_tracking_show_fdinfo(struct io_ring_ctx *ctx,
|
static __cold void common_tracking_show_fdinfo(struct io_ring_ctx *ctx,
|
||||||
struct seq_file *m,
|
struct seq_file *m,
|
||||||
@@ -90,7 +59,6 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
|
|||||||
{
|
{
|
||||||
struct io_overflow_cqe *ocqe;
|
struct io_overflow_cqe *ocqe;
|
||||||
struct io_rings *r = ctx->rings;
|
struct io_rings *r = ctx->rings;
|
||||||
struct rusage sq_usage;
|
|
||||||
unsigned int sq_mask = ctx->sq_entries - 1, cq_mask = ctx->cq_entries - 1;
|
unsigned int sq_mask = ctx->sq_entries - 1, cq_mask = ctx->cq_entries - 1;
|
||||||
unsigned int sq_head = READ_ONCE(r->sq.head);
|
unsigned int sq_head = READ_ONCE(r->sq.head);
|
||||||
unsigned int sq_tail = READ_ONCE(r->sq.tail);
|
unsigned int sq_tail = READ_ONCE(r->sq.tail);
|
||||||
@@ -172,18 +140,27 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
|
|||||||
|
|
||||||
if (ctx->flags & IORING_SETUP_SQPOLL) {
|
if (ctx->flags & IORING_SETUP_SQPOLL) {
|
||||||
struct io_sq_data *sq = ctx->sq_data;
|
struct io_sq_data *sq = ctx->sq_data;
|
||||||
|
struct task_struct *tsk;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
tsk = rcu_dereference(sq->thread);
|
||||||
/*
|
/*
|
||||||
* sq->thread might be NULL if we raced with the sqpoll
|
* sq->thread might be NULL if we raced with the sqpoll
|
||||||
* thread termination.
|
* thread termination.
|
||||||
*/
|
*/
|
||||||
if (sq->thread) {
|
if (tsk) {
|
||||||
|
u64 usec;
|
||||||
|
|
||||||
|
get_task_struct(tsk);
|
||||||
|
rcu_read_unlock();
|
||||||
|
usec = io_sq_cpu_usec(tsk);
|
||||||
|
put_task_struct(tsk);
|
||||||
sq_pid = sq->task_pid;
|
sq_pid = sq->task_pid;
|
||||||
sq_cpu = sq->sq_cpu;
|
sq_cpu = sq->sq_cpu;
|
||||||
getrusage(sq->thread, RUSAGE_SELF, &sq_usage);
|
sq_total_time = usec;
|
||||||
sq_total_time = (sq_usage.ru_stime.tv_sec * 1000000
|
|
||||||
+ sq_usage.ru_stime.tv_usec);
|
|
||||||
sq_work_time = sq->work_time;
|
sq_work_time = sq->work_time;
|
||||||
|
} else {
|
||||||
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,14 +191,6 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m)
|
|||||||
else
|
else
|
||||||
seq_printf(m, "%5u: <none>\n", i);
|
seq_printf(m, "%5u: <none>\n", i);
|
||||||
}
|
}
|
||||||
if (!xa_empty(&ctx->personalities)) {
|
|
||||||
unsigned long index;
|
|
||||||
const struct cred *cred;
|
|
||||||
|
|
||||||
seq_printf(m, "Personalities:\n");
|
|
||||||
xa_for_each(&ctx->personalities, index, cred)
|
|
||||||
io_uring_show_cred(m, index, cred);
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_puts(m, "PollList:\n");
|
seq_puts(m, "PollList:\n");
|
||||||
for (i = 0; i < (1U << ctx->cancel_table.hash_bits); i++) {
|
for (i = 0; i < (1U << ctx->cancel_table.hash_bits); i++) {
|
||||||
@@ -264,4 +233,3 @@ __cold void io_uring_show_fdinfo(struct seq_file *m, struct file *file)
|
|||||||
mutex_unlock(&ctx->uring_lock);
|
mutex_unlock(&ctx->uring_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ void io_free_file_tables(struct io_ring_ctx *ctx, struct io_file_table *table)
|
|||||||
|
|
||||||
static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
|
static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file,
|
||||||
u32 slot_index)
|
u32 slot_index)
|
||||||
__must_hold(&req->ctx->uring_lock)
|
__must_hold(&ctx->uring_lock)
|
||||||
{
|
{
|
||||||
struct io_rsrc_node *node;
|
struct io_rsrc_node *node;
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -916,11 +916,11 @@ static bool io_wq_for_each_worker(struct io_wq *wq,
|
|||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < IO_WQ_ACCT_NR; i++) {
|
for (int i = 0; i < IO_WQ_ACCT_NR; i++) {
|
||||||
if (!io_acct_for_each_worker(&wq->acct[i], func, data))
|
if (io_acct_for_each_worker(&wq->acct[i], func, data))
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool io_wq_worker_wake(struct io_worker *worker, void *data)
|
static bool io_wq_worker_wake(struct io_worker *worker, void *data)
|
||||||
|
|||||||
+15
-12
@@ -290,7 +290,6 @@ static void io_free_alloc_caches(struct io_ring_ctx *ctx)
|
|||||||
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
|
io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
|
||||||
io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
|
io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free);
|
||||||
io_alloc_cache_free(&ctx->cmd_cache, io_cmd_cache_free);
|
io_alloc_cache_free(&ctx->cmd_cache, io_cmd_cache_free);
|
||||||
io_alloc_cache_free(&ctx->msg_cache, kfree);
|
|
||||||
io_futex_cache_free(ctx);
|
io_futex_cache_free(ctx);
|
||||||
io_rsrc_cache_free(ctx);
|
io_rsrc_cache_free(ctx);
|
||||||
}
|
}
|
||||||
@@ -337,9 +336,6 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
|
|||||||
ret |= io_alloc_cache_init(&ctx->cmd_cache, IO_ALLOC_CACHE_MAX,
|
ret |= io_alloc_cache_init(&ctx->cmd_cache, IO_ALLOC_CACHE_MAX,
|
||||||
sizeof(struct io_async_cmd),
|
sizeof(struct io_async_cmd),
|
||||||
sizeof(struct io_async_cmd));
|
sizeof(struct io_async_cmd));
|
||||||
spin_lock_init(&ctx->msg_lock);
|
|
||||||
ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
|
|
||||||
sizeof(struct io_kiocb), 0);
|
|
||||||
ret |= io_futex_cache_init(ctx);
|
ret |= io_futex_cache_init(ctx);
|
||||||
ret |= io_rsrc_cache_init(ctx);
|
ret |= io_rsrc_cache_init(ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -1359,8 +1355,10 @@ static void io_req_task_cancel(struct io_kiocb *req, io_tw_token_t tw)
|
|||||||
|
|
||||||
void io_req_task_submit(struct io_kiocb *req, io_tw_token_t tw)
|
void io_req_task_submit(struct io_kiocb *req, io_tw_token_t tw)
|
||||||
{
|
{
|
||||||
io_tw_lock(req->ctx, tw);
|
struct io_ring_ctx *ctx = req->ctx;
|
||||||
if (unlikely(io_should_terminate_tw()))
|
|
||||||
|
io_tw_lock(ctx, tw);
|
||||||
|
if (unlikely(io_should_terminate_tw(ctx)))
|
||||||
io_req_defer_failed(req, -EFAULT);
|
io_req_defer_failed(req, -EFAULT);
|
||||||
else if (req->flags & REQ_F_FORCE_ASYNC)
|
else if (req->flags & REQ_F_FORCE_ASYNC)
|
||||||
io_queue_iowq(req);
|
io_queue_iowq(req);
|
||||||
@@ -2444,6 +2442,9 @@ static enum hrtimer_restart io_cqring_min_timer_wakeup(struct hrtimer *timer)
|
|||||||
goto out_wake;
|
goto out_wake;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* any generated CQE posted past this time should wake us up */
|
||||||
|
iowq->cq_tail = iowq->cq_min_tail;
|
||||||
|
|
||||||
hrtimer_update_function(&iowq->t, io_cqring_timer_wakeup);
|
hrtimer_update_function(&iowq->t, io_cqring_timer_wakeup);
|
||||||
hrtimer_set_expires(timer, iowq->timeout);
|
hrtimer_set_expires(timer, iowq->timeout);
|
||||||
return HRTIMER_RESTART;
|
return HRTIMER_RESTART;
|
||||||
@@ -2901,7 +2902,7 @@ static __cold void io_ring_exit_work(struct work_struct *work)
|
|||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
|
|
||||||
io_sq_thread_park(sqd);
|
io_sq_thread_park(sqd);
|
||||||
tsk = sqd->thread;
|
tsk = sqpoll_task_locked(sqd);
|
||||||
if (tsk && tsk->io_uring && tsk->io_uring->io_wq)
|
if (tsk && tsk->io_uring && tsk->io_uring->io_wq)
|
||||||
io_wq_cancel_cb(tsk->io_uring->io_wq,
|
io_wq_cancel_cb(tsk->io_uring->io_wq,
|
||||||
io_cancel_ctx_cb, ctx, true);
|
io_cancel_ctx_cb, ctx, true);
|
||||||
@@ -3138,7 +3139,7 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
|
|||||||
s64 inflight;
|
s64 inflight;
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
|
|
||||||
WARN_ON_ONCE(sqd && sqd->thread != current);
|
WARN_ON_ONCE(sqd && sqpoll_task_locked(sqd) != current);
|
||||||
|
|
||||||
if (!current->io_uring)
|
if (!current->io_uring)
|
||||||
return;
|
return;
|
||||||
@@ -3504,10 +3505,6 @@ static __cold int io_allocate_scq_urings(struct io_ring_ctx *ctx,
|
|||||||
|
|
||||||
if (!(ctx->flags & IORING_SETUP_NO_SQARRAY))
|
if (!(ctx->flags & IORING_SETUP_NO_SQARRAY))
|
||||||
ctx->sq_array = (u32 *)((char *)rings + sq_array_offset);
|
ctx->sq_array = (u32 *)((char *)rings + sq_array_offset);
|
||||||
rings->sq_ring_mask = p->sq_entries - 1;
|
|
||||||
rings->cq_ring_mask = p->cq_entries - 1;
|
|
||||||
rings->sq_ring_entries = p->sq_entries;
|
|
||||||
rings->cq_ring_entries = p->cq_entries;
|
|
||||||
|
|
||||||
if (p->flags & IORING_SETUP_SQE128)
|
if (p->flags & IORING_SETUP_SQE128)
|
||||||
size = array_size(2 * sizeof(struct io_uring_sqe), p->sq_entries);
|
size = array_size(2 * sizeof(struct io_uring_sqe), p->sq_entries);
|
||||||
@@ -3530,6 +3527,12 @@ static __cold int io_allocate_scq_urings(struct io_ring_ctx *ctx,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ctx->sq_sqes = io_region_get_ptr(&ctx->sq_region);
|
ctx->sq_sqes = io_region_get_ptr(&ctx->sq_region);
|
||||||
|
|
||||||
|
memset(rings, 0, sizeof(*rings));
|
||||||
|
WRITE_ONCE(rings->sq_ring_mask, ctx->sq_entries - 1);
|
||||||
|
WRITE_ONCE(rings->cq_ring_mask, ctx->cq_entries - 1);
|
||||||
|
WRITE_ONCE(rings->sq_ring_entries, ctx->sq_entries);
|
||||||
|
WRITE_ONCE(rings->cq_ring_entries, ctx->cq_entries);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -464,9 +464,9 @@ static inline bool io_allowed_run_tw(struct io_ring_ctx *ctx)
|
|||||||
* 2) PF_KTHREAD is set, in which case the invoker of the task_work is
|
* 2) PF_KTHREAD is set, in which case the invoker of the task_work is
|
||||||
* our fallback task_work.
|
* our fallback task_work.
|
||||||
*/
|
*/
|
||||||
static inline bool io_should_terminate_tw(void)
|
static inline bool io_should_terminate_tw(struct io_ring_ctx *ctx)
|
||||||
{
|
{
|
||||||
return current->flags & (PF_KTHREAD | PF_EXITING);
|
return (current->flags & (PF_KTHREAD | PF_EXITING)) || percpu_ref_is_dying(&ctx->refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void io_req_queue_tw_complete(struct io_kiocb *req, s32 res)
|
static inline void io_req_queue_tw_complete(struct io_kiocb *req, s32 res)
|
||||||
|
|||||||
+5
-5
@@ -44,7 +44,7 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len)
|
|||||||
buf_len -= this_len;
|
buf_len -= this_len;
|
||||||
/* Stop looping for invalid buffer length of 0 */
|
/* Stop looping for invalid buffer length of 0 */
|
||||||
if (buf_len || !this_len) {
|
if (buf_len || !this_len) {
|
||||||
buf->addr += this_len;
|
buf->addr = READ_ONCE(buf->addr) + this_len;
|
||||||
buf->len = buf_len;
|
buf->len = buf_len;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -178,8 +178,8 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len,
|
|||||||
*len = buf_len;
|
*len = buf_len;
|
||||||
req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT;
|
req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT;
|
||||||
req->buf_list = bl;
|
req->buf_list = bl;
|
||||||
req->buf_index = buf->bid;
|
req->buf_index = READ_ONCE(buf->bid);
|
||||||
ret = u64_to_user_ptr(buf->addr);
|
ret = u64_to_user_ptr(READ_ONCE(buf->addr));
|
||||||
|
|
||||||
if (issue_flags & IO_URING_F_UNLOCKED || !io_file_can_poll(req)) {
|
if (issue_flags & IO_URING_F_UNLOCKED || !io_file_can_poll(req)) {
|
||||||
/*
|
/*
|
||||||
@@ -269,7 +269,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
|
|||||||
if (!arg->max_len)
|
if (!arg->max_len)
|
||||||
arg->max_len = INT_MAX;
|
arg->max_len = INT_MAX;
|
||||||
|
|
||||||
req->buf_index = buf->bid;
|
req->buf_index = READ_ONCE(buf->bid);
|
||||||
do {
|
do {
|
||||||
u32 len = READ_ONCE(buf->len);
|
u32 len = READ_ONCE(buf->len);
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
|
|||||||
buf->len = len;
|
buf->len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
iov->iov_base = u64_to_user_ptr(buf->addr);
|
iov->iov_base = u64_to_user_ptr(READ_ONCE(buf->addr));
|
||||||
iov->iov_len = len;
|
iov->iov_len = len;
|
||||||
iov++;
|
iov++;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -134,7 +134,7 @@ static int io_region_pin_pages(struct io_ring_ctx *ctx,
|
|||||||
struct io_mapped_region *mr,
|
struct io_mapped_region *mr,
|
||||||
struct io_uring_region_desc *reg)
|
struct io_uring_region_desc *reg)
|
||||||
{
|
{
|
||||||
unsigned long size = mr->nr_pages << PAGE_SHIFT;
|
unsigned long size = (size_t) mr->nr_pages << PAGE_SHIFT;
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
int nr_pages;
|
int nr_pages;
|
||||||
|
|
||||||
|
|||||||
+2
-22
@@ -11,7 +11,6 @@
|
|||||||
#include "io_uring.h"
|
#include "io_uring.h"
|
||||||
#include "rsrc.h"
|
#include "rsrc.h"
|
||||||
#include "filetable.h"
|
#include "filetable.h"
|
||||||
#include "alloc_cache.h"
|
|
||||||
#include "msg_ring.h"
|
#include "msg_ring.h"
|
||||||
|
|
||||||
/* All valid masks for MSG_RING */
|
/* All valid masks for MSG_RING */
|
||||||
@@ -76,13 +75,7 @@ static void io_msg_tw_complete(struct io_kiocb *req, io_tw_token_t tw)
|
|||||||
struct io_ring_ctx *ctx = req->ctx;
|
struct io_ring_ctx *ctx = req->ctx;
|
||||||
|
|
||||||
io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
|
io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
|
||||||
if (spin_trylock(&ctx->msg_lock)) {
|
kfree_rcu(req, rcu_head);
|
||||||
if (io_alloc_cache_put(&ctx->msg_cache, req))
|
|
||||||
req = NULL;
|
|
||||||
spin_unlock(&ctx->msg_lock);
|
|
||||||
}
|
|
||||||
if (req)
|
|
||||||
kfree_rcu(req, rcu_head);
|
|
||||||
percpu_ref_put(&ctx->refs);
|
percpu_ref_put(&ctx->refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,26 +97,13 @@ static int io_msg_remote_post(struct io_ring_ctx *ctx, struct io_kiocb *req,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct io_kiocb *req = NULL;
|
|
||||||
|
|
||||||
if (spin_trylock(&ctx->msg_lock)) {
|
|
||||||
req = io_alloc_cache_get(&ctx->msg_cache);
|
|
||||||
spin_unlock(&ctx->msg_lock);
|
|
||||||
if (req)
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int io_msg_data_remote(struct io_ring_ctx *target_ctx,
|
static int io_msg_data_remote(struct io_ring_ctx *target_ctx,
|
||||||
struct io_msg *msg)
|
struct io_msg *msg)
|
||||||
{
|
{
|
||||||
struct io_kiocb *target;
|
struct io_kiocb *target;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
|
||||||
target = io_msg_get_kiocb(target_ctx);
|
target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO) ;
|
||||||
if (unlikely(!target))
|
if (unlikely(!target))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|||||||
+15
-12
@@ -468,6 +468,15 @@ static int io_bundle_nbufs(struct io_async_msghdr *kmsg, int ret)
|
|||||||
return nbufs;
|
return nbufs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int io_net_kbuf_recyle(struct io_kiocb *req,
|
||||||
|
struct io_async_msghdr *kmsg, int len)
|
||||||
|
{
|
||||||
|
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||||
|
if (req->flags & REQ_F_BUFFERS_COMMIT)
|
||||||
|
io_kbuf_commit(req, req->buf_list, len, io_bundle_nbufs(kmsg, len));
|
||||||
|
return IOU_RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool io_send_finish(struct io_kiocb *req, int *ret,
|
static inline bool io_send_finish(struct io_kiocb *req, int *ret,
|
||||||
struct io_async_msghdr *kmsg,
|
struct io_async_msghdr *kmsg,
|
||||||
unsigned issue_flags)
|
unsigned issue_flags)
|
||||||
@@ -536,8 +545,7 @@ int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||||||
kmsg->msg.msg_controllen = 0;
|
kmsg->msg.msg_controllen = 0;
|
||||||
kmsg->msg.msg_control = NULL;
|
kmsg->msg.msg_control = NULL;
|
||||||
sr->done_io += ret;
|
sr->done_io += ret;
|
||||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
if (ret == -ERESTARTSYS)
|
if (ret == -ERESTARTSYS)
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
@@ -647,8 +655,7 @@ retry_bundle:
|
|||||||
sr->len -= ret;
|
sr->len -= ret;
|
||||||
sr->buf += ret;
|
sr->buf += ret;
|
||||||
sr->done_io += ret;
|
sr->done_io += ret;
|
||||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
if (ret == -ERESTARTSYS)
|
if (ret == -ERESTARTSYS)
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
@@ -1020,8 +1027,7 @@ retry_multishot:
|
|||||||
}
|
}
|
||||||
if (ret > 0 && io_net_retry(sock, flags)) {
|
if (ret > 0 && io_net_retry(sock, flags)) {
|
||||||
sr->done_io += ret;
|
sr->done_io += ret;
|
||||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||||
return IOU_RETRY;
|
|
||||||
}
|
}
|
||||||
if (ret == -ERESTARTSYS)
|
if (ret == -ERESTARTSYS)
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
@@ -1158,8 +1164,7 @@ retry_multishot:
|
|||||||
sr->len -= ret;
|
sr->len -= ret;
|
||||||
sr->buf += ret;
|
sr->buf += ret;
|
||||||
sr->done_io += ret;
|
sr->done_io += ret;
|
||||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
if (ret == -ERESTARTSYS)
|
if (ret == -ERESTARTSYS)
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
@@ -1377,8 +1382,7 @@ int io_send_zc(struct io_kiocb *req, unsigned int issue_flags)
|
|||||||
zc->len -= ret;
|
zc->len -= ret;
|
||||||
zc->buf += ret;
|
zc->buf += ret;
|
||||||
zc->done_io += ret;
|
zc->done_io += ret;
|
||||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
if (ret == -ERESTARTSYS)
|
if (ret == -ERESTARTSYS)
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
@@ -1450,8 +1454,7 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags)
|
|||||||
|
|
||||||
if (ret > 0 && io_net_retry(sock, flags)) {
|
if (ret > 0 && io_net_retry(sock, flags)) {
|
||||||
sr->done_io += ret;
|
sr->done_io += ret;
|
||||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
if (ret == -ERESTARTSYS)
|
if (ret == -ERESTARTSYS)
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ static int io_link_skb(struct sk_buff *skb, struct ubuf_info *uarg)
|
|||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
prev_nd = container_of(prev_uarg, struct io_notif_data, uarg);
|
prev_nd = container_of(prev_uarg, struct io_notif_data, uarg);
|
||||||
prev_notif = cmd_to_io_kiocb(nd);
|
prev_notif = cmd_to_io_kiocb(prev_nd);
|
||||||
|
|
||||||
/* make sure all noifications can be finished in the same task_work */
|
/* make sure all noifications can be finished in the same task_work */
|
||||||
if (unlikely(notif->ctx != prev_notif->ctx ||
|
if (unlikely(notif->ctx != prev_notif->ctx ||
|
||||||
|
|||||||
@@ -70,13 +70,13 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
|||||||
open->filename = NULL;
|
open->filename = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
req->flags |= REQ_F_NEED_CLEANUP;
|
||||||
|
|
||||||
open->file_slot = READ_ONCE(sqe->file_index);
|
open->file_slot = READ_ONCE(sqe->file_index);
|
||||||
if (open->file_slot && (open->how.flags & O_CLOEXEC))
|
if (open->file_slot && (open->how.flags & O_CLOEXEC))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
open->nofile = rlimit(RLIMIT_NOFILE);
|
open->nofile = rlimit(RLIMIT_NOFILE);
|
||||||
req->flags |= REQ_F_NEED_CLEANUP;
|
|
||||||
if (io_openat_force_async(open))
|
if (io_openat_force_async(open))
|
||||||
req->flags |= REQ_F_FORCE_ASYNC;
|
req->flags |= REQ_F_FORCE_ASYNC;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+8
-3
@@ -224,7 +224,7 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw)
|
|||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
if (unlikely(io_should_terminate_tw()))
|
if (unlikely(io_should_terminate_tw(req->ctx)))
|
||||||
return -ECANCELED;
|
return -ECANCELED;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -930,12 +930,17 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
|
|||||||
|
|
||||||
ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
|
ret2 = io_poll_add(preq, issue_flags & ~IO_URING_F_UNLOCKED);
|
||||||
/* successfully updated, don't complete poll request */
|
/* successfully updated, don't complete poll request */
|
||||||
if (!ret2 || ret2 == -EIOCBQUEUED)
|
if (ret2 == IOU_ISSUE_SKIP_COMPLETE)
|
||||||
goto out;
|
goto out;
|
||||||
|
/* request completed as part of the update, complete it */
|
||||||
|
else if (ret2 == IOU_COMPLETE)
|
||||||
|
goto complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
req_set_fail(preq);
|
|
||||||
io_req_set_res(preq, -ECANCELED, 0);
|
io_req_set_res(preq, -ECANCELED, 0);
|
||||||
|
complete:
|
||||||
|
if (preq->cqe.res < 0)
|
||||||
|
req_set_fail(preq);
|
||||||
preq->io_task_work.func = io_req_task_complete;
|
preq->io_task_work.func = io_req_task_complete;
|
||||||
io_req_task_work_add(preq);
|
io_req_task_work_add(preq);
|
||||||
out:
|
out:
|
||||||
|
|||||||
+6
-2
@@ -272,6 +272,8 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
|
|||||||
if (ctx->flags & IORING_SETUP_SQPOLL) {
|
if (ctx->flags & IORING_SETUP_SQPOLL) {
|
||||||
sqd = ctx->sq_data;
|
sqd = ctx->sq_data;
|
||||||
if (sqd) {
|
if (sqd) {
|
||||||
|
struct task_struct *tsk;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Observe the correct sqd->lock -> ctx->uring_lock
|
* Observe the correct sqd->lock -> ctx->uring_lock
|
||||||
* ordering. Fine to drop uring_lock here, we hold
|
* ordering. Fine to drop uring_lock here, we hold
|
||||||
@@ -281,8 +283,9 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx,
|
|||||||
mutex_unlock(&ctx->uring_lock);
|
mutex_unlock(&ctx->uring_lock);
|
||||||
mutex_lock(&sqd->lock);
|
mutex_lock(&sqd->lock);
|
||||||
mutex_lock(&ctx->uring_lock);
|
mutex_lock(&ctx->uring_lock);
|
||||||
if (sqd->thread)
|
tsk = sqpoll_task_locked(sqd);
|
||||||
tctx = sqd->thread->io_uring;
|
if (tsk)
|
||||||
|
tctx = tsk->io_uring;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tctx = current->io_uring;
|
tctx = current->io_uring;
|
||||||
@@ -614,6 +617,7 @@ static int io_register_mem_region(struct io_ring_ctx *ctx, void __user *uarg)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (copy_to_user(rd_uptr, &rd, sizeof(rd))) {
|
if (copy_to_user(rd_uptr, &rd, sizeof(rd))) {
|
||||||
|
guard(mutex)(&ctx->mmap_lock);
|
||||||
io_free_region(ctx, &ctx->param_region);
|
io_free_region(ctx, &ctx->param_region);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-12
@@ -55,7 +55,7 @@ int __io_account_mem(struct user_struct *user, unsigned long nr_pages)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
|
void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
|
||||||
{
|
{
|
||||||
if (ctx->user)
|
if (ctx->user)
|
||||||
__io_unaccount_mem(ctx->user, nr_pages);
|
__io_unaccount_mem(ctx->user, nr_pages);
|
||||||
@@ -64,7 +64,7 @@ static void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
|
|||||||
atomic64_sub(nr_pages, &ctx->mm_account->pinned_vm);
|
atomic64_sub(nr_pages, &ctx->mm_account->pinned_vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
|
int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -931,8 +931,8 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
|
|||||||
struct req_iterator rq_iter;
|
struct req_iterator rq_iter;
|
||||||
struct io_mapped_ubuf *imu;
|
struct io_mapped_ubuf *imu;
|
||||||
struct io_rsrc_node *node;
|
struct io_rsrc_node *node;
|
||||||
struct bio_vec bv, *bvec;
|
struct bio_vec bv;
|
||||||
u16 nr_bvecs;
|
unsigned int nr_bvecs = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
io_ring_submit_lock(ctx, issue_flags);
|
io_ring_submit_lock(ctx, issue_flags);
|
||||||
@@ -953,8 +953,11 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
nr_bvecs = blk_rq_nr_phys_segments(rq);
|
/*
|
||||||
imu = io_alloc_imu(ctx, nr_bvecs);
|
* blk_rq_nr_phys_segments() may overestimate the number of bvecs
|
||||||
|
* but avoids needing to iterate over the bvecs
|
||||||
|
*/
|
||||||
|
imu = io_alloc_imu(ctx, blk_rq_nr_phys_segments(rq));
|
||||||
if (!imu) {
|
if (!imu) {
|
||||||
kfree(node);
|
kfree(node);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
@@ -965,16 +968,15 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
|
|||||||
imu->len = blk_rq_bytes(rq);
|
imu->len = blk_rq_bytes(rq);
|
||||||
imu->acct_pages = 0;
|
imu->acct_pages = 0;
|
||||||
imu->folio_shift = PAGE_SHIFT;
|
imu->folio_shift = PAGE_SHIFT;
|
||||||
imu->nr_bvecs = nr_bvecs;
|
|
||||||
refcount_set(&imu->refs, 1);
|
refcount_set(&imu->refs, 1);
|
||||||
imu->release = release;
|
imu->release = release;
|
||||||
imu->priv = rq;
|
imu->priv = rq;
|
||||||
imu->is_kbuf = true;
|
imu->is_kbuf = true;
|
||||||
imu->dir = 1 << rq_data_dir(rq);
|
imu->dir = 1 << rq_data_dir(rq);
|
||||||
|
|
||||||
bvec = imu->bvec;
|
|
||||||
rq_for_each_bvec(bv, rq, rq_iter)
|
rq_for_each_bvec(bv, rq, rq_iter)
|
||||||
*bvec++ = bv;
|
imu->bvec[nr_bvecs++] = bv;
|
||||||
|
imu->nr_bvecs = nr_bvecs;
|
||||||
|
|
||||||
node->buf = imu;
|
node->buf = imu;
|
||||||
data->nodes[index] = node;
|
data->nodes[index] = node;
|
||||||
@@ -1043,6 +1045,7 @@ static int io_import_kbuf(int ddir, struct iov_iter *iter,
|
|||||||
if (count < imu->len) {
|
if (count < imu->len) {
|
||||||
const struct bio_vec *bvec = iter->bvec;
|
const struct bio_vec *bvec = iter->bvec;
|
||||||
|
|
||||||
|
len += iter->iov_offset;
|
||||||
while (len > bvec->bv_len) {
|
while (len > bvec->bv_len) {
|
||||||
len -= bvec->bv_len;
|
len -= bvec->bv_len;
|
||||||
bvec++;
|
bvec++;
|
||||||
@@ -1181,7 +1184,7 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Fill entries in data from dst that won't overlap with src */
|
/* Copy original dst nodes from before the cloned range */
|
||||||
for (i = 0; i < min(arg->dst_off, ctx->buf_table.nr); i++) {
|
for (i = 0; i < min(arg->dst_off, ctx->buf_table.nr); i++) {
|
||||||
struct io_rsrc_node *src_node = ctx->buf_table.nodes[i];
|
struct io_rsrc_node *src_node = ctx->buf_table.nodes[i];
|
||||||
|
|
||||||
@@ -1236,6 +1239,16 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy original dst nodes from after the cloned range */
|
||||||
|
for (i = nbufs; i < ctx->buf_table.nr; i++) {
|
||||||
|
struct io_rsrc_node *node = ctx->buf_table.nodes[i];
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
data.nodes[i] = node;
|
||||||
|
node->refs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If asked for replace, put the old table. data->nodes[] holds both
|
* If asked for replace, put the old table. data->nodes[] holds both
|
||||||
* old and new nodes at this point.
|
* old and new nodes at this point.
|
||||||
@@ -1387,8 +1400,11 @@ static int io_estimate_bvec_size(struct iovec *iov, unsigned nr_iovs,
|
|||||||
size_t max_segs = 0;
|
size_t max_segs = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < nr_iovs; i++)
|
for (i = 0; i < nr_iovs; i++) {
|
||||||
max_segs += (iov[i].iov_len >> shift) + 2;
|
max_segs += (iov[i].iov_len >> shift) + 2;
|
||||||
|
if (max_segs > INT_MAX)
|
||||||
|
return -EOVERFLOW;
|
||||||
|
}
|
||||||
return max_segs;
|
return max_segs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1494,7 +1510,11 @@ int io_import_reg_vec(int ddir, struct iov_iter *iter,
|
|||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
nr_segs = io_estimate_bvec_size(iov, nr_iovs, imu);
|
int ret = io_estimate_bvec_size(iov, nr_iovs, imu);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
nr_segs = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(struct bio_vec) > sizeof(struct iovec)) {
|
if (sizeof(struct bio_vec) > sizeof(struct iovec)) {
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ int io_files_update(struct io_kiocb *req, unsigned int issue_flags);
|
|||||||
int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
|
int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
|
||||||
|
|
||||||
int __io_account_mem(struct user_struct *user, unsigned long nr_pages);
|
int __io_account_mem(struct user_struct *user, unsigned long nr_pages);
|
||||||
|
int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages);
|
||||||
|
void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages);
|
||||||
|
|
||||||
static inline void __io_unaccount_mem(struct user_struct *user,
|
static inline void __io_unaccount_mem(struct user_struct *user,
|
||||||
unsigned long nr_pages)
|
unsigned long nr_pages)
|
||||||
|
|||||||
+8
-2
@@ -285,7 +285,7 @@ static int __io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
|
|||||||
|
|
||||||
rw->addr = READ_ONCE(sqe->addr);
|
rw->addr = READ_ONCE(sqe->addr);
|
||||||
rw->len = READ_ONCE(sqe->len);
|
rw->len = READ_ONCE(sqe->len);
|
||||||
rw->flags = READ_ONCE(sqe->rw_flags);
|
rw->flags = (__force rwf_t) READ_ONCE(sqe->rw_flags);
|
||||||
|
|
||||||
attr_type_mask = READ_ONCE(sqe->attr_type_mask);
|
attr_type_mask = READ_ONCE(sqe->attr_type_mask);
|
||||||
if (attr_type_mask) {
|
if (attr_type_mask) {
|
||||||
@@ -458,7 +458,10 @@ int io_read_mshot_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||||||
|
|
||||||
void io_readv_writev_cleanup(struct io_kiocb *req)
|
void io_readv_writev_cleanup(struct io_kiocb *req)
|
||||||
{
|
{
|
||||||
|
struct io_async_rw *rw = req->async_data;
|
||||||
|
|
||||||
lockdep_assert_held(&req->ctx->uring_lock);
|
lockdep_assert_held(&req->ctx->uring_lock);
|
||||||
|
io_vec_free(&rw->vec);
|
||||||
io_rw_recycle(req, 0);
|
io_rw_recycle(req, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +540,7 @@ static void __io_complete_rw_common(struct io_kiocb *req, long res)
|
|||||||
{
|
{
|
||||||
if (res == req->cqe.res)
|
if (res == req->cqe.res)
|
||||||
return;
|
return;
|
||||||
if (res == -EAGAIN && io_rw_should_reissue(req)) {
|
if ((res == -EOPNOTSUPP || res == -EAGAIN) && io_rw_should_reissue(req)) {
|
||||||
req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE;
|
req->flags |= REQ_F_REISSUE | REQ_F_BL_NO_RECYCLE;
|
||||||
} else {
|
} else {
|
||||||
req_set_fail(req);
|
req_set_fail(req);
|
||||||
@@ -883,6 +886,9 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode, int rw_type)
|
|||||||
if (req->flags & REQ_F_HAS_METADATA) {
|
if (req->flags & REQ_F_HAS_METADATA) {
|
||||||
struct io_async_rw *io = req->async_data;
|
struct io_async_rw *io = req->async_data;
|
||||||
|
|
||||||
|
if (!(file->f_mode & FMODE_HAS_METADATA))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a union of meta fields with wpq used for buffered-io
|
* We have a union of meta fields with wpq used for buffered-io
|
||||||
* in io_async_rw, so fail it here.
|
* in io_async_rw, so fail it here.
|
||||||
|
|||||||
+74
-39
@@ -11,6 +11,7 @@
|
|||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
#include <linux/cpuset.h>
|
#include <linux/cpuset.h>
|
||||||
|
#include <linux/sched/cputime.h>
|
||||||
#include <linux/io_uring.h>
|
#include <linux/io_uring.h>
|
||||||
|
|
||||||
#include <uapi/linux/io_uring.h>
|
#include <uapi/linux/io_uring.h>
|
||||||
@@ -30,7 +31,7 @@ enum {
|
|||||||
void io_sq_thread_unpark(struct io_sq_data *sqd)
|
void io_sq_thread_unpark(struct io_sq_data *sqd)
|
||||||
__releases(&sqd->lock)
|
__releases(&sqd->lock)
|
||||||
{
|
{
|
||||||
WARN_ON_ONCE(sqd->thread == current);
|
WARN_ON_ONCE(sqpoll_task_locked(sqd) == current);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the dance but not conditional clear_bit() because it'd race with
|
* Do the dance but not conditional clear_bit() because it'd race with
|
||||||
@@ -46,24 +47,32 @@ void io_sq_thread_unpark(struct io_sq_data *sqd)
|
|||||||
void io_sq_thread_park(struct io_sq_data *sqd)
|
void io_sq_thread_park(struct io_sq_data *sqd)
|
||||||
__acquires(&sqd->lock)
|
__acquires(&sqd->lock)
|
||||||
{
|
{
|
||||||
WARN_ON_ONCE(data_race(sqd->thread) == current);
|
struct task_struct *tsk;
|
||||||
|
|
||||||
atomic_inc(&sqd->park_pending);
|
atomic_inc(&sqd->park_pending);
|
||||||
set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state);
|
set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state);
|
||||||
mutex_lock(&sqd->lock);
|
mutex_lock(&sqd->lock);
|
||||||
if (sqd->thread)
|
|
||||||
wake_up_process(sqd->thread);
|
tsk = sqpoll_task_locked(sqd);
|
||||||
|
if (tsk) {
|
||||||
|
WARN_ON_ONCE(tsk == current);
|
||||||
|
wake_up_process(tsk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void io_sq_thread_stop(struct io_sq_data *sqd)
|
void io_sq_thread_stop(struct io_sq_data *sqd)
|
||||||
{
|
{
|
||||||
WARN_ON_ONCE(sqd->thread == current);
|
struct task_struct *tsk;
|
||||||
|
|
||||||
WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state));
|
WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state));
|
||||||
|
|
||||||
set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state);
|
set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state);
|
||||||
mutex_lock(&sqd->lock);
|
mutex_lock(&sqd->lock);
|
||||||
if (sqd->thread)
|
tsk = sqpoll_task_locked(sqd);
|
||||||
wake_up_process(sqd->thread);
|
if (tsk) {
|
||||||
|
WARN_ON_ONCE(tsk == current);
|
||||||
|
wake_up_process(tsk);
|
||||||
|
}
|
||||||
mutex_unlock(&sqd->lock);
|
mutex_unlock(&sqd->lock);
|
||||||
wait_for_completion(&sqd->exited);
|
wait_for_completion(&sqd->exited);
|
||||||
}
|
}
|
||||||
@@ -168,7 +177,38 @@ static inline bool io_sqd_events_pending(struct io_sq_data *sqd)
|
|||||||
return READ_ONCE(sqd->state);
|
return READ_ONCE(sqd->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries)
|
struct io_sq_time {
|
||||||
|
bool started;
|
||||||
|
u64 usec;
|
||||||
|
};
|
||||||
|
|
||||||
|
u64 io_sq_cpu_usec(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
u64 utime, stime;
|
||||||
|
|
||||||
|
task_cputime_adjusted(tsk, &utime, &stime);
|
||||||
|
do_div(stime, 1000);
|
||||||
|
return stime;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void io_sq_update_worktime(struct io_sq_data *sqd, struct io_sq_time *ist)
|
||||||
|
{
|
||||||
|
if (!ist->started)
|
||||||
|
return;
|
||||||
|
ist->started = false;
|
||||||
|
sqd->work_time += io_sq_cpu_usec(current) - ist->usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void io_sq_start_worktime(struct io_sq_time *ist)
|
||||||
|
{
|
||||||
|
if (ist->started)
|
||||||
|
return;
|
||||||
|
ist->started = true;
|
||||||
|
ist->usec = io_sq_cpu_usec(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __io_sq_thread(struct io_ring_ctx *ctx, struct io_sq_data *sqd,
|
||||||
|
bool cap_entries, struct io_sq_time *ist)
|
||||||
{
|
{
|
||||||
unsigned int to_submit;
|
unsigned int to_submit;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -181,6 +221,8 @@ static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries)
|
|||||||
if (to_submit || !wq_list_empty(&ctx->iopoll_list)) {
|
if (to_submit || !wq_list_empty(&ctx->iopoll_list)) {
|
||||||
const struct cred *creds = NULL;
|
const struct cred *creds = NULL;
|
||||||
|
|
||||||
|
io_sq_start_worktime(ist);
|
||||||
|
|
||||||
if (ctx->sq_creds != current_cred())
|
if (ctx->sq_creds != current_cred())
|
||||||
creds = override_creds(ctx->sq_creds);
|
creds = override_creds(ctx->sq_creds);
|
||||||
|
|
||||||
@@ -254,23 +296,11 @@ static bool io_sq_tw_pending(struct llist_node *retry_list)
|
|||||||
return retry_list || !llist_empty(&tctx->task_list);
|
return retry_list || !llist_empty(&tctx->task_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_sq_update_worktime(struct io_sq_data *sqd, struct rusage *start)
|
|
||||||
{
|
|
||||||
struct rusage end;
|
|
||||||
|
|
||||||
getrusage(current, RUSAGE_SELF, &end);
|
|
||||||
end.ru_stime.tv_sec -= start->ru_stime.tv_sec;
|
|
||||||
end.ru_stime.tv_usec -= start->ru_stime.tv_usec;
|
|
||||||
|
|
||||||
sqd->work_time += end.ru_stime.tv_usec + end.ru_stime.tv_sec * 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int io_sq_thread(void *data)
|
static int io_sq_thread(void *data)
|
||||||
{
|
{
|
||||||
struct llist_node *retry_list = NULL;
|
struct llist_node *retry_list = NULL;
|
||||||
struct io_sq_data *sqd = data;
|
struct io_sq_data *sqd = data;
|
||||||
struct io_ring_ctx *ctx;
|
struct io_ring_ctx *ctx;
|
||||||
struct rusage start;
|
|
||||||
unsigned long timeout = 0;
|
unsigned long timeout = 0;
|
||||||
char buf[TASK_COMM_LEN] = {};
|
char buf[TASK_COMM_LEN] = {};
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
@@ -278,7 +308,8 @@ static int io_sq_thread(void *data)
|
|||||||
/* offload context creation failed, just exit */
|
/* offload context creation failed, just exit */
|
||||||
if (!current->io_uring) {
|
if (!current->io_uring) {
|
||||||
mutex_lock(&sqd->lock);
|
mutex_lock(&sqd->lock);
|
||||||
sqd->thread = NULL;
|
rcu_assign_pointer(sqd->thread, NULL);
|
||||||
|
put_task_struct(current);
|
||||||
mutex_unlock(&sqd->lock);
|
mutex_unlock(&sqd->lock);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@@ -307,6 +338,7 @@ static int io_sq_thread(void *data)
|
|||||||
mutex_lock(&sqd->lock);
|
mutex_lock(&sqd->lock);
|
||||||
while (1) {
|
while (1) {
|
||||||
bool cap_entries, sqt_spin = false;
|
bool cap_entries, sqt_spin = false;
|
||||||
|
struct io_sq_time ist = { };
|
||||||
|
|
||||||
if (io_sqd_events_pending(sqd) || signal_pending(current)) {
|
if (io_sqd_events_pending(sqd) || signal_pending(current)) {
|
||||||
if (io_sqd_handle_event(sqd))
|
if (io_sqd_handle_event(sqd))
|
||||||
@@ -315,9 +347,8 @@ static int io_sq_thread(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cap_entries = !list_is_singular(&sqd->ctx_list);
|
cap_entries = !list_is_singular(&sqd->ctx_list);
|
||||||
getrusage(current, RUSAGE_SELF, &start);
|
|
||||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
|
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
|
||||||
int ret = __io_sq_thread(ctx, cap_entries);
|
int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist);
|
||||||
|
|
||||||
if (!sqt_spin && (ret > 0 || !wq_list_empty(&ctx->iopoll_list)))
|
if (!sqt_spin && (ret > 0 || !wq_list_empty(&ctx->iopoll_list)))
|
||||||
sqt_spin = true;
|
sqt_spin = true;
|
||||||
@@ -325,15 +356,18 @@ static int io_sq_thread(void *data)
|
|||||||
if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE))
|
if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE))
|
||||||
sqt_spin = true;
|
sqt_spin = true;
|
||||||
|
|
||||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
|
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
|
||||||
if (io_napi(ctx))
|
if (io_napi(ctx)) {
|
||||||
|
io_sq_start_worktime(&ist);
|
||||||
io_napi_sqpoll_busy_poll(ctx);
|
io_napi_sqpoll_busy_poll(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io_sq_update_worktime(sqd, &ist);
|
||||||
|
|
||||||
if (sqt_spin || !time_after(jiffies, timeout)) {
|
if (sqt_spin || !time_after(jiffies, timeout)) {
|
||||||
if (sqt_spin) {
|
if (sqt_spin)
|
||||||
io_sq_update_worktime(sqd, &start);
|
|
||||||
timeout = jiffies + sqd->sq_thread_idle;
|
timeout = jiffies + sqd->sq_thread_idle;
|
||||||
}
|
|
||||||
if (unlikely(need_resched())) {
|
if (unlikely(need_resched())) {
|
||||||
mutex_unlock(&sqd->lock);
|
mutex_unlock(&sqd->lock);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@@ -387,7 +421,8 @@ static int io_sq_thread(void *data)
|
|||||||
io_sq_tw(&retry_list, UINT_MAX);
|
io_sq_tw(&retry_list, UINT_MAX);
|
||||||
|
|
||||||
io_uring_cancel_generic(true, sqd);
|
io_uring_cancel_generic(true, sqd);
|
||||||
sqd->thread = NULL;
|
rcu_assign_pointer(sqd->thread, NULL);
|
||||||
|
put_task_struct(current);
|
||||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
|
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
|
||||||
atomic_or(IORING_SQ_NEED_WAKEUP, &ctx->rings->sq_flags);
|
atomic_or(IORING_SQ_NEED_WAKEUP, &ctx->rings->sq_flags);
|
||||||
io_run_task_work();
|
io_run_task_work();
|
||||||
@@ -417,7 +452,6 @@ void io_sqpoll_wait_sq(struct io_ring_ctx *ctx)
|
|||||||
__cold int io_sq_offload_create(struct io_ring_ctx *ctx,
|
__cold int io_sq_offload_create(struct io_ring_ctx *ctx,
|
||||||
struct io_uring_params *p)
|
struct io_uring_params *p)
|
||||||
{
|
{
|
||||||
struct task_struct *task_to_put = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Retain compatibility with failing for an invalid attach attempt */
|
/* Retain compatibility with failing for an invalid attach attempt */
|
||||||
@@ -497,8 +531,11 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
|
|||||||
goto err_sqpoll;
|
goto err_sqpoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqd->thread = tsk;
|
mutex_lock(&sqd->lock);
|
||||||
task_to_put = get_task_struct(tsk);
|
rcu_assign_pointer(sqd->thread, tsk);
|
||||||
|
mutex_unlock(&sqd->lock);
|
||||||
|
|
||||||
|
get_task_struct(tsk);
|
||||||
ret = io_uring_alloc_task_context(tsk, ctx);
|
ret = io_uring_alloc_task_context(tsk, ctx);
|
||||||
wake_up_new_task(tsk);
|
wake_up_new_task(tsk);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -508,16 +545,11 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task_to_put)
|
|
||||||
put_task_struct(task_to_put);
|
|
||||||
return 0;
|
return 0;
|
||||||
err_sqpoll:
|
err_sqpoll:
|
||||||
complete(&ctx->sq_data->exited);
|
complete(&ctx->sq_data->exited);
|
||||||
err:
|
err:
|
||||||
io_sq_thread_finish(ctx);
|
io_sq_thread_finish(ctx);
|
||||||
if (task_to_put)
|
|
||||||
put_task_struct(task_to_put);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,10 +560,13 @@ __cold int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx,
|
|||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
if (sqd) {
|
if (sqd) {
|
||||||
|
struct task_struct *tsk;
|
||||||
|
|
||||||
io_sq_thread_park(sqd);
|
io_sq_thread_park(sqd);
|
||||||
/* Don't set affinity for a dying thread */
|
/* Don't set affinity for a dying thread */
|
||||||
if (sqd->thread)
|
tsk = sqpoll_task_locked(sqd);
|
||||||
ret = io_wq_cpu_affinity(sqd->thread->io_uring, mask);
|
if (tsk)
|
||||||
|
ret = io_wq_cpu_affinity(tsk->io_uring, mask);
|
||||||
io_sq_thread_unpark(sqd);
|
io_sq_thread_unpark(sqd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -8,7 +8,7 @@ struct io_sq_data {
|
|||||||
/* ctx's that are using this sqd */
|
/* ctx's that are using this sqd */
|
||||||
struct list_head ctx_list;
|
struct list_head ctx_list;
|
||||||
|
|
||||||
struct task_struct *thread;
|
struct task_struct __rcu *thread;
|
||||||
struct wait_queue_head wait;
|
struct wait_queue_head wait;
|
||||||
|
|
||||||
unsigned sq_thread_idle;
|
unsigned sq_thread_idle;
|
||||||
@@ -29,3 +29,10 @@ void io_sq_thread_unpark(struct io_sq_data *sqd);
|
|||||||
void io_put_sq_data(struct io_sq_data *sqd);
|
void io_put_sq_data(struct io_sq_data *sqd);
|
||||||
void io_sqpoll_wait_sq(struct io_ring_ctx *ctx);
|
void io_sqpoll_wait_sq(struct io_ring_ctx *ctx);
|
||||||
int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, cpumask_var_t mask);
|
int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, cpumask_var_t mask);
|
||||||
|
|
||||||
|
static inline struct task_struct *sqpoll_task_locked(struct io_sq_data *sqd)
|
||||||
|
{
|
||||||
|
return rcu_dereference_protected(sqd->thread,
|
||||||
|
lockdep_is_held(&sqd->lock));
|
||||||
|
}
|
||||||
|
u64 io_sq_cpu_usec(struct task_struct *tsk);
|
||||||
|
|||||||
+1
-1
@@ -319,7 +319,7 @@ static void io_req_task_link_timeout(struct io_kiocb *req, io_tw_token_t tw)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
if (!io_should_terminate_tw()) {
|
if (!io_should_terminate_tw(req->ctx)) {
|
||||||
struct io_cancel_data cd = {
|
struct io_cancel_data cd = {
|
||||||
.ctx = req->ctx,
|
.ctx = req->ctx,
|
||||||
.data = prev->cqe.user_data,
|
.data = prev->cqe.user_data,
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ static void io_uring_cmd_work(struct io_kiocb *req, io_tw_token_t tw)
|
|||||||
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
|
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
|
||||||
unsigned int flags = IO_URING_F_COMPLETE_DEFER;
|
unsigned int flags = IO_URING_F_COMPLETE_DEFER;
|
||||||
|
|
||||||
if (io_should_terminate_tw())
|
if (io_should_terminate_tw(req->ctx))
|
||||||
flags |= IO_URING_F_TASK_DEAD;
|
flags |= IO_URING_F_TASK_DEAD;
|
||||||
|
|
||||||
/* task_work executor checks the deffered list completion */
|
/* task_work executor checks the deffered list completion */
|
||||||
|
|||||||
+1
-1
@@ -252,7 +252,7 @@ int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
iwa = io_uring_alloc_async_data(NULL, req);
|
iwa = io_uring_alloc_async_data(NULL, req);
|
||||||
if (!unlikely(iwa))
|
if (unlikely(!iwa))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
iwa->req = req;
|
iwa->req = req;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user