]> git.proxmox.com Git - mirror_zfs.git/blame - module/zcommon/zfs_uio.c
cstyle: Resolve C style issues
[mirror_zfs.git] / module / zcommon / zfs_uio.c
CommitLineData
590329b5
BB
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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27/* All Rights Reserved */
28
29/*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39/*
40 * The uio support from OpenSolaris has been added as a short term
41 * work around. The hope is to adopt native Linux type and drop the
42 * use of uio's entirely. Under Linux they only add overhead and
43 * when possible we want to use native APIs for the ZPL layer.
44 */
45#ifdef _KERNEL
46
47#include <sys/types.h>
48#include <sys/uio_impl.h>
49
50/*
51 * Move "n" bytes at byte address "p"; "rw" indicates the direction
52 * of the move, and the I/O parameters are provided in "uio", which is
53 * update to reflect the data which was moved. Returns 0 on success or
54 * a non-zero errno on failure.
55 */
56int
57uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio)
58{
59 struct iovec *iov;
60 ulong_t cnt;
61
62 while (n && uio->uio_resid) {
63 iov = uio->uio_iov;
64 cnt = MIN(iov->iov_len, n);
65 if (cnt == 0l) {
66 uio->uio_iov++;
67 uio->uio_iovcnt--;
68 continue;
69 }
70 switch (uio->uio_segflg) {
71 case UIO_USERSPACE:
72 case UIO_USERISPACE:
d1d7e268
MK
73 /*
74 * p = kernel data pointer
75 * iov->iov_base = user data pointer
76 */
590329b5
BB
77 if (rw == UIO_READ) {
78 if (copy_to_user(iov->iov_base, p, cnt))
d1d7e268 79 return (EFAULT);
590329b5 80 } else {
590329b5 81 if (copy_from_user(p, iov->iov_base, cnt))
d1d7e268 82 return (EFAULT);
590329b5
BB
83 }
84 break;
85 case UIO_SYSSPACE:
86 if (rw == UIO_READ)
87 bcopy(p, iov->iov_base, cnt);
88 else
89 bcopy(iov->iov_base, p, cnt);
90 break;
91 }
92 iov->iov_base += cnt;
93 iov->iov_len -= cnt;
94 uio->uio_resid -= cnt;
95 uio->uio_loffset += cnt;
96 p = (caddr_t)p + cnt;
97 n -= cnt;
98 }
99 return (0);
100}
101EXPORT_SYMBOL(uiomove);
102
d1d7e268 103#define fuword8(uptr, vptr) get_user((*vptr), (uptr))
590329b5
BB
104
105/*
106 * Fault in the pages of the first n bytes specified by the uio structure.
107 * 1 byte in each page is touched and the uio struct is unmodified. Any
108 * error will terminate the process as this is only a best attempt to get
109 * the pages resident.
110 */
111void
112uio_prefaultpages(ssize_t n, struct uio *uio)
113{
114 struct iovec *iov;
115 ulong_t cnt, incr;
116 caddr_t p;
117 uint8_t tmp;
118 int iovcnt;
119
120 iov = uio->uio_iov;
121 iovcnt = uio->uio_iovcnt;
122
123 while ((n > 0) && (iovcnt > 0)) {
124 cnt = MIN(iov->iov_len, n);
125 if (cnt == 0) {
126 /* empty iov entry */
127 iov++;
128 iovcnt--;
129 continue;
130 }
131 n -= cnt;
132 /*
133 * touch each page in this segment.
134 */
135 p = iov->iov_base;
136 while (cnt) {
137 switch (uio->uio_segflg) {
138 case UIO_USERSPACE:
139 case UIO_USERISPACE:
140 if (fuword8((uint8_t *) p, &tmp))
141 return;
142 break;
143 case UIO_SYSSPACE:
144 bcopy(p, &tmp, 1);
145 break;
146 }
147 incr = MIN(cnt, PAGESIZE);
148 p += incr;
149 cnt -= incr;
150 }
151 /*
152 * touch the last byte in case it straddles a page.
153 */
154 p--;
155 switch (uio->uio_segflg) {
156 case UIO_USERSPACE:
157 case UIO_USERISPACE:
158 if (fuword8((uint8_t *) p, &tmp))
159 return;
160 break;
161 case UIO_SYSSPACE:
162 bcopy(p, &tmp, 1);
163 break;
164 }
165 iov++;
166 iovcnt--;
167 }
168}
169EXPORT_SYMBOL(uio_prefaultpages);
170
171/*
172 * same as uiomove() but doesn't modify uio structure.
173 * return in cbytes how many bytes were copied.
174 */
175int
176uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes)
177{
178 struct iovec *iov;
179 ulong_t cnt;
180 int iovcnt;
181
182 iovcnt = uio->uio_iovcnt;
183 *cbytes = 0;
184
185 for (iov = uio->uio_iov; n && iovcnt; iov++, iovcnt--) {
186 cnt = MIN(iov->iov_len, n);
187 if (cnt == 0)
188 continue;
189
190 switch (uio->uio_segflg) {
191
192 case UIO_USERSPACE:
193 case UIO_USERISPACE:
d1d7e268
MK
194 /*
195 * p = kernel data pointer
196 * iov->iov_base = user data pointer
197 */
590329b5 198 if (rw == UIO_READ) {
d1d7e268 199 /* UIO_READ = copy data from kernel to user */
590329b5 200 if (copy_to_user(iov->iov_base, p, cnt))
d1d7e268 201 return (EFAULT);
590329b5 202 } else {
d1d7e268 203 /* UIO_WRITE = copy data from user to kernel */
590329b5 204 if (copy_from_user(p, iov->iov_base, cnt))
d1d7e268 205 return (EFAULT);
590329b5
BB
206 }
207 break;
208
209 case UIO_SYSSPACE:
210 if (rw == UIO_READ)
211 bcopy(p, iov->iov_base, cnt);
212 else
213 bcopy(iov->iov_base, p, cnt);
214 break;
215 }
216 p = (caddr_t)p + cnt;
217 n -= cnt;
218 *cbytes += cnt;
219 }
220 return (0);
221}
222EXPORT_SYMBOL(uiocopy);
223
224/*
225 * Drop the next n chars out of *uiop.
226 */
227void
228uioskip(uio_t *uiop, size_t n)
229{
230 if (n > uiop->uio_resid)
231 return;
232 while (n != 0) {
233 iovec_t *iovp = uiop->uio_iov;
234 size_t niovb = MIN(iovp->iov_len, n);
235
236 if (niovb == 0) {
237 uiop->uio_iov++;
238 uiop->uio_iovcnt--;
239 continue;
240 }
241 iovp->iov_base += niovb;
242 uiop->uio_loffset += niovb;
243 iovp->iov_len -= niovb;
244 uiop->uio_resid -= niovb;
245 n -= niovb;
246 }
247}
248EXPORT_SYMBOL(uioskip);
249#endif /* _KERNEL */