1 /* 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 39 * $FreeBSD: src/sys/kern/kern_subr.c,v 1.31.2.2 2002/04/21 08:09:37 bde Exp $ 40 * $DragonFly: src/sys/kern/kern_subr.c,v 1.20 2004/11/09 17:52:45 joerg Exp $ 41 */ 42 43 #include "opt_ddb.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/proc.h> 49 #include <sys/malloc.h> 50 #include <sys/lock.h> 51 #include <sys/resourcevar.h> 52 #include <sys/sysctl.h> 53 #include <sys/uio.h> 54 #include <sys/vnode.h> 55 #include <machine/limits.h> 56 57 #include <vm/vm.h> 58 #include <vm/vm_page.h> 59 #include <vm/vm_map.h> 60 61 SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV, 62 "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)"); 63 64 /* 65 * UIO_READ: copy the kernelspace cp to the user or kernelspace UIO 66 * UIO_WRITE: copy the user or kernelspace UIO to cp 67 * 68 * For userspace UIO's, uio_td must be the current thread. 69 */ 70 int 71 uiomove(caddr_t cp, int n, struct uio *uio) 72 { 73 struct iovec *iov; 74 u_int cnt; 75 int error = 0; 76 int save = 0; 77 int baseticks = ticks; 78 79 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 80 ("uiomove: mode")); 81 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 82 ("uiomove proc")); 83 84 if (curproc) { 85 save = curproc->p_flag & P_DEADLKTREAT; 86 curproc->p_flag |= P_DEADLKTREAT; 87 } 88 89 while (n > 0 && uio->uio_resid) { 90 iov = uio->uio_iov; 91 cnt = iov->iov_len; 92 if (cnt == 0) { 93 uio->uio_iov++; 94 uio->uio_iovcnt--; 95 continue; 96 } 97 if (cnt > n) 98 cnt = n; 99 100 switch (uio->uio_segflg) { 101 102 case UIO_USERSPACE: 103 if (ticks - baseticks >= hogticks) { 104 uio_yield(); 105 baseticks = ticks; 106 } 107 if (uio->uio_rw == UIO_READ) 108 error = copyout(cp, iov->iov_base, cnt); 109 else 110 error = copyin(iov->iov_base, cp, cnt); 111 if (error) 112 break; 113 break; 114 115 case UIO_SYSSPACE: 116 if (uio->uio_rw == UIO_READ) 117 bcopy((caddr_t)cp, iov->iov_base, cnt); 118 else 119 bcopy(iov->iov_base, (caddr_t)cp, cnt); 120 break; 121 case UIO_NOCOPY: 122 break; 123 } 124 iov->iov_base += cnt; 125 iov->iov_len -= cnt; 126 uio->uio_resid -= cnt; 127 uio->uio_offset += cnt; 128 cp += cnt; 129 n -= cnt; 130 } 131 if (curproc) 132 curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save; 133 return (error); 134 } 135 /* 136 * Wrapper for uiomove() that validates the arguments against a known-good 137 * kernel buffer. Currently, uiomove accepts a signed (n) argument, which 138 * is almost definitely a bad thing, so we catch that here as well. We 139 * return a runtime failure, but it might be desirable to generate a runtime 140 * assertion failure instead. 141 */ 142 int 143 uiomove_frombuf(void *buf, int buflen, struct uio *uio) 144 { 145 unsigned int offset, n; 146 147 if (uio->uio_offset < 0 || uio->uio_resid < 0 || 148 (offset = uio->uio_offset) != uio->uio_offset) 149 return (EINVAL); 150 if (buflen <= 0 || offset >= buflen) 151 return (0); 152 if ((n = buflen - offset) > INT_MAX) 153 return (EINVAL); 154 return (uiomove((char *)buf + offset, n, uio)); 155 } 156 157 158 int 159 uiomoveco(cp, n, uio, obj) 160 caddr_t cp; 161 int n; 162 struct uio *uio; 163 struct vm_object *obj; 164 { 165 struct iovec *iov; 166 u_int cnt; 167 int error; 168 int baseticks = ticks; 169 170 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 171 ("uiomoveco: mode")); 172 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 173 ("uiomoveco proc")); 174 175 while (n > 0 && uio->uio_resid) { 176 iov = uio->uio_iov; 177 cnt = iov->iov_len; 178 if (cnt == 0) { 179 uio->uio_iov++; 180 uio->uio_iovcnt--; 181 continue; 182 } 183 if (cnt > n) 184 cnt = n; 185 186 switch (uio->uio_segflg) { 187 188 case UIO_USERSPACE: 189 if (ticks - baseticks >= hogticks) { 190 uio_yield(); 191 baseticks = ticks; 192 } 193 if (uio->uio_rw == UIO_READ) { 194 error = copyout(cp, iov->iov_base, cnt); 195 } else { 196 error = copyin(iov->iov_base, cp, cnt); 197 } 198 if (error) 199 return (error); 200 break; 201 202 case UIO_SYSSPACE: 203 if (uio->uio_rw == UIO_READ) 204 bcopy((caddr_t)cp, iov->iov_base, cnt); 205 else 206 bcopy(iov->iov_base, (caddr_t)cp, cnt); 207 break; 208 case UIO_NOCOPY: 209 break; 210 } 211 iov->iov_base += cnt; 212 iov->iov_len -= cnt; 213 uio->uio_resid -= cnt; 214 uio->uio_offset += cnt; 215 cp += cnt; 216 n -= cnt; 217 } 218 return (0); 219 } 220 221 /* 222 * Give next character to user as result of read. 223 */ 224 int 225 ureadc(c, uio) 226 int c; 227 struct uio *uio; 228 { 229 struct iovec *iov; 230 231 again: 232 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 233 panic("ureadc"); 234 iov = uio->uio_iov; 235 if (iov->iov_len == 0) { 236 uio->uio_iovcnt--; 237 uio->uio_iov++; 238 goto again; 239 } 240 switch (uio->uio_segflg) { 241 242 case UIO_USERSPACE: 243 if (subyte(iov->iov_base, c) < 0) 244 return (EFAULT); 245 break; 246 247 case UIO_SYSSPACE: 248 *iov->iov_base = c; 249 break; 250 251 case UIO_NOCOPY: 252 break; 253 } 254 iov->iov_base++; 255 iov->iov_len--; 256 uio->uio_resid--; 257 uio->uio_offset++; 258 return (0); 259 } 260 261 /* 262 * General routine to allocate a hash table. Make the hash table size a 263 * power of 2 greater or equal to the number of elements requested, and 264 * store the masking value in *hashmask. 265 */ 266 void * 267 hashinit(elements, type, hashmask) 268 int elements; 269 struct malloc_type *type; 270 u_long *hashmask; 271 { 272 long hashsize; 273 LIST_HEAD(generic, generic) *hashtbl; 274 int i; 275 276 if (elements <= 0) 277 panic("hashinit: bad elements"); 278 for (hashsize = 2; hashsize < elements; hashsize <<= 1) 279 continue; 280 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 281 for (i = 0; i < hashsize; i++) 282 LIST_INIT(&hashtbl[i]); 283 *hashmask = hashsize - 1; 284 return (hashtbl); 285 } 286 287 static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039, 288 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653, 289 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; 290 #define NPRIMES (sizeof(primes) / sizeof(primes[0])) 291 292 /* 293 * General routine to allocate a prime number sized hash table. 294 */ 295 void * 296 phashinit(elements, type, nentries) 297 int elements; 298 struct malloc_type *type; 299 u_long *nentries; 300 { 301 long hashsize; 302 LIST_HEAD(generic, generic) *hashtbl; 303 int i; 304 305 if (elements <= 0) 306 panic("phashinit: bad elements"); 307 for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 308 i++; 309 if (i == NPRIMES) 310 break; 311 hashsize = primes[i]; 312 } 313 hashsize = primes[i - 1]; 314 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 315 for (i = 0; i < hashsize; i++) 316 LIST_INIT(&hashtbl[i]); 317 *nentries = hashsize; 318 return (hashtbl); 319 } 320 321 /* 322 * Copyin an iovec. If the iovec array fits, use the preallocated small 323 * iovec structure. If it is too big, dynamically allocate an iovec array 324 * of sufficient size. 325 */ 326 int 327 iovec_copyin(struct iovec *uiov, struct iovec **kiov, struct iovec *siov, 328 size_t iov_cnt, size_t *iov_len) 329 { 330 struct iovec *iovp; 331 int error, i; 332 333 if (iov_cnt >= UIO_MAXIOV) 334 return EMSGSIZE; 335 if (iov_cnt >= UIO_SMALLIOV) { 336 MALLOC(*kiov, struct iovec *, sizeof(struct iovec) * iov_cnt, 337 M_IOV, M_WAITOK); 338 } else { 339 *kiov = siov; 340 } 341 error = copyin(uiov, *kiov, iov_cnt * sizeof(struct iovec)); 342 if (error) 343 goto cleanup; 344 *iov_len = 0; 345 for (i = 0, iovp = *kiov; i < iov_cnt; i++, iovp++) 346 *iov_len += iovp->iov_len; 347 348 cleanup: 349 if (error) 350 iovec_free(kiov, siov); 351 return (error); 352 } 353