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.11 2003/10/02 19:21:06 drhodus 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/vnode.h> 53 #include <machine/limits.h> 54 55 #include <vm/vm.h> 56 #include <vm/vm_page.h> 57 #include <vm/vm_map.h> 58 59 int 60 uiomove(cp, n, uio) 61 caddr_t cp; 62 int n; 63 struct uio *uio; 64 { 65 struct iovec *iov; 66 u_int cnt; 67 int error = 0; 68 int save = 0; 69 int baseticks = ticks; 70 71 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 72 ("uiomove: mode")); 73 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 74 ("uiomove proc")); 75 76 if (curproc) { 77 save = curproc->p_flag & P_DEADLKTREAT; 78 curproc->p_flag |= P_DEADLKTREAT; 79 } 80 81 while (n > 0 && uio->uio_resid) { 82 iov = uio->uio_iov; 83 cnt = iov->iov_len; 84 if (cnt == 0) { 85 uio->uio_iov++; 86 uio->uio_iovcnt--; 87 continue; 88 } 89 if (cnt > n) 90 cnt = n; 91 92 switch (uio->uio_segflg) { 93 94 case UIO_USERSPACE: 95 case UIO_USERISPACE: 96 if (ticks - baseticks >= hogticks) { 97 uio_yield(); 98 baseticks = ticks; 99 } 100 if (uio->uio_rw == UIO_READ) 101 error = copyout(cp, iov->iov_base, cnt); 102 else 103 error = copyin(iov->iov_base, cp, cnt); 104 if (error) 105 break; 106 break; 107 108 case UIO_SYSSPACE: 109 if (uio->uio_rw == UIO_READ) 110 bcopy((caddr_t)cp, iov->iov_base, cnt); 111 else 112 bcopy(iov->iov_base, (caddr_t)cp, cnt); 113 break; 114 case UIO_NOCOPY: 115 break; 116 } 117 iov->iov_base += cnt; 118 iov->iov_len -= cnt; 119 uio->uio_resid -= cnt; 120 uio->uio_offset += cnt; 121 cp += cnt; 122 n -= cnt; 123 } 124 if (curproc) 125 curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save; 126 return (error); 127 } 128 /* 129 * Wrapper for uiomove() that validates the arguments against a known-good 130 * kernel buffer. Currently, uiomove accepts a signed (n) argument, which 131 * is almost definitely a bad thing, so we catch that here as well. We 132 * return a runtime failure, but it might be desirable to generate a runtime 133 * assertion failure instead. 134 */ 135 int 136 uiomove_frombuf(void *buf, int buflen, struct uio *uio) 137 { 138 unsigned int offset, n; 139 140 if (uio->uio_offset < 0 || uio->uio_resid < 0 || 141 (offset = uio->uio_offset) != uio->uio_offset) 142 return (EINVAL); 143 if (buflen <= 0 || offset >= buflen) 144 return (0); 145 if ((n = buflen - offset) > INT_MAX) 146 return (EINVAL); 147 return (uiomove((char *)buf + offset, n, uio)); 148 } 149 150 151 int 152 uiomoveco(cp, n, uio, obj) 153 caddr_t cp; 154 int n; 155 struct uio *uio; 156 struct vm_object *obj; 157 { 158 struct iovec *iov; 159 u_int cnt; 160 int error; 161 int baseticks = ticks; 162 163 KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 164 ("uiomoveco: mode")); 165 KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 166 ("uiomoveco proc")); 167 168 while (n > 0 && uio->uio_resid) { 169 iov = uio->uio_iov; 170 cnt = iov->iov_len; 171 if (cnt == 0) { 172 uio->uio_iov++; 173 uio->uio_iovcnt--; 174 continue; 175 } 176 if (cnt > n) 177 cnt = n; 178 179 switch (uio->uio_segflg) { 180 181 case UIO_USERSPACE: 182 case UIO_USERISPACE: 183 if (ticks - baseticks >= hogticks) { 184 uio_yield(); 185 baseticks = ticks; 186 } 187 if (uio->uio_rw == UIO_READ) { 188 #ifdef ENABLE_VFS_IOOPT 189 if (vfs_ioopt && ((cnt & PAGE_MASK) == 0) && 190 ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) && 191 ((uio->uio_offset & PAGE_MASK) == 0) && 192 ((((intptr_t) cp) & PAGE_MASK) == 0)) { 193 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, 194 uio->uio_offset, cnt, 195 (vm_offset_t) iov->iov_base, NULL); 196 } else 197 #endif 198 { 199 error = copyout(cp, iov->iov_base, cnt); 200 } 201 } else { 202 error = copyin(iov->iov_base, cp, cnt); 203 } 204 if (error) 205 return (error); 206 break; 207 208 case UIO_SYSSPACE: 209 if (uio->uio_rw == UIO_READ) 210 bcopy((caddr_t)cp, iov->iov_base, cnt); 211 else 212 bcopy(iov->iov_base, (caddr_t)cp, cnt); 213 break; 214 case UIO_NOCOPY: 215 break; 216 } 217 iov->iov_base += cnt; 218 iov->iov_len -= cnt; 219 uio->uio_resid -= cnt; 220 uio->uio_offset += cnt; 221 cp += cnt; 222 n -= cnt; 223 } 224 return (0); 225 } 226 227 #ifdef ENABLE_VFS_IOOPT 228 229 int 230 uioread(n, uio, obj, nread) 231 int n; 232 struct uio *uio; 233 struct vm_object *obj; 234 int *nread; 235 { 236 int npagesmoved; 237 struct iovec *iov; 238 u_int cnt, tcnt; 239 int error; 240 int baseticks = ticks; 241 242 *nread = 0; 243 if (vfs_ioopt < 2) 244 return 0; 245 246 error = 0; 247 248 while (n > 0 && uio->uio_resid) { 249 iov = uio->uio_iov; 250 cnt = iov->iov_len; 251 if (cnt == 0) { 252 uio->uio_iov++; 253 uio->uio_iovcnt--; 254 continue; 255 } 256 if (cnt > n) 257 cnt = n; 258 259 if ((uio->uio_segflg == UIO_USERSPACE) && 260 ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) && 261 ((uio->uio_offset & PAGE_MASK) == 0) ) { 262 263 if (cnt < PAGE_SIZE) 264 break; 265 266 cnt &= ~PAGE_MASK; 267 268 if (ticks - baseticks >= hogticks) { 269 uio_yield(); 270 baseticks = ticks; 271 } 272 error = vm_uiomove(&curproc->p_vmspace->vm_map, obj, 273 uio->uio_offset, cnt, 274 (vm_offset_t) iov->iov_base, &npagesmoved); 275 276 if (npagesmoved == 0) 277 break; 278 279 tcnt = npagesmoved * PAGE_SIZE; 280 cnt = tcnt; 281 282 if (error) 283 break; 284 285 iov->iov_base += cnt; 286 iov->iov_len -= cnt; 287 uio->uio_resid -= cnt; 288 uio->uio_offset += cnt; 289 *nread += cnt; 290 n -= cnt; 291 } else { 292 break; 293 } 294 } 295 return error; 296 } 297 298 #endif 299 300 /* 301 * Give next character to user as result of read. 302 */ 303 int 304 ureadc(c, uio) 305 int c; 306 struct uio *uio; 307 { 308 struct iovec *iov; 309 310 again: 311 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 312 panic("ureadc"); 313 iov = uio->uio_iov; 314 if (iov->iov_len == 0) { 315 uio->uio_iovcnt--; 316 uio->uio_iov++; 317 goto again; 318 } 319 switch (uio->uio_segflg) { 320 321 case UIO_USERSPACE: 322 if (subyte(iov->iov_base, c) < 0) 323 return (EFAULT); 324 break; 325 326 case UIO_SYSSPACE: 327 *iov->iov_base = c; 328 break; 329 330 case UIO_USERISPACE: 331 if (suibyte(iov->iov_base, c) < 0) 332 return (EFAULT); 333 break; 334 case UIO_NOCOPY: 335 break; 336 } 337 iov->iov_base++; 338 iov->iov_len--; 339 uio->uio_resid--; 340 uio->uio_offset++; 341 return (0); 342 } 343 344 #ifdef vax /* unused except by ct.c, other oddities XXX */ 345 /* 346 * Get next character written in by user from uio. 347 */ 348 int 349 uwritec(uio) 350 struct uio *uio; 351 { 352 struct iovec *iov; 353 int c; 354 355 if (uio->uio_resid <= 0) 356 return (-1); 357 again: 358 if (uio->uio_iovcnt <= 0) 359 panic("uwritec"); 360 iov = uio->uio_iov; 361 if (iov->iov_len == 0) { 362 uio->uio_iov++; 363 if (--uio->uio_iovcnt == 0) 364 return (-1); 365 goto again; 366 } 367 switch (uio->uio_segflg) { 368 369 case UIO_USERSPACE: 370 c = fubyte(iov->iov_base); 371 break; 372 373 case UIO_SYSSPACE: 374 c = *(u_char *) iov->iov_base; 375 break; 376 377 case UIO_USERISPACE: 378 c = fuibyte(iov->iov_base); 379 break; 380 } 381 if (c < 0) 382 return (-1); 383 iov->iov_base++; 384 iov->iov_len--; 385 uio->uio_resid--; 386 uio->uio_offset++; 387 return (c); 388 } 389 #endif /* vax */ 390 391 /* 392 * General routine to allocate a hash table. 393 */ 394 void * 395 hashinit(elements, type, hashmask) 396 int elements; 397 struct malloc_type *type; 398 u_long *hashmask; 399 { 400 long hashsize; 401 LIST_HEAD(generic, generic) *hashtbl; 402 int i; 403 404 if (elements <= 0) 405 panic("hashinit: bad elements"); 406 for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 407 continue; 408 hashsize >>= 1; 409 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 410 for (i = 0; i < hashsize; i++) 411 LIST_INIT(&hashtbl[i]); 412 *hashmask = hashsize - 1; 413 return (hashtbl); 414 } 415 416 static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039, 417 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653, 418 7159, 7673, 8191, 12281, 16381, 24571, 32749 }; 419 #define NPRIMES (sizeof(primes) / sizeof(primes[0])) 420 421 /* 422 * General routine to allocate a prime number sized hash table. 423 */ 424 void * 425 phashinit(elements, type, nentries) 426 int elements; 427 struct malloc_type *type; 428 u_long *nentries; 429 { 430 long hashsize; 431 LIST_HEAD(generic, generic) *hashtbl; 432 int i; 433 434 if (elements <= 0) 435 panic("phashinit: bad elements"); 436 for (i = 1, hashsize = primes[1]; hashsize <= elements;) { 437 i++; 438 if (i == NPRIMES) 439 break; 440 hashsize = primes[i]; 441 } 442 hashsize = primes[i - 1]; 443 hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 444 for (i = 0; i < hashsize; i++) 445 LIST_INIT(&hashtbl[i]); 446 *nentries = hashsize; 447 return (hashtbl); 448 } 449