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);
+}