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/mm.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/blk-integrity.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mpage.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))
|
||||
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);
|
||||
if (ret)
|
||||
|
||||
+2
-1
@@ -147,7 +147,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
||||
/* Expect random access pattern */
|
||||
#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 */
|
||||
#define FMODE_PATH ((__force fmode_t)(1 << 14))
|
||||
|
||||
@@ -415,9 +415,6 @@ struct io_ring_ctx {
|
||||
struct callback_head poll_wq_task_work;
|
||||
struct list_head defer_list;
|
||||
|
||||
struct io_alloc_cache msg_cache;
|
||||
spinlock_t msg_lock;
|
||||
|
||||
#ifdef CONFIG_NET_RX_BUSY_POLL
|
||||
struct list_head napi_list; /* track busy poll napi_id */
|
||||
spinlock_t napi_lock; /* napi_list lock */
|
||||
|
||||
@@ -50,7 +50,7 @@ struct io_uring_sqe {
|
||||
};
|
||||
__u32 len; /* buffer size or number of iovecs */
|
||||
union {
|
||||
__kernel_rwf_t rw_flags;
|
||||
__u32 rw_flags;
|
||||
__u32 fsync_flags;
|
||||
__u16 poll_events; /* compatibility */
|
||||
__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 \
|
||||
sqpoll.o xattr.o nop.o fs.o splice.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 \
|
||||
truncate.o memmap.o alloc_cache.o
|
||||
obj-$(CONFIG_IO_WQ) += io-wq.o
|
||||
obj-$(CONFIG_FUTEX) += futex.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 "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
|
||||
static __cold void common_tracking_show_fdinfo(struct io_ring_ctx *ctx,
|
||||
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_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_head = READ_ONCE(r->sq.head);
|
||||
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) {
|
||||
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
|
||||
* 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_cpu = sq->sq_cpu;
|
||||
getrusage(sq->thread, RUSAGE_SELF, &sq_usage);
|
||||
sq_total_time = (sq_usage.ru_stime.tv_sec * 1000000
|
||||
+ sq_usage.ru_stime.tv_usec);
|
||||
sq_total_time = usec;
|
||||
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
|
||||
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");
|
||||
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);
|
||||
}
|
||||
}
|
||||
#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,
|
||||
u32 slot_index)
|
||||
__must_hold(&req->ctx->uring_lock)
|
||||
__must_hold(&ctx->uring_lock)
|
||||
{
|
||||
struct io_rsrc_node *node;
|
||||
|
||||
|
||||
+3
-3
@@ -916,11 +916,11 @@ static bool io_wq_for_each_worker(struct io_wq *wq,
|
||||
void *data)
|
||||
{
|
||||
for (int i = 0; i < IO_WQ_ACCT_NR; i++) {
|
||||
if (!io_acct_for_each_worker(&wq->acct[i], func, data))
|
||||
return false;
|
||||
if (io_acct_for_each_worker(&wq->acct[i], func, data))
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
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->rw_cache, io_rw_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_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,
|
||||
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_rsrc_cache_init(ctx);
|
||||
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)
|
||||
{
|
||||
io_tw_lock(req->ctx, tw);
|
||||
if (unlikely(io_should_terminate_tw()))
|
||||
struct io_ring_ctx *ctx = req->ctx;
|
||||
|
||||
io_tw_lock(ctx, tw);
|
||||
if (unlikely(io_should_terminate_tw(ctx)))
|
||||
io_req_defer_failed(req, -EFAULT);
|
||||
else if (req->flags & REQ_F_FORCE_ASYNC)
|
||||
io_queue_iowq(req);
|
||||
@@ -2444,6 +2442,9 @@ static enum hrtimer_restart io_cqring_min_timer_wakeup(struct hrtimer *timer)
|
||||
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_set_expires(timer, iowq->timeout);
|
||||
return HRTIMER_RESTART;
|
||||
@@ -2901,7 +2902,7 @@ static __cold void io_ring_exit_work(struct work_struct *work)
|
||||
struct task_struct *tsk;
|
||||
|
||||
io_sq_thread_park(sqd);
|
||||
tsk = sqd->thread;
|
||||
tsk = sqpoll_task_locked(sqd);
|
||||
if (tsk && tsk->io_uring && tsk->io_uring->io_wq)
|
||||
io_wq_cancel_cb(tsk->io_uring->io_wq,
|
||||
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;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
WARN_ON_ONCE(sqd && sqd->thread != current);
|
||||
WARN_ON_ONCE(sqd && sqpoll_task_locked(sqd) != current);
|
||||
|
||||
if (!current->io_uring)
|
||||
return;
|
||||
@@ -3504,10 +3505,6 @@ static __cold int io_allocate_scq_urings(struct io_ring_ctx *ctx,
|
||||
|
||||
if (!(ctx->flags & IORING_SETUP_NO_SQARRAY))
|
||||
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)
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+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
|
||||
* 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)
|
||||
|
||||
+5
-5
@@ -44,7 +44,7 @@ static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len)
|
||||
buf_len -= this_len;
|
||||
/* Stop looping for invalid buffer length of 0 */
|
||||
if (buf_len || !this_len) {
|
||||
buf->addr += this_len;
|
||||
buf->addr = READ_ONCE(buf->addr) + this_len;
|
||||
buf->len = buf_len;
|
||||
return false;
|
||||
}
|
||||
@@ -178,8 +178,8 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len,
|
||||
*len = buf_len;
|
||||
req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT;
|
||||
req->buf_list = bl;
|
||||
req->buf_index = buf->bid;
|
||||
ret = u64_to_user_ptr(buf->addr);
|
||||
req->buf_index = READ_ONCE(buf->bid);
|
||||
ret = u64_to_user_ptr(READ_ONCE(buf->addr));
|
||||
|
||||
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)
|
||||
arg->max_len = INT_MAX;
|
||||
|
||||
req->buf_index = buf->bid;
|
||||
req->buf_index = READ_ONCE(buf->bid);
|
||||
do {
|
||||
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;
|
||||
}
|
||||
|
||||
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++;
|
||||
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ static int io_region_pin_pages(struct io_ring_ctx *ctx,
|
||||
struct io_mapped_region *mr,
|
||||
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;
|
||||
int nr_pages;
|
||||
|
||||
|
||||
+2
-22
@@ -11,7 +11,6 @@
|
||||
#include "io_uring.h"
|
||||
#include "rsrc.h"
|
||||
#include "filetable.h"
|
||||
#include "alloc_cache.h"
|
||||
#include "msg_ring.h"
|
||||
|
||||
/* 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;
|
||||
|
||||
io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags);
|
||||
if (spin_trylock(&ctx->msg_lock)) {
|
||||
if (io_alloc_cache_put(&ctx->msg_cache, req))
|
||||
req = NULL;
|
||||
spin_unlock(&ctx->msg_lock);
|
||||
}
|
||||
if (req)
|
||||
kfree_rcu(req, rcu_head);
|
||||
kfree_rcu(req, rcu_head);
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
struct io_msg *msg)
|
||||
{
|
||||
struct io_kiocb *target;
|
||||
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))
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
+15
-12
@@ -468,6 +468,15 @@ static int io_bundle_nbufs(struct io_async_msghdr *kmsg, int ret)
|
||||
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,
|
||||
struct io_async_msghdr *kmsg,
|
||||
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_control = NULL;
|
||||
sr->done_io += ret;
|
||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||
return -EAGAIN;
|
||||
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
ret = -EINTR;
|
||||
@@ -647,8 +655,7 @@ retry_bundle:
|
||||
sr->len -= ret;
|
||||
sr->buf += ret;
|
||||
sr->done_io += ret;
|
||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||
return -EAGAIN;
|
||||
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
ret = -EINTR;
|
||||
@@ -1020,8 +1027,7 @@ retry_multishot:
|
||||
}
|
||||
if (ret > 0 && io_net_retry(sock, flags)) {
|
||||
sr->done_io += ret;
|
||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||
return IOU_RETRY;
|
||||
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
ret = -EINTR;
|
||||
@@ -1158,8 +1164,7 @@ retry_multishot:
|
||||
sr->len -= ret;
|
||||
sr->buf += ret;
|
||||
sr->done_io += ret;
|
||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||
return -EAGAIN;
|
||||
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
ret = -EINTR;
|
||||
@@ -1377,8 +1382,7 @@ int io_send_zc(struct io_kiocb *req, unsigned int issue_flags)
|
||||
zc->len -= ret;
|
||||
zc->buf += ret;
|
||||
zc->done_io += ret;
|
||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||
return -EAGAIN;
|
||||
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
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)) {
|
||||
sr->done_io += ret;
|
||||
req->flags |= REQ_F_BL_NO_RECYCLE;
|
||||
return -EAGAIN;
|
||||
return io_net_kbuf_recyle(req, kmsg, ret);
|
||||
}
|
||||
if (ret == -ERESTARTSYS)
|
||||
ret = -EINTR;
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ static int io_link_skb(struct sk_buff *skb, struct ubuf_info *uarg)
|
||||
return -EEXIST;
|
||||
|
||||
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 */
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
req->flags |= REQ_F_NEED_CLEANUP;
|
||||
|
||||
open->file_slot = READ_ONCE(sqe->file_index);
|
||||
if (open->file_slot && (open->how.flags & O_CLOEXEC))
|
||||
return -EINVAL;
|
||||
|
||||
open->nofile = rlimit(RLIMIT_NOFILE);
|
||||
req->flags |= REQ_F_NEED_CLEANUP;
|
||||
if (io_openat_force_async(open))
|
||||
req->flags |= REQ_F_FORCE_ASYNC;
|
||||
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;
|
||||
|
||||
if (unlikely(io_should_terminate_tw()))
|
||||
if (unlikely(io_should_terminate_tw(req->ctx)))
|
||||
return -ECANCELED;
|
||||
|
||||
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);
|
||||
/* successfully updated, don't complete poll request */
|
||||
if (!ret2 || ret2 == -EIOCBQUEUED)
|
||||
if (ret2 == IOU_ISSUE_SKIP_COMPLETE)
|
||||
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);
|
||||
complete:
|
||||
if (preq->cqe.res < 0)
|
||||
req_set_fail(preq);
|
||||
preq->io_task_work.func = io_req_task_complete;
|
||||
io_req_task_work_add(preq);
|
||||
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) {
|
||||
sqd = ctx->sq_data;
|
||||
if (sqd) {
|
||||
struct task_struct *tsk;
|
||||
|
||||
/*
|
||||
* Observe the correct sqd->lock -> ctx->uring_lock
|
||||
* 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_lock(&sqd->lock);
|
||||
mutex_lock(&ctx->uring_lock);
|
||||
if (sqd->thread)
|
||||
tctx = sqd->thread->io_uring;
|
||||
tsk = sqpoll_task_locked(sqd);
|
||||
if (tsk)
|
||||
tctx = tsk->io_uring;
|
||||
}
|
||||
} else {
|
||||
tctx = current->io_uring;
|
||||
@@ -614,6 +617,7 @@ static int io_register_mem_region(struct io_ring_ctx *ctx, void __user *uarg)
|
||||
if (ret)
|
||||
return ret;
|
||||
if (copy_to_user(rd_uptr, &rd, sizeof(rd))) {
|
||||
guard(mutex)(&ctx->mmap_lock);
|
||||
io_free_region(ctx, &ctx->param_region);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
+32
-12
@@ -55,7 +55,7 @@ int __io_account_mem(struct user_struct *user, unsigned long nr_pages)
|
||||
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)
|
||||
__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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -931,8 +931,8 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
|
||||
struct req_iterator rq_iter;
|
||||
struct io_mapped_ubuf *imu;
|
||||
struct io_rsrc_node *node;
|
||||
struct bio_vec bv, *bvec;
|
||||
u16 nr_bvecs;
|
||||
struct bio_vec bv;
|
||||
unsigned int nr_bvecs = 0;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
kfree(node);
|
||||
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->acct_pages = 0;
|
||||
imu->folio_shift = PAGE_SHIFT;
|
||||
imu->nr_bvecs = nr_bvecs;
|
||||
refcount_set(&imu->refs, 1);
|
||||
imu->release = release;
|
||||
imu->priv = rq;
|
||||
imu->is_kbuf = true;
|
||||
imu->dir = 1 << rq_data_dir(rq);
|
||||
|
||||
bvec = imu->bvec;
|
||||
rq_for_each_bvec(bv, rq, rq_iter)
|
||||
*bvec++ = bv;
|
||||
imu->bvec[nr_bvecs++] = bv;
|
||||
imu->nr_bvecs = nr_bvecs;
|
||||
|
||||
node->buf = imu;
|
||||
data->nodes[index] = node;
|
||||
@@ -1043,6 +1045,7 @@ static int io_import_kbuf(int ddir, struct iov_iter *iter,
|
||||
if (count < imu->len) {
|
||||
const struct bio_vec *bvec = iter->bvec;
|
||||
|
||||
len += iter->iov_offset;
|
||||
while (len > bvec->bv_len) {
|
||||
len -= bvec->bv_len;
|
||||
bvec++;
|
||||
@@ -1181,7 +1184,7 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx
|
||||
if (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++) {
|
||||
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++;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* 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;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < nr_iovs; i++)
|
||||
for (i = 0; i < nr_iovs; i++) {
|
||||
max_segs += (iov[i].iov_len >> shift) + 2;
|
||||
if (max_segs > INT_MAX)
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
return max_segs;
|
||||
}
|
||||
|
||||
@@ -1494,7 +1510,11 @@ int io_import_reg_vec(int ddir, struct iov_iter *iter,
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
} 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)) {
|
||||
|
||||
@@ -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_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,
|
||||
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->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);
|
||||
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)
|
||||
{
|
||||
struct io_async_rw *rw = req->async_data;
|
||||
|
||||
lockdep_assert_held(&req->ctx->uring_lock);
|
||||
io_vec_free(&rw->vec);
|
||||
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)
|
||||
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;
|
||||
} else {
|
||||
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) {
|
||||
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
|
||||
* in io_async_rw, so fail it here.
|
||||
|
||||
+74
-39
@@ -11,6 +11,7 @@
|
||||
#include <linux/audit.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/cpuset.h>
|
||||
#include <linux/sched/cputime.h>
|
||||
#include <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)
|
||||
__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
|
||||
@@ -46,24 +47,32 @@ void io_sq_thread_unpark(struct io_sq_data *sqd)
|
||||
void io_sq_thread_park(struct io_sq_data *sqd)
|
||||
__acquires(&sqd->lock)
|
||||
{
|
||||
WARN_ON_ONCE(data_race(sqd->thread) == current);
|
||||
struct task_struct *tsk;
|
||||
|
||||
atomic_inc(&sqd->park_pending);
|
||||
set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state);
|
||||
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)
|
||||
{
|
||||
WARN_ON_ONCE(sqd->thread == current);
|
||||
struct task_struct *tsk;
|
||||
|
||||
WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state));
|
||||
|
||||
set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state);
|
||||
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);
|
||||
}
|
||||
mutex_unlock(&sqd->lock);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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)) {
|
||||
const struct cred *creds = NULL;
|
||||
|
||||
io_sq_start_worktime(ist);
|
||||
|
||||
if (ctx->sq_creds != current_cred())
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct llist_node *retry_list = NULL;
|
||||
struct io_sq_data *sqd = data;
|
||||
struct io_ring_ctx *ctx;
|
||||
struct rusage start;
|
||||
unsigned long timeout = 0;
|
||||
char buf[TASK_COMM_LEN] = {};
|
||||
DEFINE_WAIT(wait);
|
||||
@@ -278,7 +308,8 @@ static int io_sq_thread(void *data)
|
||||
/* offload context creation failed, just exit */
|
||||
if (!current->io_uring) {
|
||||
mutex_lock(&sqd->lock);
|
||||
sqd->thread = NULL;
|
||||
rcu_assign_pointer(sqd->thread, NULL);
|
||||
put_task_struct(current);
|
||||
mutex_unlock(&sqd->lock);
|
||||
goto err_out;
|
||||
}
|
||||
@@ -307,6 +338,7 @@ static int io_sq_thread(void *data)
|
||||
mutex_lock(&sqd->lock);
|
||||
while (1) {
|
||||
bool cap_entries, sqt_spin = false;
|
||||
struct io_sq_time ist = { };
|
||||
|
||||
if (io_sqd_events_pending(sqd) || signal_pending(current)) {
|
||||
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);
|
||||
getrusage(current, RUSAGE_SELF, &start);
|
||||
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)))
|
||||
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))
|
||||
sqt_spin = true;
|
||||
|
||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
|
||||
if (io_napi(ctx))
|
||||
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
|
||||
if (io_napi(ctx)) {
|
||||
io_sq_start_worktime(&ist);
|
||||
io_napi_sqpoll_busy_poll(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
io_sq_update_worktime(sqd, &ist);
|
||||
|
||||
if (sqt_spin || !time_after(jiffies, timeout)) {
|
||||
if (sqt_spin) {
|
||||
io_sq_update_worktime(sqd, &start);
|
||||
if (sqt_spin)
|
||||
timeout = jiffies + sqd->sq_thread_idle;
|
||||
}
|
||||
if (unlikely(need_resched())) {
|
||||
mutex_unlock(&sqd->lock);
|
||||
cond_resched();
|
||||
@@ -387,7 +421,8 @@ static int io_sq_thread(void *data)
|
||||
io_sq_tw(&retry_list, UINT_MAX);
|
||||
|
||||
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)
|
||||
atomic_or(IORING_SQ_NEED_WAKEUP, &ctx->rings->sq_flags);
|
||||
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,
|
||||
struct io_uring_params *p)
|
||||
{
|
||||
struct task_struct *task_to_put = NULL;
|
||||
int ret;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
sqd->thread = tsk;
|
||||
task_to_put = get_task_struct(tsk);
|
||||
mutex_lock(&sqd->lock);
|
||||
rcu_assign_pointer(sqd->thread, tsk);
|
||||
mutex_unlock(&sqd->lock);
|
||||
|
||||
get_task_struct(tsk);
|
||||
ret = io_uring_alloc_task_context(tsk, ctx);
|
||||
wake_up_new_task(tsk);
|
||||
if (ret)
|
||||
@@ -508,16 +545,11 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (task_to_put)
|
||||
put_task_struct(task_to_put);
|
||||
return 0;
|
||||
err_sqpoll:
|
||||
complete(&ctx->sq_data->exited);
|
||||
err:
|
||||
io_sq_thread_finish(ctx);
|
||||
if (task_to_put)
|
||||
put_task_struct(task_to_put);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -528,10 +560,13 @@ __cold int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx,
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (sqd) {
|
||||
struct task_struct *tsk;
|
||||
|
||||
io_sq_thread_park(sqd);
|
||||
/* Don't set affinity for a dying thread */
|
||||
if (sqd->thread)
|
||||
ret = io_wq_cpu_affinity(sqd->thread->io_uring, mask);
|
||||
tsk = sqpoll_task_locked(sqd);
|
||||
if (tsk)
|
||||
ret = io_wq_cpu_affinity(tsk->io_uring, mask);
|
||||
io_sq_thread_unpark(sqd);
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -8,7 +8,7 @@ struct io_sq_data {
|
||||
/* ctx's that are using this sqd */
|
||||
struct list_head ctx_list;
|
||||
|
||||
struct task_struct *thread;
|
||||
struct task_struct __rcu *thread;
|
||||
struct wait_queue_head wait;
|
||||
|
||||
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_sqpoll_wait_sq(struct io_ring_ctx *ctx);
|
||||
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;
|
||||
|
||||
if (prev) {
|
||||
if (!io_should_terminate_tw()) {
|
||||
if (!io_should_terminate_tw(req->ctx)) {
|
||||
struct io_cancel_data cd = {
|
||||
.ctx = req->ctx,
|
||||
.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);
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
iwa = io_uring_alloc_async_data(NULL, req);
|
||||
if (!unlikely(iwa))
|
||||
if (unlikely(!iwa))
|
||||
return -ENOMEM;
|
||||
iwa->req = req;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user