162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Contains the core associated with submission side polling of the SQ 462306a36Sopenharmony_ci * ring, offloading submissions from the application to a kernel thread. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#include <linux/errno.h> 862306a36Sopenharmony_ci#include <linux/file.h> 962306a36Sopenharmony_ci#include <linux/mm.h> 1062306a36Sopenharmony_ci#include <linux/slab.h> 1162306a36Sopenharmony_ci#include <linux/audit.h> 1262306a36Sopenharmony_ci#include <linux/security.h> 1362306a36Sopenharmony_ci#include <linux/io_uring.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <uapi/linux/io_uring.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "io_uring.h" 1862306a36Sopenharmony_ci#include "sqpoll.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define IORING_SQPOLL_CAP_ENTRIES_VALUE 8 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cienum { 2362306a36Sopenharmony_ci IO_SQ_THREAD_SHOULD_STOP = 0, 2462306a36Sopenharmony_ci IO_SQ_THREAD_SHOULD_PARK, 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_civoid io_sq_thread_unpark(struct io_sq_data *sqd) 2862306a36Sopenharmony_ci __releases(&sqd->lock) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci WARN_ON_ONCE(sqd->thread == current); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci /* 3362306a36Sopenharmony_ci * Do the dance but not conditional clear_bit() because it'd race with 3462306a36Sopenharmony_ci * other threads incrementing park_pending and setting the bit. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci clear_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state); 3762306a36Sopenharmony_ci if (atomic_dec_return(&sqd->park_pending)) 3862306a36Sopenharmony_ci set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state); 3962306a36Sopenharmony_ci mutex_unlock(&sqd->lock); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_civoid io_sq_thread_park(struct io_sq_data *sqd) 4362306a36Sopenharmony_ci __acquires(&sqd->lock) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci WARN_ON_ONCE(sqd->thread == current); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci atomic_inc(&sqd->park_pending); 4862306a36Sopenharmony_ci set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state); 4962306a36Sopenharmony_ci mutex_lock(&sqd->lock); 5062306a36Sopenharmony_ci if (sqd->thread) 5162306a36Sopenharmony_ci wake_up_process(sqd->thread); 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_civoid io_sq_thread_stop(struct io_sq_data *sqd) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci WARN_ON_ONCE(sqd->thread == current); 5762306a36Sopenharmony_ci WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state)); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state); 6062306a36Sopenharmony_ci mutex_lock(&sqd->lock); 6162306a36Sopenharmony_ci if (sqd->thread) 6262306a36Sopenharmony_ci wake_up_process(sqd->thread); 6362306a36Sopenharmony_ci mutex_unlock(&sqd->lock); 6462306a36Sopenharmony_ci wait_for_completion(&sqd->exited); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_civoid io_put_sq_data(struct io_sq_data *sqd) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci if (refcount_dec_and_test(&sqd->refs)) { 7062306a36Sopenharmony_ci WARN_ON_ONCE(atomic_read(&sqd->park_pending)); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci io_sq_thread_stop(sqd); 7362306a36Sopenharmony_ci kfree(sqd); 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic __cold void io_sqd_update_thread_idle(struct io_sq_data *sqd) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct io_ring_ctx *ctx; 8062306a36Sopenharmony_ci unsigned sq_thread_idle = 0; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) 8362306a36Sopenharmony_ci sq_thread_idle = max(sq_thread_idle, ctx->sq_thread_idle); 8462306a36Sopenharmony_ci sqd->sq_thread_idle = sq_thread_idle; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid io_sq_thread_finish(struct io_ring_ctx *ctx) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci struct io_sq_data *sqd = ctx->sq_data; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (sqd) { 9262306a36Sopenharmony_ci io_sq_thread_park(sqd); 9362306a36Sopenharmony_ci list_del_init(&ctx->sqd_list); 9462306a36Sopenharmony_ci io_sqd_update_thread_idle(sqd); 9562306a36Sopenharmony_ci io_sq_thread_unpark(sqd); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci io_put_sq_data(sqd); 9862306a36Sopenharmony_ci ctx->sq_data = NULL; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic struct io_sq_data *io_attach_sq_data(struct io_uring_params *p) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct io_ring_ctx *ctx_attach; 10562306a36Sopenharmony_ci struct io_sq_data *sqd; 10662306a36Sopenharmony_ci struct fd f; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci f = fdget(p->wq_fd); 10962306a36Sopenharmony_ci if (!f.file) 11062306a36Sopenharmony_ci return ERR_PTR(-ENXIO); 11162306a36Sopenharmony_ci if (!io_is_uring_fops(f.file)) { 11262306a36Sopenharmony_ci fdput(f); 11362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci ctx_attach = f.file->private_data; 11762306a36Sopenharmony_ci sqd = ctx_attach->sq_data; 11862306a36Sopenharmony_ci if (!sqd) { 11962306a36Sopenharmony_ci fdput(f); 12062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci if (sqd->task_tgid != current->tgid) { 12362306a36Sopenharmony_ci fdput(f); 12462306a36Sopenharmony_ci return ERR_PTR(-EPERM); 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci refcount_inc(&sqd->refs); 12862306a36Sopenharmony_ci fdput(f); 12962306a36Sopenharmony_ci return sqd; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic struct io_sq_data *io_get_sq_data(struct io_uring_params *p, 13362306a36Sopenharmony_ci bool *attached) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci struct io_sq_data *sqd; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci *attached = false; 13862306a36Sopenharmony_ci if (p->flags & IORING_SETUP_ATTACH_WQ) { 13962306a36Sopenharmony_ci sqd = io_attach_sq_data(p); 14062306a36Sopenharmony_ci if (!IS_ERR(sqd)) { 14162306a36Sopenharmony_ci *attached = true; 14262306a36Sopenharmony_ci return sqd; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci /* fall through for EPERM case, setup new sqd/task */ 14562306a36Sopenharmony_ci if (PTR_ERR(sqd) != -EPERM) 14662306a36Sopenharmony_ci return sqd; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci sqd = kzalloc(sizeof(*sqd), GFP_KERNEL); 15062306a36Sopenharmony_ci if (!sqd) 15162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci atomic_set(&sqd->park_pending, 0); 15462306a36Sopenharmony_ci refcount_set(&sqd->refs, 1); 15562306a36Sopenharmony_ci INIT_LIST_HEAD(&sqd->ctx_list); 15662306a36Sopenharmony_ci mutex_init(&sqd->lock); 15762306a36Sopenharmony_ci init_waitqueue_head(&sqd->wait); 15862306a36Sopenharmony_ci init_completion(&sqd->exited); 15962306a36Sopenharmony_ci return sqd; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic inline bool io_sqd_events_pending(struct io_sq_data *sqd) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci return READ_ONCE(sqd->state); 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci unsigned int to_submit; 17062306a36Sopenharmony_ci int ret = 0; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci to_submit = io_sqring_entries(ctx); 17362306a36Sopenharmony_ci /* if we're handling multiple rings, cap submit size for fairness */ 17462306a36Sopenharmony_ci if (cap_entries && to_submit > IORING_SQPOLL_CAP_ENTRIES_VALUE) 17562306a36Sopenharmony_ci to_submit = IORING_SQPOLL_CAP_ENTRIES_VALUE; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (!wq_list_empty(&ctx->iopoll_list) || to_submit) { 17862306a36Sopenharmony_ci const struct cred *creds = NULL; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (ctx->sq_creds != current_cred()) 18162306a36Sopenharmony_ci creds = override_creds(ctx->sq_creds); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci mutex_lock(&ctx->uring_lock); 18462306a36Sopenharmony_ci if (!wq_list_empty(&ctx->iopoll_list)) 18562306a36Sopenharmony_ci io_do_iopoll(ctx, true); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * Don't submit if refs are dying, good for io_uring_register(), 18962306a36Sopenharmony_ci * but also it is relied upon by io_ring_exit_work() 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci if (to_submit && likely(!percpu_ref_is_dying(&ctx->refs)) && 19262306a36Sopenharmony_ci !(ctx->flags & IORING_SETUP_R_DISABLED)) 19362306a36Sopenharmony_ci ret = io_submit_sqes(ctx, to_submit); 19462306a36Sopenharmony_ci mutex_unlock(&ctx->uring_lock); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (to_submit && wq_has_sleeper(&ctx->sqo_sq_wait)) 19762306a36Sopenharmony_ci wake_up(&ctx->sqo_sq_wait); 19862306a36Sopenharmony_ci if (creds) 19962306a36Sopenharmony_ci revert_creds(creds); 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return ret; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic bool io_sqd_handle_event(struct io_sq_data *sqd) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci bool did_sig = false; 20862306a36Sopenharmony_ci struct ksignal ksig; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (test_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state) || 21162306a36Sopenharmony_ci signal_pending(current)) { 21262306a36Sopenharmony_ci mutex_unlock(&sqd->lock); 21362306a36Sopenharmony_ci if (signal_pending(current)) 21462306a36Sopenharmony_ci did_sig = get_signal(&ksig); 21562306a36Sopenharmony_ci cond_resched(); 21662306a36Sopenharmony_ci mutex_lock(&sqd->lock); 21762306a36Sopenharmony_ci sqd->sq_cpu = raw_smp_processor_id(); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci return did_sig || test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic int io_sq_thread(void *data) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci struct io_sq_data *sqd = data; 22562306a36Sopenharmony_ci struct io_ring_ctx *ctx; 22662306a36Sopenharmony_ci unsigned long timeout = 0; 22762306a36Sopenharmony_ci char buf[TASK_COMM_LEN]; 22862306a36Sopenharmony_ci DEFINE_WAIT(wait); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "iou-sqp-%d", sqd->task_pid); 23162306a36Sopenharmony_ci set_task_comm(current, buf); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* reset to our pid after we've set task_comm, for fdinfo */ 23462306a36Sopenharmony_ci sqd->task_pid = current->pid; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (sqd->sq_cpu != -1) { 23762306a36Sopenharmony_ci set_cpus_allowed_ptr(current, cpumask_of(sqd->sq_cpu)); 23862306a36Sopenharmony_ci } else { 23962306a36Sopenharmony_ci set_cpus_allowed_ptr(current, cpu_online_mask); 24062306a36Sopenharmony_ci sqd->sq_cpu = raw_smp_processor_id(); 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci mutex_lock(&sqd->lock); 24462306a36Sopenharmony_ci while (1) { 24562306a36Sopenharmony_ci bool cap_entries, sqt_spin = false; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (io_sqd_events_pending(sqd) || signal_pending(current)) { 24862306a36Sopenharmony_ci if (io_sqd_handle_event(sqd)) 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci timeout = jiffies + sqd->sq_thread_idle; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci cap_entries = !list_is_singular(&sqd->ctx_list); 25462306a36Sopenharmony_ci list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { 25562306a36Sopenharmony_ci int ret = __io_sq_thread(ctx, cap_entries); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (!sqt_spin && (ret > 0 || !wq_list_empty(&ctx->iopoll_list))) 25862306a36Sopenharmony_ci sqt_spin = true; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci if (io_run_task_work()) 26162306a36Sopenharmony_ci sqt_spin = true; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (sqt_spin || !time_after(jiffies, timeout)) { 26462306a36Sopenharmony_ci if (sqt_spin) 26562306a36Sopenharmony_ci timeout = jiffies + sqd->sq_thread_idle; 26662306a36Sopenharmony_ci if (unlikely(need_resched())) { 26762306a36Sopenharmony_ci mutex_unlock(&sqd->lock); 26862306a36Sopenharmony_ci cond_resched(); 26962306a36Sopenharmony_ci mutex_lock(&sqd->lock); 27062306a36Sopenharmony_ci sqd->sq_cpu = raw_smp_processor_id(); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci continue; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci prepare_to_wait(&sqd->wait, &wait, TASK_INTERRUPTIBLE); 27662306a36Sopenharmony_ci if (!io_sqd_events_pending(sqd) && !task_work_pending(current)) { 27762306a36Sopenharmony_ci bool needs_sched = true; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { 28062306a36Sopenharmony_ci atomic_or(IORING_SQ_NEED_WAKEUP, 28162306a36Sopenharmony_ci &ctx->rings->sq_flags); 28262306a36Sopenharmony_ci if ((ctx->flags & IORING_SETUP_IOPOLL) && 28362306a36Sopenharmony_ci !wq_list_empty(&ctx->iopoll_list)) { 28462306a36Sopenharmony_ci needs_sched = false; 28562306a36Sopenharmony_ci break; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* 28962306a36Sopenharmony_ci * Ensure the store of the wakeup flag is not 29062306a36Sopenharmony_ci * reordered with the load of the SQ tail 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_ci smp_mb__after_atomic(); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci if (io_sqring_entries(ctx)) { 29562306a36Sopenharmony_ci needs_sched = false; 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci } 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (needs_sched) { 30162306a36Sopenharmony_ci mutex_unlock(&sqd->lock); 30262306a36Sopenharmony_ci schedule(); 30362306a36Sopenharmony_ci mutex_lock(&sqd->lock); 30462306a36Sopenharmony_ci sqd->sq_cpu = raw_smp_processor_id(); 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) 30762306a36Sopenharmony_ci atomic_andnot(IORING_SQ_NEED_WAKEUP, 30862306a36Sopenharmony_ci &ctx->rings->sq_flags); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci finish_wait(&sqd->wait, &wait); 31262306a36Sopenharmony_ci timeout = jiffies + sqd->sq_thread_idle; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci io_uring_cancel_generic(true, sqd); 31662306a36Sopenharmony_ci sqd->thread = NULL; 31762306a36Sopenharmony_ci list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) 31862306a36Sopenharmony_ci atomic_or(IORING_SQ_NEED_WAKEUP, &ctx->rings->sq_flags); 31962306a36Sopenharmony_ci io_run_task_work(); 32062306a36Sopenharmony_ci mutex_unlock(&sqd->lock); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci complete(&sqd->exited); 32362306a36Sopenharmony_ci do_exit(0); 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_civoid io_sqpoll_wait_sq(struct io_ring_ctx *ctx) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci DEFINE_WAIT(wait); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci do { 33162306a36Sopenharmony_ci if (!io_sqring_full(ctx)) 33262306a36Sopenharmony_ci break; 33362306a36Sopenharmony_ci prepare_to_wait(&ctx->sqo_sq_wait, &wait, TASK_INTERRUPTIBLE); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci if (!io_sqring_full(ctx)) 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci schedule(); 33862306a36Sopenharmony_ci } while (!signal_pending(current)); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci finish_wait(&ctx->sqo_sq_wait, &wait); 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci__cold int io_sq_offload_create(struct io_ring_ctx *ctx, 34462306a36Sopenharmony_ci struct io_uring_params *p) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci int ret; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* Retain compatibility with failing for an invalid attach attempt */ 34962306a36Sopenharmony_ci if ((ctx->flags & (IORING_SETUP_ATTACH_WQ | IORING_SETUP_SQPOLL)) == 35062306a36Sopenharmony_ci IORING_SETUP_ATTACH_WQ) { 35162306a36Sopenharmony_ci struct fd f; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci f = fdget(p->wq_fd); 35462306a36Sopenharmony_ci if (!f.file) 35562306a36Sopenharmony_ci return -ENXIO; 35662306a36Sopenharmony_ci if (!io_is_uring_fops(f.file)) { 35762306a36Sopenharmony_ci fdput(f); 35862306a36Sopenharmony_ci return -EINVAL; 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci fdput(f); 36162306a36Sopenharmony_ci } 36262306a36Sopenharmony_ci if (ctx->flags & IORING_SETUP_SQPOLL) { 36362306a36Sopenharmony_ci struct task_struct *tsk; 36462306a36Sopenharmony_ci struct io_sq_data *sqd; 36562306a36Sopenharmony_ci bool attached; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ret = security_uring_sqpoll(); 36862306a36Sopenharmony_ci if (ret) 36962306a36Sopenharmony_ci return ret; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci sqd = io_get_sq_data(p, &attached); 37262306a36Sopenharmony_ci if (IS_ERR(sqd)) { 37362306a36Sopenharmony_ci ret = PTR_ERR(sqd); 37462306a36Sopenharmony_ci goto err; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci ctx->sq_creds = get_current_cred(); 37862306a36Sopenharmony_ci ctx->sq_data = sqd; 37962306a36Sopenharmony_ci ctx->sq_thread_idle = msecs_to_jiffies(p->sq_thread_idle); 38062306a36Sopenharmony_ci if (!ctx->sq_thread_idle) 38162306a36Sopenharmony_ci ctx->sq_thread_idle = HZ; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci io_sq_thread_park(sqd); 38462306a36Sopenharmony_ci list_add(&ctx->sqd_list, &sqd->ctx_list); 38562306a36Sopenharmony_ci io_sqd_update_thread_idle(sqd); 38662306a36Sopenharmony_ci /* don't attach to a dying SQPOLL thread, would be racy */ 38762306a36Sopenharmony_ci ret = (attached && !sqd->thread) ? -ENXIO : 0; 38862306a36Sopenharmony_ci io_sq_thread_unpark(sqd); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (ret < 0) 39162306a36Sopenharmony_ci goto err; 39262306a36Sopenharmony_ci if (attached) 39362306a36Sopenharmony_ci return 0; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (p->flags & IORING_SETUP_SQ_AFF) { 39662306a36Sopenharmony_ci int cpu = p->sq_thread_cpu; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci ret = -EINVAL; 39962306a36Sopenharmony_ci if (cpu >= nr_cpu_ids || !cpu_online(cpu)) 40062306a36Sopenharmony_ci goto err_sqpoll; 40162306a36Sopenharmony_ci sqd->sq_cpu = cpu; 40262306a36Sopenharmony_ci } else { 40362306a36Sopenharmony_ci sqd->sq_cpu = -1; 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci sqd->task_pid = current->pid; 40762306a36Sopenharmony_ci sqd->task_tgid = current->tgid; 40862306a36Sopenharmony_ci tsk = create_io_thread(io_sq_thread, sqd, NUMA_NO_NODE); 40962306a36Sopenharmony_ci if (IS_ERR(tsk)) { 41062306a36Sopenharmony_ci ret = PTR_ERR(tsk); 41162306a36Sopenharmony_ci goto err_sqpoll; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci sqd->thread = tsk; 41562306a36Sopenharmony_ci ret = io_uring_alloc_task_context(tsk, ctx); 41662306a36Sopenharmony_ci wake_up_new_task(tsk); 41762306a36Sopenharmony_ci if (ret) 41862306a36Sopenharmony_ci goto err; 41962306a36Sopenharmony_ci } else if (p->flags & IORING_SETUP_SQ_AFF) { 42062306a36Sopenharmony_ci /* Can't have SQ_AFF without SQPOLL */ 42162306a36Sopenharmony_ci ret = -EINVAL; 42262306a36Sopenharmony_ci goto err; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci return 0; 42662306a36Sopenharmony_cierr_sqpoll: 42762306a36Sopenharmony_ci complete(&ctx->sq_data->exited); 42862306a36Sopenharmony_cierr: 42962306a36Sopenharmony_ci io_sq_thread_finish(ctx); 43062306a36Sopenharmony_ci return ret; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci__cold int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, 43462306a36Sopenharmony_ci cpumask_var_t mask) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci struct io_sq_data *sqd = ctx->sq_data; 43762306a36Sopenharmony_ci int ret = -EINVAL; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (sqd) { 44062306a36Sopenharmony_ci io_sq_thread_park(sqd); 44162306a36Sopenharmony_ci /* Don't set affinity for a dying thread */ 44262306a36Sopenharmony_ci if (sqd->thread) 44362306a36Sopenharmony_ci ret = io_wq_cpu_affinity(sqd->thread->io_uring, mask); 44462306a36Sopenharmony_ci io_sq_thread_unpark(sqd); 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci return ret; 44862306a36Sopenharmony_ci} 449