162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef IOCONTEXT_H
362306a36Sopenharmony_ci#define IOCONTEXT_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/radix-tree.h>
662306a36Sopenharmony_ci#include <linux/rcupdate.h>
762306a36Sopenharmony_ci#include <linux/workqueue.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_cienum {
1062306a36Sopenharmony_ci	ICQ_EXITED		= 1 << 2,
1162306a36Sopenharmony_ci	ICQ_DESTROYED		= 1 << 3,
1262306a36Sopenharmony_ci};
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * An io_cq (icq) is association between an io_context (ioc) and a
1662306a36Sopenharmony_ci * request_queue (q).  This is used by elevators which need to track
1762306a36Sopenharmony_ci * information per ioc - q pair.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * Elevator can request use of icq by setting elevator_type->icq_size and
2062306a36Sopenharmony_ci * ->icq_align.  Both size and align must be larger than that of struct
2162306a36Sopenharmony_ci * io_cq and elevator can use the tail area for private information.  The
2262306a36Sopenharmony_ci * recommended way to do this is defining a struct which contains io_cq as
2362306a36Sopenharmony_ci * the first member followed by private members and using its size and
2462306a36Sopenharmony_ci * align.  For example,
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci *	struct snail_io_cq {
2762306a36Sopenharmony_ci *		struct io_cq	icq;
2862306a36Sopenharmony_ci *		int		poke_snail;
2962306a36Sopenharmony_ci *		int		feed_snail;
3062306a36Sopenharmony_ci *	};
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci *	struct elevator_type snail_elv_type {
3362306a36Sopenharmony_ci *		.ops =		{ ... },
3462306a36Sopenharmony_ci *		.icq_size =	sizeof(struct snail_io_cq),
3562306a36Sopenharmony_ci *		.icq_align =	__alignof__(struct snail_io_cq),
3662306a36Sopenharmony_ci *		...
3762306a36Sopenharmony_ci *	};
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci * If icq_size is set, block core will manage icq's.  All requests will
4062306a36Sopenharmony_ci * have its ->elv.icq field set before elevator_ops->elevator_set_req_fn()
4162306a36Sopenharmony_ci * is called and be holding a reference to the associated io_context.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * Whenever a new icq is created, elevator_ops->elevator_init_icq_fn() is
4462306a36Sopenharmony_ci * called and, on destruction, ->elevator_exit_icq_fn().  Both functions
4562306a36Sopenharmony_ci * are called with both the associated io_context and queue locks held.
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci * Elevator is allowed to lookup icq using ioc_lookup_icq() while holding
4862306a36Sopenharmony_ci * queue lock but the returned icq is valid only until the queue lock is
4962306a36Sopenharmony_ci * released.  Elevators can not and should not try to create or destroy
5062306a36Sopenharmony_ci * icq's.
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci * As icq's are linked from both ioc and q, the locking rules are a bit
5362306a36Sopenharmony_ci * complex.
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci * - ioc lock nests inside q lock.
5662306a36Sopenharmony_ci *
5762306a36Sopenharmony_ci * - ioc->icq_list and icq->ioc_node are protected by ioc lock.
5862306a36Sopenharmony_ci *   q->icq_list and icq->q_node by q lock.
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci * - ioc->icq_tree and ioc->icq_hint are protected by ioc lock, while icq
6162306a36Sopenharmony_ci *   itself is protected by q lock.  However, both the indexes and icq
6262306a36Sopenharmony_ci *   itself are also RCU managed and lookup can be performed holding only
6362306a36Sopenharmony_ci *   the q lock.
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * - icq's are not reference counted.  They are destroyed when either the
6662306a36Sopenharmony_ci *   ioc or q goes away.  Each request with icq set holds an extra
6762306a36Sopenharmony_ci *   reference to ioc to ensure it stays until the request is completed.
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci * - Linking and unlinking icq's are performed while holding both ioc and q
7062306a36Sopenharmony_ci *   locks.  Due to the lock ordering, q exit is simple but ioc exit
7162306a36Sopenharmony_ci *   requires reverse-order double lock dance.
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistruct io_cq {
7462306a36Sopenharmony_ci	struct request_queue	*q;
7562306a36Sopenharmony_ci	struct io_context	*ioc;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/*
7862306a36Sopenharmony_ci	 * q_node and ioc_node link io_cq through icq_list of q and ioc
7962306a36Sopenharmony_ci	 * respectively.  Both fields are unused once ioc_exit_icq() is
8062306a36Sopenharmony_ci	 * called and shared with __rcu_icq_cache and __rcu_head which are
8162306a36Sopenharmony_ci	 * used for RCU free of io_cq.
8262306a36Sopenharmony_ci	 */
8362306a36Sopenharmony_ci	union {
8462306a36Sopenharmony_ci		struct list_head	q_node;
8562306a36Sopenharmony_ci		struct kmem_cache	*__rcu_icq_cache;
8662306a36Sopenharmony_ci	};
8762306a36Sopenharmony_ci	union {
8862306a36Sopenharmony_ci		struct hlist_node	ioc_node;
8962306a36Sopenharmony_ci		struct rcu_head		__rcu_head;
9062306a36Sopenharmony_ci	};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	unsigned int		flags;
9362306a36Sopenharmony_ci};
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci * I/O subsystem state of the associated processes.  It is refcounted
9762306a36Sopenharmony_ci * and kmalloc'ed. These could be shared between processes.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_cistruct io_context {
10062306a36Sopenharmony_ci	atomic_long_t refcount;
10162306a36Sopenharmony_ci	atomic_t active_ref;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	unsigned short ioprio;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#ifdef CONFIG_BLK_ICQ
10662306a36Sopenharmony_ci	/* all the fields below are protected by this lock */
10762306a36Sopenharmony_ci	spinlock_t lock;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	struct radix_tree_root	icq_tree;
11062306a36Sopenharmony_ci	struct io_cq __rcu	*icq_hint;
11162306a36Sopenharmony_ci	struct hlist_head	icq_list;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	struct work_struct release_work;
11462306a36Sopenharmony_ci#endif /* CONFIG_BLK_ICQ */
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistruct task_struct;
11862306a36Sopenharmony_ci#ifdef CONFIG_BLOCK
11962306a36Sopenharmony_civoid put_io_context(struct io_context *ioc);
12062306a36Sopenharmony_civoid exit_io_context(struct task_struct *task);
12162306a36Sopenharmony_ciint __copy_io(unsigned long clone_flags, struct task_struct *tsk);
12262306a36Sopenharmony_cistatic inline int copy_io(unsigned long clone_flags, struct task_struct *tsk)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	if (!current->io_context)
12562306a36Sopenharmony_ci		return 0;
12662306a36Sopenharmony_ci	return __copy_io(clone_flags, tsk);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci#else
12962306a36Sopenharmony_cistruct io_context;
13062306a36Sopenharmony_cistatic inline void put_io_context(struct io_context *ioc) { }
13162306a36Sopenharmony_cistatic inline void exit_io_context(struct task_struct *task) { }
13262306a36Sopenharmony_cistatic inline int copy_io(unsigned long clone_flags, struct task_struct *tsk)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	return 0;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci#endif /* CONFIG_BLOCK */
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#endif /* IOCONTEXT_H */
139