Module Name: src Committed By: pooka Date: Wed Nov 4 16:54:00 UTC 2009
Modified Files: src/sys/conf: files src/sys/kern: kern_subr.c Added Files: src/sys/kern: subr_copy.c Log Message: Split uiomove() and high-level copy routines out of the crowded kern_subr and into their own cozy home in subr_copy. To generate a diff of this commit: cvs rdiff -u -r1.961 -r1.962 src/sys/conf/files cvs rdiff -u -r1.201 -r1.202 src/sys/kern/kern_subr.c cvs rdiff -u -r0 -r1.1 src/sys/kern/subr_copy.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/conf/files diff -u src/sys/conf/files:1.961 src/sys/conf/files:1.962 --- src/sys/conf/files:1.961 Wed Nov 4 13:29:45 2009 +++ src/sys/conf/files Wed Nov 4 16:54:00 2009 @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.961 2009/11/04 13:29:45 pooka Exp $ +# $NetBSD: files,v 1.962 2009/11/04 16:54:00 pooka Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 version 20090313 @@ -1476,6 +1476,7 @@ file kern/subr_blist.c vmswap file kern/subr_bufq.c file kern/subr_callback.c +file kern/subr_copy.c file kern/subr_debug.c debug file kern/subr_devsw.c file kern/subr_disk.c Index: src/sys/kern/kern_subr.c diff -u src/sys/kern/kern_subr.c:1.201 src/sys/kern/kern_subr.c:1.202 --- src/sys/kern/kern_subr.c:1.201 Fri Oct 2 15:48:41 2009 +++ src/sys/kern/kern_subr.c Wed Nov 4 16:54:00 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_subr.c,v 1.201 2009/10/02 15:48:41 pooka Exp $ */ +/* $NetBSD: kern_subr.c,v 1.202 2009/11/04 16:54:00 pooka Exp $ */ /*- * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc. @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.201 2009/10/02 15:48:41 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.202 2009/11/04 16:54:00 pooka Exp $"); #include "opt_ddb.h" #include "opt_md.h" @@ -137,244 +137,6 @@ dev_t dumpcdev; /* for savecore */ -void -uio_setup_sysspace(struct uio *uio) -{ - - uio->uio_vmspace = vmspace_kernel(); -} - -int -uiomove(void *buf, size_t n, struct uio *uio) -{ - struct vmspace *vm = uio->uio_vmspace; - struct iovec *iov; - size_t cnt; - int error = 0; - char *cp = buf; - - ASSERT_SLEEPABLE(); - -#ifdef DIAGNOSTIC - if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) - panic("uiomove: mode"); -#endif - while (n > 0 && uio->uio_resid) { - iov = uio->uio_iov; - cnt = iov->iov_len; - if (cnt == 0) { - KASSERT(uio->uio_iovcnt > 0); - uio->uio_iov++; - uio->uio_iovcnt--; - continue; - } - if (cnt > n) - cnt = n; - if (!VMSPACE_IS_KERNEL_P(vm)) { - if (curcpu()->ci_schedstate.spc_flags & - SPCF_SHOULDYIELD) - preempt(); - } - - if (uio->uio_rw == UIO_READ) { - error = copyout_vmspace(vm, cp, iov->iov_base, - cnt); - } else { - error = copyin_vmspace(vm, iov->iov_base, cp, - cnt); - } - if (error) { - break; - } - iov->iov_base = (char *)iov->iov_base + cnt; - iov->iov_len -= cnt; - uio->uio_resid -= cnt; - uio->uio_offset += cnt; - cp += cnt; - KDASSERT(cnt <= n); - n -= cnt; - } - - return (error); -} - -/* - * Wrapper for uiomove() that validates the arguments against a known-good - * kernel buffer. - */ -int -uiomove_frombuf(void *buf, size_t buflen, struct uio *uio) -{ - size_t offset; - - if (uio->uio_offset < 0 || /* uio->uio_resid < 0 || */ - (offset = uio->uio_offset) != uio->uio_offset) - return (EINVAL); - if (offset >= buflen) - return (0); - return (uiomove((char *)buf + offset, buflen - offset, uio)); -} - -/* - * Give next character to user as result of read. - */ -int -ureadc(int c, struct uio *uio) -{ - struct iovec *iov; - - if (uio->uio_resid <= 0) - panic("ureadc: non-positive resid"); -again: - if (uio->uio_iovcnt <= 0) - panic("ureadc: non-positive iovcnt"); - iov = uio->uio_iov; - if (iov->iov_len <= 0) { - uio->uio_iovcnt--; - uio->uio_iov++; - goto again; - } - if (!VMSPACE_IS_KERNEL_P(uio->uio_vmspace)) { - if (subyte(iov->iov_base, c) < 0) - return (EFAULT); - } else { - *(char *)iov->iov_base = c; - } - iov->iov_base = (char *)iov->iov_base + 1; - iov->iov_len--; - uio->uio_resid--; - uio->uio_offset++; - return (0); -} - -/* - * Like copyin(), but operates on an arbitrary vmspace. - */ -int -copyin_vmspace(struct vmspace *vm, const void *uaddr, void *kaddr, size_t len) -{ - struct iovec iov; - struct uio uio; - int error; - - if (len == 0) - return (0); - - if (VMSPACE_IS_KERNEL_P(vm)) { - return kcopy(uaddr, kaddr, len); - } - if (__predict_true(vm == curproc->p_vmspace)) { - return copyin(uaddr, kaddr, len); - } - - iov.iov_base = kaddr; - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)(uintptr_t)uaddr; - uio.uio_resid = len; - uio.uio_rw = UIO_READ; - UIO_SETUP_SYSSPACE(&uio); - error = uvm_io(&vm->vm_map, &uio); - - return (error); -} - -/* - * Like copyout(), but operates on an arbitrary vmspace. - */ -int -copyout_vmspace(struct vmspace *vm, const void *kaddr, void *uaddr, size_t len) -{ - struct iovec iov; - struct uio uio; - int error; - - if (len == 0) - return (0); - - if (VMSPACE_IS_KERNEL_P(vm)) { - return kcopy(kaddr, uaddr, len); - } - if (__predict_true(vm == curproc->p_vmspace)) { - return copyout(kaddr, uaddr, len); - } - - iov.iov_base = __UNCONST(kaddr); /* XXXUNCONST cast away const */ - iov.iov_len = len; - uio.uio_iov = &iov; - uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)(uintptr_t)uaddr; - uio.uio_resid = len; - uio.uio_rw = UIO_WRITE; - UIO_SETUP_SYSSPACE(&uio); - error = uvm_io(&vm->vm_map, &uio); - - return (error); -} - -/* - * Like copyin(), but operates on an arbitrary process. - */ -int -copyin_proc(struct proc *p, const void *uaddr, void *kaddr, size_t len) -{ - struct vmspace *vm; - int error; - - error = proc_vmspace_getref(p, &vm); - if (error) { - return error; - } - error = copyin_vmspace(vm, uaddr, kaddr, len); - uvmspace_free(vm); - - return error; -} - -/* - * Like copyout(), but operates on an arbitrary process. - */ -int -copyout_proc(struct proc *p, const void *kaddr, void *uaddr, size_t len) -{ - struct vmspace *vm; - int error; - - error = proc_vmspace_getref(p, &vm); - if (error) { - return error; - } - error = copyout_vmspace(vm, kaddr, uaddr, len); - uvmspace_free(vm); - - return error; -} - -/* - * Like copyin(), except it operates on kernel addresses when the FKIOCTL - * flag is passed in `ioctlflags' from the ioctl call. - */ -int -ioctl_copyin(int ioctlflags, const void *src, void *dst, size_t len) -{ - if (ioctlflags & FKIOCTL) - return kcopy(src, dst, len); - return copyin(src, dst, len); -} - -/* - * Like copyout(), except it operates on kernel addresses when the FKIOCTL - * flag is passed in `ioctlflags' from the ioctl call. - */ -int -ioctl_copyout(int ioctlflags, const void *src, void *dst, size_t len) -{ - if (ioctlflags & FKIOCTL) - return kcopy(src, dst, len); - return copyout(src, dst, len); -} - static void * hook_establish(hook_list_t *list, void (*fn)(void *), void *arg) { Added files: Index: src/sys/kern/subr_copy.c diff -u /dev/null src/sys/kern/subr_copy.c:1.1 --- /dev/null Wed Nov 4 16:54:00 2009 +++ src/sys/kern/subr_copy.c Wed Nov 4 16:54:00 2009 @@ -0,0 +1,327 @@ +/* $NetBSD: subr_copy.c,v 1.1 2009/11/04 16:54:00 pooka Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kern_subr.c 8.4 (Berkeley) 2/14/95 + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: subr_copy.c,v 1.1 2009/11/04 16:54:00 pooka Exp $"); + +#include <sys/param.h> +#include <sys/fcntl.h> +#include <sys/proc.h> +#include <sys/systm.h> + +#include <uvm/uvm_extern.h> + +void +uio_setup_sysspace(struct uio *uio) +{ + + uio->uio_vmspace = vmspace_kernel(); +} + +int +uiomove(void *buf, size_t n, struct uio *uio) +{ + struct vmspace *vm = uio->uio_vmspace; + struct iovec *iov; + size_t cnt; + int error = 0; + char *cp = buf; + + ASSERT_SLEEPABLE(); + +#ifdef DIAGNOSTIC + if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) + panic("uiomove: mode"); +#endif + while (n > 0 && uio->uio_resid) { + iov = uio->uio_iov; + cnt = iov->iov_len; + if (cnt == 0) { + KASSERT(uio->uio_iovcnt > 0); + uio->uio_iov++; + uio->uio_iovcnt--; + continue; + } + if (cnt > n) + cnt = n; + if (!VMSPACE_IS_KERNEL_P(vm)) { + if (curcpu()->ci_schedstate.spc_flags & + SPCF_SHOULDYIELD) + preempt(); + } + + if (uio->uio_rw == UIO_READ) { + error = copyout_vmspace(vm, cp, iov->iov_base, + cnt); + } else { + error = copyin_vmspace(vm, iov->iov_base, cp, + cnt); + } + if (error) { + break; + } + iov->iov_base = (char *)iov->iov_base + cnt; + iov->iov_len -= cnt; + uio->uio_resid -= cnt; + uio->uio_offset += cnt; + cp += cnt; + KDASSERT(cnt <= n); + n -= cnt; + } + + return (error); +} + +/* + * Wrapper for uiomove() that validates the arguments against a known-good + * kernel buffer. + */ +int +uiomove_frombuf(void *buf, size_t buflen, struct uio *uio) +{ + size_t offset; + + if (uio->uio_offset < 0 || /* uio->uio_resid < 0 || */ + (offset = uio->uio_offset) != uio->uio_offset) + return (EINVAL); + if (offset >= buflen) + return (0); + return (uiomove((char *)buf + offset, buflen - offset, uio)); +} + +/* + * Give next character to user as result of read. + */ +int +ureadc(int c, struct uio *uio) +{ + struct iovec *iov; + + if (uio->uio_resid <= 0) + panic("ureadc: non-positive resid"); +again: + if (uio->uio_iovcnt <= 0) + panic("ureadc: non-positive iovcnt"); + iov = uio->uio_iov; + if (iov->iov_len <= 0) { + uio->uio_iovcnt--; + uio->uio_iov++; + goto again; + } + if (!VMSPACE_IS_KERNEL_P(uio->uio_vmspace)) { + if (subyte(iov->iov_base, c) < 0) + return (EFAULT); + } else { + *(char *)iov->iov_base = c; + } + iov->iov_base = (char *)iov->iov_base + 1; + iov->iov_len--; + uio->uio_resid--; + uio->uio_offset++; + return (0); +} + +/* + * Like copyin(), but operates on an arbitrary vmspace. + */ +int +copyin_vmspace(struct vmspace *vm, const void *uaddr, void *kaddr, size_t len) +{ + struct iovec iov; + struct uio uio; + int error; + + if (len == 0) + return (0); + + if (VMSPACE_IS_KERNEL_P(vm)) { + return kcopy(uaddr, kaddr, len); + } + if (__predict_true(vm == curproc->p_vmspace)) { + return copyin(uaddr, kaddr, len); + } + + iov.iov_base = kaddr; + iov.iov_len = len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)(uintptr_t)uaddr; + uio.uio_resid = len; + uio.uio_rw = UIO_READ; + UIO_SETUP_SYSSPACE(&uio); + error = uvm_io(&vm->vm_map, &uio); + + return (error); +} + +/* + * Like copyout(), but operates on an arbitrary vmspace. + */ +int +copyout_vmspace(struct vmspace *vm, const void *kaddr, void *uaddr, size_t len) +{ + struct iovec iov; + struct uio uio; + int error; + + if (len == 0) + return (0); + + if (VMSPACE_IS_KERNEL_P(vm)) { + return kcopy(kaddr, uaddr, len); + } + if (__predict_true(vm == curproc->p_vmspace)) { + return copyout(kaddr, uaddr, len); + } + + iov.iov_base = __UNCONST(kaddr); /* XXXUNCONST cast away const */ + iov.iov_len = len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = (off_t)(uintptr_t)uaddr; + uio.uio_resid = len; + uio.uio_rw = UIO_WRITE; + UIO_SETUP_SYSSPACE(&uio); + error = uvm_io(&vm->vm_map, &uio); + + return (error); +} + +/* + * Like copyin(), but operates on an arbitrary process. + */ +int +copyin_proc(struct proc *p, const void *uaddr, void *kaddr, size_t len) +{ + struct vmspace *vm; + int error; + + error = proc_vmspace_getref(p, &vm); + if (error) { + return error; + } + error = copyin_vmspace(vm, uaddr, kaddr, len); + uvmspace_free(vm); + + return error; +} + +/* + * Like copyout(), but operates on an arbitrary process. + */ +int +copyout_proc(struct proc *p, const void *kaddr, void *uaddr, size_t len) +{ + struct vmspace *vm; + int error; + + error = proc_vmspace_getref(p, &vm); + if (error) { + return error; + } + error = copyout_vmspace(vm, kaddr, uaddr, len); + uvmspace_free(vm); + + return error; +} + +/* + * Like copyin(), except it operates on kernel addresses when the FKIOCTL + * flag is passed in `ioctlflags' from the ioctl call. + */ +int +ioctl_copyin(int ioctlflags, const void *src, void *dst, size_t len) +{ + if (ioctlflags & FKIOCTL) + return kcopy(src, dst, len); + return copyin(src, dst, len); +} + +/* + * Like copyout(), except it operates on kernel addresses when the FKIOCTL + * flag is passed in `ioctlflags' from the ioctl call. + */ +int +ioctl_copyout(int ioctlflags, const void *src, void *dst, size_t len) +{ + if (ioctlflags & FKIOCTL) + return kcopy(src, dst, len); + return copyout(src, dst, len); +}