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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
39 * Copyright (c) 2015 by Chunwei Chen. All rights reserved.
44 #include <sys/types.h>
45 #include <sys/uio_impl.h>
46 #include <sys/sysmacros.h>
47 #include <sys/string.h>
48 #include <linux/kmap_compat.h>
49 #include <linux/uaccess.h>
52 * Move "n" bytes at byte address "p"; "rw" indicates the direction
53 * of the move, and the I/O parameters are provided in "uio", which is
54 * update to reflect the data which was moved. Returns 0 on success or
55 * a non-zero errno on failure.
58 zfs_uiomove_iov(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
)
60 const struct iovec
*iov
= uio
->uio_iov
;
61 size_t skip
= uio
->uio_skip
;
64 while (n
&& uio
->uio_resid
) {
65 cnt
= MIN(iov
->iov_len
- skip
, n
);
66 switch (uio
->uio_segflg
) {
69 * p = kernel data pointer
70 * iov->iov_base = user data pointer
73 if (copy_to_user(iov
->iov_base
+skip
, p
, cnt
))
76 unsigned long b_left
= 0;
77 if (uio
->uio_fault_disable
) {
78 if (!zfs_access_ok(VERIFY_READ
,
79 (iov
->iov_base
+ skip
), cnt
)) {
84 __copy_from_user_inatomic(p
,
85 (iov
->iov_base
+ skip
), cnt
);
90 (iov
->iov_base
+ skip
), cnt
);
93 unsigned long c_bytes
=
95 uio
->uio_skip
+= c_bytes
;
96 ASSERT3U(uio
->uio_skip
, <,
98 uio
->uio_resid
-= c_bytes
;
99 uio
->uio_loffset
+= c_bytes
;
106 memcpy(iov
->iov_base
+ skip
, p
, cnt
);
108 memcpy(p
, iov
->iov_base
+ skip
, cnt
);
114 if (skip
== iov
->iov_len
) {
116 uio
->uio_iov
= (++iov
);
119 uio
->uio_skip
= skip
;
120 uio
->uio_resid
-= cnt
;
121 uio
->uio_loffset
+= cnt
;
122 p
= (caddr_t
)p
+ cnt
;
129 zfs_uiomove_bvec_impl(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
)
131 const struct bio_vec
*bv
= uio
->uio_bvec
;
132 size_t skip
= uio
->uio_skip
;
135 while (n
&& uio
->uio_resid
) {
137 cnt
= MIN(bv
->bv_len
- skip
, n
);
139 paddr
= zfs_kmap_atomic(bv
->bv_page
);
140 if (rw
== UIO_READ
) {
141 /* Copy from buffer 'p' to the bvec data */
142 memcpy(paddr
+ bv
->bv_offset
+ skip
, p
, cnt
);
144 /* Copy from bvec data to buffer 'p' */
145 memcpy(p
, paddr
+ bv
->bv_offset
+ skip
, cnt
);
147 zfs_kunmap_atomic(paddr
);
150 if (skip
== bv
->bv_len
) {
152 uio
->uio_bvec
= (++bv
);
155 uio
->uio_skip
= skip
;
156 uio
->uio_resid
-= cnt
;
157 uio
->uio_loffset
+= cnt
;
158 p
= (caddr_t
)p
+ cnt
;
166 zfs_copy_bvec(void *p
, size_t skip
, size_t cnt
, zfs_uio_rw_t rw
,
171 paddr
= zfs_kmap_atomic(bv
->bv_page
);
172 if (rw
== UIO_READ
) {
173 /* Copy from buffer 'p' to the bvec data */
174 memcpy(paddr
+ bv
->bv_offset
+ skip
, p
, cnt
);
176 /* Copy from bvec data to buffer 'p' */
177 memcpy(p
, paddr
+ bv
->bv_offset
+ skip
, cnt
);
179 zfs_kunmap_atomic(paddr
);
183 * Copy 'n' bytes of data between the buffer p[] and the data represented
184 * by the request in the uio.
187 zfs_uiomove_bvec_rq(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
)
189 struct request
*rq
= uio
->rq
;
191 struct req_iterator iter
;
192 size_t this_seg_start
; /* logical offset */
193 size_t this_seg_end
; /* logical offset */
195 size_t copy_from_seg
;
200 * Get the original logical offset of this entire request (because
201 * uio->uio_loffset will be modified over time).
203 orig_loffset
= io_offset(NULL
, rq
);
204 this_seg_start
= orig_loffset
;
206 rq_for_each_segment(bv
, rq
, iter
) {
209 * If uio->iter.bio is present, then we know we've saved
210 * uio->iter from a previous call to this function, and
211 * we can skip ahead in this rq_for_each_segment() loop
212 * to where we last left off. That way, we don't need
213 * to iterate over tons of segments we've already
214 * processed - we can just restore the "saved state".
218 this_seg_start
= uio
->uio_loffset
;
219 memset(&uio
->iter
, 0, sizeof (uio
->iter
));
224 * Lookup what the logical offset of the last byte of this
227 this_seg_end
= this_seg_start
+ bv
.bv_len
- 1;
230 * We only need to operate on segments that have data we're
233 if (uio
->uio_loffset
>= this_seg_start
&&
234 uio
->uio_loffset
<= this_seg_end
) {
236 * Some, or all, of the data in this segment needs to be
241 * We may be not be copying from the first byte in the
242 * segment. Figure out how many bytes to skip copying
243 * from the beginning of this segment.
245 skip_in_seg
= uio
->uio_loffset
- this_seg_start
;
248 * Calculate the total number of bytes from this
249 * segment that we will be copying.
251 copy_from_seg
= MIN(bv
.bv_len
- skip_in_seg
, n
);
254 zfs_copy_bvec(p
, skip_in_seg
, copy_from_seg
, rw
, &bv
);
255 p
= ((char *)p
) + copy_from_seg
;
258 uio
->uio_resid
-= copy_from_seg
;
259 uio
->uio_loffset
+= copy_from_seg
;
260 copied
= 1; /* We copied some data */
265 * All done copying. Save our 'iter' value to the uio.
266 * This allows us to "save our state" and skip ahead in
267 * the rq_for_each_segment() loop the next time we call
268 * call zfs_uiomove_bvec_rq() on this uio (which we
269 * will be doing for any remaining data in the uio).
271 uio
->iter
= iter
; /* make a copy of the struct data */
276 this_seg_start
= this_seg_end
+ 1;
280 /* Didn't copy anything */
288 zfs_uiomove_bvec(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
)
292 return (zfs_uiomove_bvec_rq(p
, n
, rw
, uio
));
294 ASSERT3P(uio
->rq
, ==, NULL
);
296 return (zfs_uiomove_bvec_impl(p
, n
, rw
, uio
));
299 #if defined(HAVE_VFS_IOV_ITER)
301 zfs_uiomove_iter(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
,
304 size_t cnt
= MIN(n
, uio
->uio_resid
);
307 iov_iter_advance(uio
->uio_iter
, uio
->uio_skip
);
310 cnt
= copy_to_iter(p
, cnt
, uio
->uio_iter
);
312 cnt
= copy_from_iter(p
, cnt
, uio
->uio_iter
);
315 * When operating on a full pipe no bytes are processed.
316 * In which case return EFAULT which is converted to EAGAIN
317 * by the kernel's generic_file_splice_read() function.
323 * Revert advancing the uio_iter. This is set by zfs_uiocopy()
324 * to avoid consuming the uio and its iov_iter structure.
327 iov_iter_revert(uio
->uio_iter
, cnt
);
329 uio
->uio_resid
-= cnt
;
330 uio
->uio_loffset
+= cnt
;
337 zfs_uiomove(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
)
339 if (uio
->uio_segflg
== UIO_BVEC
)
340 return (zfs_uiomove_bvec(p
, n
, rw
, uio
));
341 #if defined(HAVE_VFS_IOV_ITER)
342 else if (uio
->uio_segflg
== UIO_ITER
)
343 return (zfs_uiomove_iter(p
, n
, rw
, uio
, B_FALSE
));
346 return (zfs_uiomove_iov(p
, n
, rw
, uio
));
348 EXPORT_SYMBOL(zfs_uiomove
);
351 * Fault in the pages of the first n bytes specified by the uio structure.
352 * 1 byte in each page is touched and the uio struct is unmodified. Any
353 * error will terminate the process as this is only a best attempt to get
354 * the pages resident.
357 zfs_uio_prefaultpages(ssize_t n
, zfs_uio_t
*uio
)
359 if (uio
->uio_segflg
== UIO_SYSSPACE
|| uio
->uio_segflg
== UIO_BVEC
) {
360 /* There's never a need to fault in kernel pages */
362 #if defined(HAVE_VFS_IOV_ITER)
363 } else if (uio
->uio_segflg
== UIO_ITER
) {
365 * At least a Linux 4.9 kernel, iov_iter_fault_in_readable()
366 * can be relied on to fault in user pages when referenced.
368 if (iov_iter_fault_in_readable(uio
->uio_iter
, n
))
372 /* Fault in all user pages */
373 ASSERT3S(uio
->uio_segflg
, ==, UIO_USERSPACE
);
374 const struct iovec
*iov
= uio
->uio_iov
;
375 int iovcnt
= uio
->uio_iovcnt
;
376 size_t skip
= uio
->uio_skip
;
380 for (; n
> 0 && iovcnt
> 0; iov
++, iovcnt
--, skip
= 0) {
381 ulong_t cnt
= MIN(iov
->iov_len
- skip
, n
);
386 /* touch each page in this segment. */
387 p
= iov
->iov_base
+ skip
;
389 if (copy_from_user(&tmp
, p
, 1))
391 ulong_t incr
= MIN(cnt
, PAGESIZE
);
395 /* touch the last byte in case it straddles a page. */
397 if (copy_from_user(&tmp
, p
, 1))
404 EXPORT_SYMBOL(zfs_uio_prefaultpages
);
407 * The same as zfs_uiomove() but doesn't modify uio structure.
408 * return in cbytes how many bytes were copied.
411 zfs_uiocopy(void *p
, size_t n
, zfs_uio_rw_t rw
, zfs_uio_t
*uio
, size_t *cbytes
)
416 memcpy(&uio_copy
, uio
, sizeof (zfs_uio_t
));
418 if (uio
->uio_segflg
== UIO_BVEC
)
419 ret
= zfs_uiomove_bvec(p
, n
, rw
, &uio_copy
);
420 #if defined(HAVE_VFS_IOV_ITER)
421 else if (uio
->uio_segflg
== UIO_ITER
)
422 ret
= zfs_uiomove_iter(p
, n
, rw
, &uio_copy
, B_TRUE
);
425 ret
= zfs_uiomove_iov(p
, n
, rw
, &uio_copy
);
427 *cbytes
= uio
->uio_resid
- uio_copy
.uio_resid
;
431 EXPORT_SYMBOL(zfs_uiocopy
);
434 * Drop the next n chars out of *uio.
437 zfs_uioskip(zfs_uio_t
*uio
, size_t n
)
439 if (n
> uio
->uio_resid
)
442 * When using a uio with a struct request, we simply
443 * use uio_loffset as a pointer to the next logical byte to
444 * copy in the request. We don't have to do any fancy
445 * accounting with uio_bvec/uio_iovcnt since we don't use
448 if (uio
->uio_segflg
== UIO_BVEC
&& uio
->rq
== NULL
) {
450 while (uio
->uio_iovcnt
&&
451 uio
->uio_skip
>= uio
->uio_bvec
->bv_len
) {
452 uio
->uio_skip
-= uio
->uio_bvec
->bv_len
;
456 #if defined(HAVE_VFS_IOV_ITER)
457 } else if (uio
->uio_segflg
== UIO_ITER
) {
458 iov_iter_advance(uio
->uio_iter
, n
);
462 while (uio
->uio_iovcnt
&&
463 uio
->uio_skip
>= uio
->uio_iov
->iov_len
) {
464 uio
->uio_skip
-= uio
->uio_iov
->iov_len
;
469 uio
->uio_loffset
+= n
;
472 EXPORT_SYMBOL(zfs_uioskip
);