xref: /freebsd/sys/contrib/openzfs/include/os/linux/spl/sys/uio.h (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
4  *  Copyright (C) 2007 The Regents of the University of California.
5  *  Copyright (c) 2015 by Chunwei Chen. All rights reserved.
6  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
7  *  Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8  *  UCRL-CODE-235197
9  *
10  *  This file is part of the SPL, Solaris Porting Layer.
11  *
12  *  The SPL is free software; you can redistribute it and/or modify it
13  *  under the terms of the GNU General Public License as published by the
14  *  Free Software Foundation; either version 2 of the License, or (at your
15  *  option) any later version.
16  *
17  *  The SPL is distributed in the hope that it will be useful, but WITHOUT
18  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  *  for more details.
21  *
22  *  You should have received a copy of the GNU General Public License along
23  *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #ifndef _SPL_UIO_H
27 #define	_SPL_UIO_H
28 
29 #include <sys/debug.h>
30 #include <linux/uio.h>
31 #include <linux/blkdev.h>
32 #include <linux/blkdev_compat.h>
33 #include <linux/mm.h>
34 #include <linux/bio.h>
35 #include <asm/uaccess.h>
36 #include <sys/types.h>
37 #include <sys/string.h>
38 
39 /*
40  * uio_extflg: extended flags
41  */
42 #define	UIO_DIRECT	0x0001 /* Direct I/O request */
43 
44 #if defined(HAVE_FAULT_IN_IOV_ITER_READABLE)
45 #define	iov_iter_fault_in_readable(a, b)	fault_in_iov_iter_readable(a, b)
46 #endif
47 
48 typedef struct iovec iovec_t;
49 
50 typedef enum zfs_uio_rw {
51 	UIO_READ =		0,
52 	UIO_WRITE =		1,
53 } zfs_uio_rw_t;
54 
55 typedef enum zfs_uio_seg {
56 	UIO_SYSSPACE =		0,
57 	UIO_BVEC =		1,
58 	UIO_ITER =		2,
59 } zfs_uio_seg_t;
60 
61 /*
62  * This structures is used when doing Direct I/O.
63  */
64 typedef struct {
65 	struct page	**pages;	/* Mapped pages */
66 	long 		npages;		/* Number of mapped pages */
67 	boolean_t	pinned;		/* Whether FOLL_PIN was used */
68 } zfs_uio_dio_t;
69 
70 typedef struct zfs_uio {
71 	union {
72 		const struct iovec	*uio_iov;
73 		const struct bio_vec	*uio_bvec;
74 		struct iov_iter		*uio_iter;
75 	};
76 	int		uio_iovcnt;	/* Number of iovecs */
77 	offset_t	uio_soffset;	/* Starting logical offset */
78 	offset_t	uio_loffset;	/* Current logical offset */
79 	zfs_uio_seg_t	uio_segflg;	/* Segment type */
80 	boolean_t	uio_fault_disable;
81 	uint16_t	uio_fmode;	/* Access mode (unused) */
82 	uint16_t	uio_extflg;	/* Extra flags (UIO_DIRECT) */
83 	ssize_t		uio_resid;	/* Residual unprocessed bytes */
84 	size_t		uio_skip;	/* Skipped bytes in current iovec */
85 	zfs_uio_dio_t	uio_dio;	/* Direct I/O user pages */
86 
87 	struct request	*rq;
88 } zfs_uio_t;
89 
90 
91 #define	zfs_uio_segflg(u)		(u)->uio_segflg
92 #define	zfs_uio_offset(u)		(u)->uio_loffset
93 #define	zfs_uio_resid(u)		(u)->uio_resid
94 #define	zfs_uio_iovcnt(u)		(u)->uio_iovcnt
95 #define	zfs_uio_iovlen(u, idx)		(u)->uio_iov[(idx)].iov_len
96 #define	zfs_uio_iovbase(u, idx)		(u)->uio_iov[(idx)].iov_base
97 #define	zfs_uio_fault_disable(u, set)	(u)->uio_fault_disable = set
98 #define	zfs_uio_soffset(u)		(u)->uio_soffset
99 #define	zfs_uio_rlimit_fsize(z, u)	(0)
100 #define	zfs_uio_fault_move(p, n, rw, u)	zfs_uiomove((p), (n), (rw), (u))
101 
102 extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *);
103 
104 static inline void
zfs_uio_setoffset(zfs_uio_t * uio,offset_t off)105 zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
106 {
107 	uio->uio_loffset = off;
108 }
109 
110 static inline void
zfs_uio_setsoffset(zfs_uio_t * uio,offset_t off)111 zfs_uio_setsoffset(zfs_uio_t *uio, offset_t off)
112 {
113 	ASSERT3U(zfs_uio_offset(uio), ==, off);
114 	zfs_uio_soffset(uio) = off;
115 }
116 
117 static inline void
zfs_uio_advance(zfs_uio_t * uio,ssize_t size)118 zfs_uio_advance(zfs_uio_t *uio, ssize_t size)
119 {
120 	uio->uio_resid -= size;
121 	uio->uio_loffset += size;
122 }
123 
124 static inline void
zfs_uio_iovec_init(zfs_uio_t * uio,const struct iovec * iov,unsigned long nr_segs,offset_t offset,zfs_uio_seg_t seg,ssize_t resid,size_t skip)125 zfs_uio_iovec_init(zfs_uio_t *uio, const struct iovec *iov,
126     unsigned long nr_segs, offset_t offset, zfs_uio_seg_t seg, ssize_t resid,
127     size_t skip)
128 {
129 	ASSERT(seg == UIO_SYSSPACE);
130 
131 	uio->uio_iov = iov;
132 	uio->uio_iovcnt = nr_segs;
133 	uio->uio_loffset = offset;
134 	uio->uio_segflg = seg;
135 	uio->uio_fault_disable = B_FALSE;
136 	uio->uio_fmode = 0;
137 	uio->uio_extflg = 0;
138 	uio->uio_resid = resid;
139 	uio->uio_skip = skip;
140 	uio->uio_soffset = uio->uio_loffset;
141 	memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t));
142 }
143 
144 static inline void
zfs_uio_bvec_init(zfs_uio_t * uio,struct bio * bio,struct request * rq)145 zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq)
146 {
147 	/* Either bio or rq will be set, but not both */
148 	ASSERT3P(uio, !=, bio);
149 
150 	if (bio) {
151 		uio->uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio);
152 		uio->uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)];
153 	} else {
154 		uio->uio_bvec = NULL;
155 		uio->uio_iovcnt = 0;
156 	}
157 
158 	uio->uio_loffset = io_offset(bio, rq);
159 	uio->uio_segflg = UIO_BVEC;
160 	uio->uio_fault_disable = B_FALSE;
161 	uio->uio_fmode = 0;
162 	uio->uio_extflg = 0;
163 	uio->uio_resid = io_size(bio, rq);
164 	if (bio) {
165 		uio->uio_skip = BIO_BI_SKIP(bio);
166 	} else {
167 		uio->uio_skip = 0;
168 	}
169 
170 	uio->rq = rq;
171 	uio->uio_soffset = uio->uio_loffset;
172 	memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t));
173 }
174 
175 static inline void
zfs_uio_iov_iter_init(zfs_uio_t * uio,struct iov_iter * iter,offset_t offset,ssize_t resid,size_t skip)176 zfs_uio_iov_iter_init(zfs_uio_t *uio, struct iov_iter *iter, offset_t offset,
177     ssize_t resid, size_t skip)
178 {
179 	uio->uio_iter = iter;
180 	uio->uio_iovcnt = iter->nr_segs;
181 	uio->uio_loffset = offset;
182 	uio->uio_segflg = UIO_ITER;
183 	uio->uio_fault_disable = B_FALSE;
184 	uio->uio_fmode = 0;
185 	uio->uio_extflg = 0;
186 	uio->uio_resid = resid;
187 	uio->uio_skip = skip;
188 	uio->uio_soffset = uio->uio_loffset;
189 	memset(&uio->uio_dio, 0, sizeof (zfs_uio_dio_t));
190 }
191 
192 #if defined(HAVE_ITER_IOV)
193 #define	zfs_uio_iter_iov(iter)	iter_iov((iter))
194 #else
195 #define	zfs_uio_iter_iov(iter)	(iter)->iov
196 #endif
197 
198 #if defined(HAVE_IOV_ITER_TYPE)
199 #define	zfs_uio_iov_iter_type(iter)	iov_iter_type((iter))
200 #else
201 #define	zfs_uio_iov_iter_type(iter)	(iter)->type
202 #endif
203 
204 #if defined(HAVE_ITER_IS_UBUF)
205 #define	zfs_user_backed_iov_iter(iter)	\
206 	(iter_is_ubuf((iter)) || \
207 	(zfs_uio_iov_iter_type((iter)) == ITER_IOVEC))
208 #else
209 #define	zfs_user_backed_iov_iter(iter) \
210 	(zfs_uio_iov_iter_type((iter)) == ITER_IOVEC)
211 #endif
212 
213 #endif /* SPL_UIO_H */
214