xref: /illumos-gate/usr/src/uts/common/sys/uio.h (revision e8d3efa1c56e5f2b5368600a2baeb7b1d54a07f8)
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  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
23  *
24  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  *
27  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
28  * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
29  * Copyright 2026 Oxide Computer Company
30  */
31 
32 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
33 /*	  All Rights Reserved	*/
34 
35 /*
36  * University Copyright- Copyright (c) 1982, 1986, 1988
37  * The Regents of the University of California
38  * All Rights Reserved
39  *
40  * University Acknowledgment- Portions of this document are derived from
41  * software developed by the University of California, Berkeley, and its
42  * contributors.
43  */
44 
45 #ifndef _SYS_UIO_H
46 #define	_SYS_UIO_H
47 
48 #include <sys/feature_tests.h>
49 
50 #ifdef	__cplusplus
51 extern "C" {
52 #endif
53 
54 #include <sys/types.h>
55 
56 /*
57  * I/O parameter information.  A uio structure describes the I/O which
58  * is to be performed by an operation.  Typically the data movement will
59  * be performed by a routine such as uiomove(), which updates the uio
60  * structure to reflect what was done.
61  */
62 
63 #if	defined(_XPG4_2)
64 typedef struct iovec {
65 	void	*iov_base;
66 	size_t	iov_len;
67 } iovec_t;
68 #else
69 typedef struct iovec {
70 	caddr_t	iov_base;
71 #if defined(_LP64)
72 	size_t	iov_len;
73 #else
74 	long	iov_len;
75 #endif
76 } iovec_t;
77 #endif	/* defined(_XPG4_2) */
78 
79 #if defined(_SYSCALL32)
80 
81 /* Kernel's view of user ILP32 iovec struct */
82 
83 typedef	struct iovec32 {
84 	caddr32_t	iov_base;
85 	int32_t		iov_len;
86 } iovec32_t;
87 
88 #endif	/* _SYSCALL32 */
89 
90 #if	!defined(_XPG4_2) || defined(__EXTENSIONS__)
91 /*
92  * Segment flag values.
93  */
94 typedef enum uio_seg { UIO_USERSPACE, UIO_SYSSPACE, UIO_USERISPACE } uio_seg_t;
95 
96 typedef struct uio {
97 	iovec_t		*uio_iov;	/* pointer to array of iovecs */
98 	int		uio_iovcnt;	/* number of iovecs */
99 	lloff_t		_uio_offset;	/* file offset */
100 	uio_seg_t	uio_segflg;	/* address space (kernel or user) */
101 	uint16_t	uio_fmode;	/* file mode flags */
102 	uint16_t	uio_extflg;	/* extended flags */
103 	lloff_t		_uio_limit;	/* u-limit (maximum byte offset) */
104 	ssize_t		uio_resid;	/* residual count */
105 } uio_t;
106 
107 /*
108  * Extended uio_t uioa_t used for asynchronous uio.
109  *
110  * Note: UIOA_IOV_MAX is defined and used as it is in "fs/vncalls.c"
111  *	 as there isn't a formal definition of IOV_MAX for the kernel.
112  */
113 #define	UIOA_IOV_MAX	16
114 
115 typedef struct uioa_page_s {		/* locked uio_iov state */
116 	int	uioa_pfncnt;		/* count of pfn_t(s) in *uioa_ppp */
117 	void	**uioa_ppp;		/* page_t or pfn_t arrary */
118 	caddr_t	uioa_base;		/* address base */
119 	size_t	uioa_len;		/* span length */
120 } uioa_page_t;
121 
122 typedef struct uioa_s {
123 	iovec_t		*uio_iov;	/* pointer to array of iovecs */
124 	int		uio_iovcnt;	/* number of iovecs */
125 	lloff_t		_uio_offset;	/* file offset */
126 	uio_seg_t	uio_segflg;	/* address space (kernel or user) */
127 	uint16_t	uio_fmode;	/* file mode flags */
128 	uint16_t	uio_extflg;	/* extended flags */
129 	lloff_t		_uio_limit;	/* u-limit (maximum byte offset) */
130 	ssize_t		uio_resid;	/* residual count */
131 	/*
132 	 * uioa extended members.
133 	 */
134 	uint32_t	uioa_state;	/* state of asynch i/o */
135 	ssize_t		uioa_mbytes;	/* bytes that have been uioamove()ed */
136 	uioa_page_t	*uioa_lcur;	/* pointer into uioa_locked[] */
137 	void		**uioa_lppp;	/* pointer into lcur->uioa_ppp[] */
138 	void		*uioa_hwst[4];	/* opaque hardware state */
139 	uioa_page_t	uioa_locked[UIOA_IOV_MAX]; /* Per iov locked pages */
140 } uioa_t;
141 
142 /*
143  * uio extensions
144  *
145  * PSARC 2009/478: Copy Reduction Interfaces
146  */
147 typedef enum xuio_type {
148 	UIOTYPE_ASYNCIO,
149 	UIOTYPE_ZEROCOPY
150 } xuio_type_t;
151 
152 typedef struct xuio {
153 	uio_t xu_uio;		/* Embedded UIO structure */
154 
155 	/* Extended uio fields */
156 	enum xuio_type xu_type;	/* What kind of uio structure? */
157 	union {
158 		/* Async I/O Support, intend to replace uioa_t. */
159 		struct {
160 			uint32_t xu_a_state;	/* state of async i/o */
161 			/* bytes that have been uioamove()ed */
162 			ssize_t xu_a_mbytes;
163 			uioa_page_t *xu_a_lcur;	/* pointer into uioa_locked[] */
164 			/* pointer into lcur->uioa_ppp[] */
165 			void **xu_a_lppp;
166 			void *xu_a_hwst[4];	/* opaque hardware state */
167 			/* Per iov locked pages */
168 			uioa_page_t xu_a_locked[UIOA_IOV_MAX];
169 		} xu_aio;
170 
171 		/*
172 		 * Copy Reduction Support -- facilate loaning / returning of
173 		 * filesystem cache buffers.
174 		 */
175 		struct {
176 			int xu_zc_rw;	/* read or write buffer */
177 			void *xu_zc_priv;	/* fs specific */
178 		} xu_zc;
179 	} xu_ext;
180 } xuio_t;
181 
182 #define	XUIO_XUZC_PRIV(xuio)    xuio->xu_ext.xu_zc.xu_zc_priv
183 #define	XUIO_XUZC_RW(xuio)	xuio->xu_ext.xu_zc.xu_zc_rw
184 
185 #define	UIOA_ALLOC	0x0001		/* allocated but not yet initialized */
186 #define	UIOA_INIT	0x0002		/* initialized but not yet enabled */
187 #define	UIOA_ENABLED	0x0004		/* enabled, asynch i/o active */
188 #define	UIOA_FINI	0x0008		/* finished waiting for uioafini() */
189 
190 #define	UIOA_CLR	(~0x000F)	/* clear mutually exclusive bits */
191 
192 #define	UIOA_POLL	0x0010		/* need dcopy_poll() */
193 
194 #define	uio_loffset	_uio_offset._f
195 #if !defined(_LP64)
196 #define	uio_offset	_uio_offset._p._l
197 #else
198 #define	uio_offset	uio_loffset
199 #endif
200 
201 #define	uio_llimit	_uio_limit._f
202 #if !defined(_LP64)
203 #define	uio_limit	_uio_limit._p._l
204 #else
205 #define	uio_limit	uio_llimit
206 #endif
207 
208 /*
209  * I/O direction.
210  */
211 typedef enum uio_rw { UIO_READ, UIO_WRITE } uio_rw_t;
212 
213 /*
214  * uio_extflg: extended flags
215  *
216  * NOTE: This flag will be used in uiomove to determine if non-temporal
217  * access, ie, access bypassing caches, should be used.  Filesystems that
218  * don't initialize this field could experience suboptimal performance due to
219  * the random data the field contains.
220  *
221  * NOTE: This flag is also used by uioasync callers to pass an extended
222  * uio_t (uioa_t), to uioasync enabled consumers. Unlike above all
223  * consumers of a uioa_t require the uio_extflg to be initialized.
224  */
225 #define	UIO_COPY_DEFAULT	0x0000	/* no special options to copy */
226 #define	UIO_COPY_CACHED		0x0001	/* copy should not bypass caches */
227 
228 #define	UIO_ASYNC		0x0002	/* uio_t is really a uioa_t */
229 #define	UIO_XUIO		0x0004	/* Structure is xuio_t */
230 
231 /*
232  * Global uioasync capability shadow state.
233  */
234 typedef struct uioasync_s {
235 	boolean_t	enabled;	/* Is uioasync enabled? */
236 	size_t		mincnt;		/* Minimum byte count for use of */
237 } uioasync_t;
238 
239 #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */
240 
241 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
242 
243 int	uiomove(void *, size_t, enum uio_rw, uio_t *);
244 void	uio_prefaultpages(ssize_t, uio_t *);
245 int	uiocopy(void *, size_t, enum uio_rw, uio_t *, size_t *);
246 int	ureadc(int, uio_t *);	/* should be errno_t in future */
247 int	uwritec(struct uio *);
248 void	uioskip(uio_t *, size_t);
249 int	uiodup(uio_t *, uio_t *, iovec_t *, int);
250 int	uio_copyin(const void *, void *, size_t, uio_seg_t);
251 int	uio_copyout(const void *, void *, size_t, uio_seg_t);
252 
253 int	uioamove(void *, size_t, enum uio_rw, uioa_t *);
254 int	uioainit(uio_t *, uioa_t *);
255 int	uioafini(uio_t *, uioa_t *);
256 extern	uioasync_t uioasync;
257 
258 #else	/* defined(_KERNEL) */
259 
260 extern ssize_t readv(int, const struct iovec *, int);
261 extern ssize_t writev(int, const struct iovec *, int);
262 
263 /*
264  * When in the large file compilation environment,
265  * map preadv/pwritev to their 64 bit offset versions
266  */
267 #if !defined(_LP64) && _FILE_OFFSET_BITS == 64
268 #ifdef __PRAGMA_REDEFINE_EXTNAME
269 #pragma	redefine_extname	preadv	preadv64
270 #pragma	redefine_extname	pwritev	pwritev64
271 #else /* __PRAGMA_REDEFINE_EXTNAME */
272 #define	preadv	preadv64
273 #define	pwritev	pwritev64
274 #endif /* __PRAGMA_REDEFINE_EXTNAME */
275 #endif /* !_LP64 && _FILE_OFFSET_BITS == 64 */
276 
277 /* In the LP64 compilation environment, the APIs are already large file */
278 #if defined(_LP64) && defined(_LARGEFILE64_SOURCE)
279 #ifdef  __PRAGMA_REDEFINE_EXTNAME
280 #pragma	redefine_extname	preadv64	preadv
281 #pragma	redefine_extname	pwritev64	pwritev
282 #else   /* __PRAGMA_REDEFINE_EXTNAME */
283 #define	preadv64	preadv
284 #define	pwritev64	pwritev
285 #endif  /* __PRAGMA_REDEFINE_EXTNAME */
286 #endif  /* _LP64 && _LARGEFILE64_SOURCE */
287 
288 extern ssize_t preadv(int, const struct iovec *, int, off_t);
289 extern ssize_t pwritev(int, const struct iovec *, int, off_t);
290 
291 /*
292  * preadv64 and pwritev64 should be defined when:
293  * - Using the transitional compilation environment, and not
294  *     the large file compilation environment.
295  */
296 #if defined(_LARGEFILE64_SOURCE) && !((_FILE_OFFSET_BITS == 64) && \
297 	!defined(__PRAGMA_REDEFINE_EXTNAME))
298 extern ssize_t preadv64(int, const struct iovec *, int, off64_t);
299 extern ssize_t pwritev64(int, const struct iovec *, int, off64_t);
300 #endif /* _LARGEFILE64_SOURCE */
301 
302 #endif	/* defined(_KERNEL) */
303 
304 #ifdef	__cplusplus
305 }
306 #endif
307 
308 #endif	/* _SYS_UIO_H */
309