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

Reply via email to