xref: /illumos-gate/usr/src/uts/common/sys/aio_impl.h (revision 2aa8db5932a99c01d32f2aea7dbbf15b4898169b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright 2026 Oxide Computer Company
26  */
27 
28 #ifndef _SYS_AIO_IMPL_H
29 #define	_SYS_AIO_IMPL_H
30 
31 #include <sys/aio_req.h>
32 #include <sys/aio.h>
33 #include <sys/aiocb.h>
34 #include <sys/uio.h>
35 #include <sys/dditypes.h>
36 #include <sys/siginfo.h>
37 #include <sys/port.h>
38 #include <sys/port_kernel.h>
39 
40 #ifdef	__cplusplus
41 extern "C" {
42 #endif
43 
44 #ifdef _KERNEL
45 
46 #define	AIO_HASHSZ		8192L		/* power of 2 */
47 #define	AIO_HASH(cookie)	(((uintptr_t)(cookie) >> 3) & (AIO_HASHSZ-1))
48 #define	DUPLICATE 1
49 
50 /*
51  * an aio_list_t is the head of a list. a group of requests are in
52  * the same list if their aio_req_list field point to the same list
53  * head.
54  *
55  * a list head is used for notification. a group of requests that
56  * should only notify a process when they are done will have a
57  * list head. notification is sent when the group of requests are
58  * done.
59  */
60 typedef struct aio_lio {
61 	int		lio_nent;		/* number of requests in list */
62 	int		lio_refcnt;		/* number of requests active */
63 	struct aio_lio	*lio_next;		/* free list pointer */
64 	kcondvar_t	lio_notify;		/* list notification */
65 	sigqueue_t	*lio_sigqp;		/* sigqueue_t pointer */
66 	int		lio_port;		/* port number notification */
67 	port_kevent_t	*lio_portkev;		/* port event structure */
68 } aio_lio_t;
69 
70 /*
71  * async I/O request struct - one per I/O request.
72  */
73 
74 /*
75  * Clustering: The aio_req_t structure is used by the PXFS module
76  * as a contract private interface.
77  */
78 
79 typedef struct aio_req_t {
80 	struct aio_req	aio_req;
81 	int		aio_req_fd;		/* aio's file descriptor */
82 	int		aio_req_flags;		/* flags */
83 	aio_result_t	*aio_req_resultp;	/* pointer to user's results */
84 	int		(*aio_req_cancel)();	/* driver's cancel cb. */
85 	struct aio_req_t *aio_req_next;		/* doneq and pollq pointers */
86 	struct aio_req_t *aio_req_prev;		/* doubly linked list */
87 	struct aio_req_t *aio_hash_next;	/* next in a hash bucket */
88 	aio_lio_t	*aio_req_lio;		/* head of list IO chain */
89 	struct uio	aio_req_uio;		/* uio struct */
90 	struct iovec	aio_req_iov;		/* iovec struct */
91 	struct buf	aio_req_buf;		/* buf struct */
92 	sigqueue_t	*aio_req_sigqp;		/* sigqueue_t pointer */
93 	union {
94 		caddr_t		iocb;		/* ptr to aiocb: 32-32, 64-64 */
95 		caddr32_t	iocb32;		/* ptr to aiocb: 32-64 */
96 	} aio_req_iocb;
97 	port_kevent_t	*aio_req_portkev;	/* port event structure */
98 	int		aio_req_port;		/* port id */
99 } aio_req_t;
100 
101 /*
102  * Struct for asynchronous I/O (aio) information per process.
103  * Each proc stucture has a field pointing to this struct.
104  * The field will be null if no aio is used.
105  */
106 typedef struct aio {
107 	int		aio_pending;		/* # uncompleted requests */
108 	int		aio_outstanding;	/* total # of requests */
109 	int		aio_ok;			/* everything ok when set */
110 	int		aio_flags;		/* flags */
111 	int		aio_rqclnup;		/* cleanup request used by DR */
112 	uint_t		aio_done_cnt;		/* # aio_done calls active */
113 	int		aio_portpendcnt;	/* # pending req. per port */
114 	aio_req_t	*aio_portq;		/* port queue head */
115 	aio_req_t	*aio_portcleanupq;	/* port cleanup queue head */
116 	aio_req_t	*aio_portpending;	/* list of pending requests */
117 	aio_req_t	*aio_free;		/* freelist of aio requests */
118 	aio_lio_t	*aio_lio_free;		/* freelist of lio heads */
119 	aio_req_t	*aio_doneq;		/* done queue head */
120 	aio_req_t	*aio_pollq;		/* poll queue head */
121 	aio_req_t	*aio_notifyq;		/* notify queue head */
122 	aio_req_t	*aio_cleanupq;		/* cleanup queue head */
123 	kmutex_t	aio_mutex;		/* mutex for aio struct */
124 	kmutex_t	aio_cleanupq_mutex;	/* cleanupq processing */
125 	kcondvar_t	aio_waitcv;		/* cv for aiowait()'ers */
126 	kcondvar_t	aio_cleanupcv;		/* notify cleanup, aio_done */
127 	kcondvar_t	aio_waitncv;		/* cv for further aiowaitn() */
128 	kcondvar_t	aio_portcv;		/* cv for port events */
129 	aiocb_t		**aio_iocb;		/* list of 32 & 64 bit ptrs */
130 	size_t		aio_iocbsz;		/* reserved space for iocbs */
131 	uint_t		aio_waitncnt;		/* # requests for aiowaitn */
132 	int		aio_notifycnt;		/* # user-level notifications */
133 	kmutex_t	aio_portq_mutex;	/* mutex for aio_portq */
134 	aio_req_t	*aio_hash[AIO_HASHSZ];	/* hash list of requests */
135 } aio_t;
136 
137 /*
138  * aio_flags for an aio_t.
139  */
140 #define	AIO_CLEANUP		0x0001	/* do aio cleanup processing */
141 #define	AIO_WAITN		0x0002	/* aiowaitn in progress */
142 #define	AIO_WAITN_PENDING	0x0004	/* aiowaitn requests pending */
143 #define	AIO_REQ_BLOCK		0x0008	/* block new requests */
144 #define	AIO_CLEANUP_PORT	0x0010
145 	/* AIO_DONE_ACTIVE (0x0020) retired; replaced by aio_done_cnt */
146 #define	AIO_SOLARIS_REQ		0x0040	/* an old solaris aio req was issued */
147 
148 /*
149  * aio_req_flags for an aio_req_t
150  */
151 #define	AIO_POLL	0x0001		/* AIO_INPROGRESS is set */
152 #define	AIO_PENDING	0x0002		/* aio is in progress */
153 #define	AIO_PHYSIODONE	0x0004		/* unlocked phys pages */
154 #define	AIO_COPYOUTDONE	0x0008		/* result copied to userland */
155 #define	AIO_NOTIFYQ	0x0010		/* aio req is on the notifyq */
156 #define	AIO_CLEANUPQ	0x0020		/* aio req is on the cleanupq */
157 #define	AIO_POLLQ	0x0040		/* aio req is on the pollq */
158 #define	AIO_DONEQ	0x0080		/* aio req is on the doneq */
159 #define	AIO_ZEROLEN	0x0100		/* aio req is zero length */
160 #define	AIO_PAGELOCKDONE 0x0200		/* aio called as_pagelock() */
161 #define	AIO_CLOSE_PORT	0x0400		/* port is being closed */
162 #define	AIO_SIGNALLED	0x0800		/* process signalled by this req */
163 #define	AIO_SOLARIS	0x1000		/* this is an old solaris aio req */
164 
165 /* flag argument of aio_cleanup() */
166 
167 #define	AIO_CLEANUP_POLL	0	/* check kaio poll queue */
168 #define	AIO_CLEANUP_EXIT	1	/* aio_cleanup_exit() */
169 #define	AIO_CLEANUP_THREAD	2	/* aio_cleanup_thread() */
170 
171 /* functions exported by common/os/aio_subr.c */
172 
173 extern int aphysio(int (*)(), int (*)(), dev_t, int, void (*)(),
174 		struct aio_req *);
175 extern void aphysio_unlock(aio_req_t *);
176 extern void aio_cleanup(int);
177 extern void aio_cleanup_exit(void);
178 extern void aio_zerolen(aio_req_t *);
179 extern void aio_req_free(aio_t *, aio_req_t *);
180 extern void aio_cleanupq_concat(aio_t *, aio_req_t *, int);
181 extern void aio_copyout_result(aio_req_t *);
182 extern void aio_copyout_result_port(struct iovec *, struct buf *, void *);
183 extern void aio_req_remove_portq(aio_t *, aio_req_t *);
184 extern void aio_enq(aio_req_t **, aio_req_t *, int);
185 extern void aio_deq(aio_req_t **, aio_req_t *);
186 /* Clustering: PXFS module uses this interface */
187 extern int aio_done(struct buf *);
188 
189 #endif /* _KERNEL */
190 
191 #ifdef	__cplusplus
192 }
193 #endif
194 
195 #endif /* _SYS_AIO_IMPL_H */
196