3944 lines · 105.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Shared application/kernel submission and completion ring pairs, for * supporting fast/efficient IO. * * A note on the read/write ordering memory barriers that are matched between * the application and kernel side. * * After the application reads the CQ ring tail, it must use an * appropriate smp_rmb() to pair with the smp_wmb() the kernel uses * before writing the tail (using smp_load_acquire to read the tail will * do). It also needs a smp_mb() before updating CQ head (ordering the * entry load(s) with the head store), pairing with an implicit barrier * through a control-dependency in io_get_cqe (smp_store_release to * store head will do). Failure to do so could lead to reading invalid * CQ entries. * * Likewise, the application must use an appropriate smp_wmb() before * writing the SQ tail (ordering SQ entry stores with the tail store), * which pairs with smp_load_acquire in io_get_sqring (smp_store_release * to store the tail will do). And it needs a barrier ordering the SQ * head load before writing new SQ entries (smp_load_acquire to read * head will do). * * When using the SQ poll thread (IORING_SETUP_SQPOLL), the application * needs to check the SQ flags for IORING_SQ_NEED_WAKEUP *after* * updating the SQ tail; a full memory barrier smp_mb() is needed * between. * * Also see the examples in the liburing library: * *	git://git.kernel.dk/liburing * * io_uring also uses READ/WRITE_ONCE() for _any_ store or load that happens * from data shared between the kernel and application. This is done both * for ordering purposes, but also to ensure that once a value is loaded from * data that the application could potentially modify, it remains stable. * * Copyright (C) 2018-2019 Jens Axboe * Copyright (c) 2018-2019 Christoph Hellwig */#include <linux/kernel.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/syscalls.h>#include <net/compat.h>#include <linux/refcount.h>#include <linux/uio.h>#include <linux/bits.h> #include <linux/sched/signal.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/percpu.h>#include <linux/slab.h>#include <linux/bvec.h>#include <linux/net.h>#include <net/sock.h>#include <linux/anon_inodes.h>#include <linux/sched/mm.h>#include <linux/uaccess.h>#include <linux/nospec.h>#include <linux/fsnotify.h>#include <linux/fadvise.h>#include <linux/task_work.h>#include <linux/io_uring.h>#include <linux/io_uring/cmd.h>#include <linux/audit.h>#include <linux/security.h>#include <linux/jump_label.h>#include <asm/shmparam.h> #define CREATE_TRACE_POINTS#include <trace/events/io_uring.h> #include <uapi/linux/io_uring.h> #include "io-wq.h" #include "io_uring.h"#include "opdef.h"#include "refs.h"#include "tctx.h"#include "register.h"#include "sqpoll.h"#include "fdinfo.h"#include "kbuf.h"#include "rsrc.h"#include "cancel.h"#include "net.h"#include "notif.h"#include "waitid.h"#include "futex.h"#include "napi.h"#include "uring_cmd.h"#include "msg_ring.h"#include "memmap.h" #include "timeout.h"#include "poll.h"#include "rw.h"#include "alloc_cache.h"#include "eventfd.h" #define SQE_COMMON_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_LINK | \			  IOSQE_IO_HARDLINK | IOSQE_ASYNC) #define SQE_VALID_FLAGS	(SQE_COMMON_FLAGS | IOSQE_BUFFER_SELECT | \			IOSQE_IO_DRAIN | IOSQE_CQE_SKIP_SUCCESS) #define IO_REQ_CLEAN_FLAGS (REQ_F_BUFFER_SELECTED | REQ_F_NEED_CLEANUP | \				REQ_F_POLLED | REQ_F_INFLIGHT | REQ_F_CREDS | \				REQ_F_ASYNC_DATA) #define IO_REQ_CLEAN_SLOW_FLAGS (REQ_F_REFCOUNT | REQ_F_LINK | REQ_F_HARDLINK |\				 IO_REQ_CLEAN_FLAGS) #define IO_TCTX_REFS_CACHE_NR	(1U << 10) #define IO_COMPL_BATCH			32#define IO_REQ_ALLOC_BATCH		8#define IO_LOCAL_TW_DEFAULT_MAX		20 struct io_defer_entry {	struct list_head	list;	struct io_kiocb		*req;	u32			seq;}; /* requests with any of those set should undergo io_disarm_next() */#define IO_DISARM_MASK (REQ_F_ARM_LTIMEOUT | REQ_F_LINK_TIMEOUT | REQ_F_FAIL)#define IO_REQ_LINK_FLAGS (REQ_F_LINK | REQ_F_HARDLINK) /* * No waiters. It's larger than any valid value of the tw counter * so that tests against ->cq_wait_nr would fail and skip wake_up(). */#define IO_CQ_WAKE_INIT		(-1U)/* Forced wake up if there is a waiter regardless of ->cq_wait_nr */#define IO_CQ_WAKE_FORCE	(IO_CQ_WAKE_INIT >> 1) static bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,					 struct io_uring_task *tctx,					 bool cancel_all); static void io_queue_sqe(struct io_kiocb *req); static __read_mostly DEFINE_STATIC_KEY_FALSE(io_key_has_sqarray); struct kmem_cache *req_cachep;static struct workqueue_struct *iou_wq __ro_after_init; static int __read_mostly sysctl_io_uring_disabled;static int __read_mostly sysctl_io_uring_group = -1; #ifdef CONFIG_SYSCTLstatic struct ctl_table kernel_io_uring_disabled_table[] = {	{		.procname	= "io_uring_disabled",		.data		= &sysctl_io_uring_disabled,		.maxlen		= sizeof(sysctl_io_uring_disabled),		.mode		= 0644,		.proc_handler	= proc_dointvec_minmax,		.extra1		= SYSCTL_ZERO,		.extra2		= SYSCTL_TWO,	},	{		.procname	= "io_uring_group",		.data		= &sysctl_io_uring_group,		.maxlen		= sizeof(gid_t),		.mode		= 0644,		.proc_handler	= proc_dointvec,	},};#endif static inline unsigned int __io_cqring_events(struct io_ring_ctx *ctx){	return ctx->cached_cq_tail - READ_ONCE(ctx->rings->cq.head);} static inline unsigned int __io_cqring_events_user(struct io_ring_ctx *ctx){	return READ_ONCE(ctx->rings->cq.tail) - READ_ONCE(ctx->rings->cq.head);} static bool io_match_linked(struct io_kiocb *head){	struct io_kiocb *req; 	io_for_each_link(req, head) {		if (req->flags & REQ_F_INFLIGHT)			return true;	}	return false;} /* * As io_match_task() but protected against racing with linked timeouts. * User must not hold timeout_lock. */bool io_match_task_safe(struct io_kiocb *head, struct io_uring_task *tctx,			bool cancel_all){	bool matched; 	if (tctx && head->tctx != tctx)		return false;	if (cancel_all)		return true; 	if (head->flags & REQ_F_LINK_TIMEOUT) {		struct io_ring_ctx *ctx = head->ctx; 		/* protect against races with linked timeouts */		raw_spin_lock_irq(&ctx->timeout_lock);		matched = io_match_linked(head);		raw_spin_unlock_irq(&ctx->timeout_lock);	} else {		matched = io_match_linked(head);	}	return matched;} static inline void req_fail_link_node(struct io_kiocb *req, int res){	req_set_fail(req);	io_req_set_res(req, res, 0);} static inline void io_req_add_to_cache(struct io_kiocb *req, struct io_ring_ctx *ctx){	wq_stack_add_head(&req->comp_list, &ctx->submit_state.free_list);} static __cold void io_ring_ctx_ref_free(struct percpu_ref *ref){	struct io_ring_ctx *ctx = container_of(ref, struct io_ring_ctx, refs); 	complete(&ctx->ref_comp);} static __cold void io_fallback_req_func(struct work_struct *work){	struct io_ring_ctx *ctx = container_of(work, struct io_ring_ctx,						fallback_work.work);	struct llist_node *node = llist_del_all(&ctx->fallback_llist);	struct io_kiocb *req, *tmp;	struct io_tw_state ts = {}; 	percpu_ref_get(&ctx->refs);	mutex_lock(&ctx->uring_lock);	llist_for_each_entry_safe(req, tmp, node, io_task_work.node)		req->io_task_work.func(req, &ts);	io_submit_flush_completions(ctx);	mutex_unlock(&ctx->uring_lock);	percpu_ref_put(&ctx->refs);} static int io_alloc_hash_table(struct io_hash_table *table, unsigned bits){	unsigned int hash_buckets;	int i; 	do {		hash_buckets = 1U << bits;		table->hbs = kvmalloc_array(hash_buckets, sizeof(table->hbs[0]),						GFP_KERNEL_ACCOUNT);		if (table->hbs)			break;		if (bits == 1)			return -ENOMEM;		bits--;	} while (1); 	table->hash_bits = bits;	for (i = 0; i < hash_buckets; i++)		INIT_HLIST_HEAD(&table->hbs[i].list);	return 0;} static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p){	struct io_ring_ctx *ctx;	int hash_bits;	bool ret; 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);	if (!ctx)		return NULL; 	xa_init(&ctx->io_bl_xa); 	/*	 * Use 5 bits less than the max cq entries, that should give us around	 * 32 entries per hash list if totally full and uniformly spread, but	 * don't keep too many buckets to not overconsume memory.	 */	hash_bits = ilog2(p->cq_entries) - 5;	hash_bits = clamp(hash_bits, 1, 8);	if (io_alloc_hash_table(&ctx->cancel_table, hash_bits))		goto err;	if (percpu_ref_init(&ctx->refs, io_ring_ctx_ref_free,			    0, GFP_KERNEL))		goto err; 	ctx->flags = p->flags;	ctx->hybrid_poll_time = LLONG_MAX;	atomic_set(&ctx->cq_wait_nr, IO_CQ_WAKE_INIT);	init_waitqueue_head(&ctx->sqo_sq_wait);	INIT_LIST_HEAD(&ctx->sqd_list);	INIT_LIST_HEAD(&ctx->cq_overflow_list);	INIT_LIST_HEAD(&ctx->io_buffers_cache);	ret = io_alloc_cache_init(&ctx->apoll_cache, IO_POLL_ALLOC_CACHE_MAX,			    sizeof(struct async_poll));	ret |= io_alloc_cache_init(&ctx->netmsg_cache, IO_ALLOC_CACHE_MAX,			    sizeof(struct io_async_msghdr));	ret |= io_alloc_cache_init(&ctx->rw_cache, IO_ALLOC_CACHE_MAX,			    sizeof(struct io_async_rw));	ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,			    sizeof(struct io_uring_cmd_data));	spin_lock_init(&ctx->msg_lock);	ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,			    sizeof(struct io_kiocb));	ret |= io_futex_cache_init(ctx);	if (ret)		goto free_ref;	init_completion(&ctx->ref_comp);	xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1);	mutex_init(&ctx->uring_lock);	init_waitqueue_head(&ctx->cq_wait);	init_waitqueue_head(&ctx->poll_wq);	spin_lock_init(&ctx->completion_lock);	raw_spin_lock_init(&ctx->timeout_lock);	INIT_WQ_LIST(&ctx->iopoll_list);	INIT_LIST_HEAD(&ctx->io_buffers_comp);	INIT_LIST_HEAD(&ctx->defer_list);	INIT_LIST_HEAD(&ctx->timeout_list);	INIT_LIST_HEAD(&ctx->ltimeout_list);	init_llist_head(&ctx->work_llist);	INIT_LIST_HEAD(&ctx->tctx_list);	ctx->submit_state.free_list.next = NULL;	INIT_HLIST_HEAD(&ctx->waitid_list);#ifdef CONFIG_FUTEX	INIT_HLIST_HEAD(&ctx->futex_list);#endif	INIT_DELAYED_WORK(&ctx->fallback_work, io_fallback_req_func);	INIT_WQ_LIST(&ctx->submit_state.compl_reqs);	INIT_HLIST_HEAD(&ctx->cancelable_uring_cmd);	io_napi_init(ctx);	mutex_init(&ctx->resize_lock); 	return ctx; free_ref:	percpu_ref_exit(&ctx->refs);err:	io_alloc_cache_free(&ctx->apoll_cache, kfree);	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->uring_cache, kfree);	io_alloc_cache_free(&ctx->msg_cache, io_msg_cache_free);	io_futex_cache_free(ctx);	kvfree(ctx->cancel_table.hbs);	xa_destroy(&ctx->io_bl_xa);	kfree(ctx);	return NULL;} static void io_account_cq_overflow(struct io_ring_ctx *ctx){	struct io_rings *r = ctx->rings; 	WRITE_ONCE(r->cq_overflow, READ_ONCE(r->cq_overflow) + 1);	ctx->cq_extra--;} static bool req_need_defer(struct io_kiocb *req, u32 seq){	if (unlikely(req->flags & REQ_F_IO_DRAIN)) {		struct io_ring_ctx *ctx = req->ctx; 		return seq + READ_ONCE(ctx->cq_extra) != ctx->cached_cq_tail;	} 	return false;} static void io_clean_op(struct io_kiocb *req){	if (req->flags & REQ_F_BUFFER_SELECTED) {		spin_lock(&req->ctx->completion_lock);		io_kbuf_drop(req);		spin_unlock(&req->ctx->completion_lock);	} 	if (req->flags & REQ_F_NEED_CLEANUP) {		const struct io_cold_def *def = &io_cold_defs[req->opcode]; 		if (def->cleanup)			def->cleanup(req);	}	if ((req->flags & REQ_F_POLLED) && req->apoll) {		kfree(req->apoll->double_poll);		kfree(req->apoll);		req->apoll = NULL;	}	if (req->flags & REQ_F_INFLIGHT)		atomic_dec(&req->tctx->inflight_tracked);	if (req->flags & REQ_F_CREDS)		put_cred(req->creds);	if (req->flags & REQ_F_ASYNC_DATA) {		kfree(req->async_data);		req->async_data = NULL;	}	req->flags &= ~IO_REQ_CLEAN_FLAGS;} static inline void io_req_track_inflight(struct io_kiocb *req){	if (!(req->flags & REQ_F_INFLIGHT)) {		req->flags |= REQ_F_INFLIGHT;		atomic_inc(&req->tctx->inflight_tracked);	}} static struct io_kiocb *__io_prep_linked_timeout(struct io_kiocb *req){	if (WARN_ON_ONCE(!req->link))		return NULL; 	req->flags &= ~REQ_F_ARM_LTIMEOUT;	req->flags |= REQ_F_LINK_TIMEOUT; 	/* linked timeouts should have two refs once prep'ed */	io_req_set_refcount(req);	__io_req_set_refcount(req->link, 2);	return req->link;} static inline struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req){	if (likely(!(req->flags & REQ_F_ARM_LTIMEOUT)))		return NULL;	return __io_prep_linked_timeout(req);} static noinline void __io_arm_ltimeout(struct io_kiocb *req){	io_queue_linked_timeout(__io_prep_linked_timeout(req));} static inline void io_arm_ltimeout(struct io_kiocb *req){	if (unlikely(req->flags & REQ_F_ARM_LTIMEOUT))		__io_arm_ltimeout(req);} static void io_prep_async_work(struct io_kiocb *req){	const struct io_issue_def *def = &io_issue_defs[req->opcode];	struct io_ring_ctx *ctx = req->ctx; 	if (!(req->flags & REQ_F_CREDS)) {		req->flags |= REQ_F_CREDS;		req->creds = get_current_cred();	} 	req->work.list.next = NULL;	atomic_set(&req->work.flags, 0);	if (req->flags & REQ_F_FORCE_ASYNC)		atomic_or(IO_WQ_WORK_CONCURRENT, &req->work.flags); 	if (req->file && !(req->flags & REQ_F_FIXED_FILE))		req->flags |= io_file_get_flags(req->file); 	if (req->file && (req->flags & REQ_F_ISREG)) {		bool should_hash = def->hash_reg_file; 		/* don't serialize this request if the fs doesn't need it */		if (should_hash && (req->file->f_flags & O_DIRECT) &&		    (req->file->f_op->fop_flags & FOP_DIO_PARALLEL_WRITE))			should_hash = false;		if (should_hash || (ctx->flags & IORING_SETUP_IOPOLL))			io_wq_hash_work(&req->work, file_inode(req->file));	} else if (!req->file || !S_ISBLK(file_inode(req->file)->i_mode)) {		if (def->unbound_nonreg_file)			atomic_or(IO_WQ_WORK_UNBOUND, &req->work.flags);	}} static void io_prep_async_link(struct io_kiocb *req){	struct io_kiocb *cur; 	if (req->flags & REQ_F_LINK_TIMEOUT) {		struct io_ring_ctx *ctx = req->ctx; 

Lines 1–500 of 3944.