Import Alan Cox's /usr/src/sys/kern/sys_pipe.c 1.171. This rips out
authorMatthew Dillon <dillon@dragonflybsd.org>
Sun, 28 Mar 2004 08:25:54 +0000 (08:25 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sun, 28 Mar 2004 08:25:54 +0000 (08:25 +0000)
writer-side KVA mappings and replaces them with writer-side vm_page wiring
(left intact from before) plus reader-side SF_BUF copies.

Import 1.141, which is a simple patch which removes a blocking condition
when space is available in the pipe's write buffer which was causing
non-blocking I/O select-based writes to spin-wait unnecessarily.  1.171
rips out writer-side KVA mappings and replaces them

Import FreeBSD-5.x's uiomove_fromphys(), which sys_pipe.c now uses.  This
procedure could become very useful in a number of DragonFly subsystems.

This greatly improves PIPE performance for the direct-mapped case (moderate
to large reads and writes).  Additionally, recent scheduler fixes greatly
improve PIPE performance for both the direct-mapped and small-buffer cases.

NOTE: wired page limits for pipes have not yet been imported, and the heavy
use of sf_buf's may require some tuning in the many-pipes case.

    BLKSIZE BEFORE AFTER
MBytes/s MBytes/s Tests on AMD64/3200+ FN85 MB
    ------- ------ ------ (64KB L1, 1MB L2)
    256KB 1900 2200
     64KB 1800 2200
     16KB 1650 2500-3000
      8KB 1400 2300
      4KB 1300 1400-1500 (note 1)

    note 1: The 4KB case is not a direct-write case, the results are due to
    the scheduler fixes only.

Obtained-from: FreeBSD-5.x / FreeBSD's Alan Cox

sys/conf/files.i386
sys/i386/i386/uio_machdep.c [new file with mode: 0644]
sys/kern/sys_pipe.c
sys/platform/pc32/i386/uio_machdep.c [new file with mode: 0644]
sys/sys/pipe.h
sys/sys/sfbuf.h
sys/sys/uio.h

index 5334c64..470561c 100644 (file)
@@ -2,7 +2,7 @@
 # files marked standard are always included.
 #
 # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $
-# $DragonFly: src/sys/conf/Attic/files.i386,v 1.21 2004/02/24 18:09:12 joerg Exp $
+# $DragonFly: src/sys/conf/Attic/files.i386,v 1.22 2004/03/28 08:25:54 dillon Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -223,6 +223,7 @@ i386/i386/support.s         standard
 i386/i386/swtch.s              standard
 i386/i386/sys_machdep.c                standard
 i386/i386/trap.c               standard
+i386/i386/uio_machdep.c                standard
 i386/i386/userconfig.c         optional        userconfig
 i386/i386/vm86.c               standard
 i386/i386/vm_machdep.c         standard
diff --git a/sys/i386/i386/uio_machdep.c b/sys/i386/i386/uio_machdep.c
new file mode 100644 (file)
index 0000000..ebd9e45
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu>
+ * 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.
+ *
+ * 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. 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, Berkeley and its contributors.
+ * 4. 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.3 (Berkeley) 1/21/94
+ * $FreeBSD: src/sys/i386/i386/uio_machdep.c,v 1.1 2004/03/21 20:28:36 alc Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/uio_machdep.c,v 1.1 2004/03/28 08:25:52 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/sfbuf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/thread2.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+/*
+ * Implement uiomove(9) from physical memory using sf_bufs to reduce
+ * the creation and destruction of ephemeral mappings.
+ */
+int
+uiomove_fromphys(vm_page_t *ma, vm_offset_t offset, int n, struct uio *uio)
+{
+       struct sf_buf *sf;
+       struct thread *td = curthread;
+       struct iovec *iov;
+       void *cp;
+       vm_offset_t page_offset;
+       vm_page_t m;
+       size_t cnt;
+       int error = 0;
+       int save = 0;
+
+       KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
+           ("uiomove_fromphys: mode"));
+       KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
+           ("uiomove_fromphys proc"));
+
+       crit_enter();
+       save = td->td_flags & TDF_DEADLKTREAT;
+       td->td_flags |= TDF_DEADLKTREAT;
+       crit_exit();
+
+       while (n > 0 && uio->uio_resid) {
+               iov = uio->uio_iov;
+               cnt = iov->iov_len;
+               if (cnt == 0) {
+                       uio->uio_iov++;
+                       uio->uio_iovcnt--;
+                       continue;
+               }
+               if (cnt > n)
+                       cnt = n;
+               page_offset = offset & PAGE_MASK;
+               cnt = min(cnt, PAGE_SIZE - page_offset);
+               m = ma[offset >> PAGE_SHIFT];
+               vm_page_wire(m);        /* sf_buf_free() cruft from 4.x */
+               sf = sf_buf_alloc(m);
+               cp = (char *)sf_buf_kva(sf) + page_offset;
+               switch (uio->uio_segflg) {
+               case UIO_USERSPACE:
+                       /*
+                        * note: removed uioyield (it was the wrong place to
+                        * put it).
+                        */
+                       if (uio->uio_rw == UIO_READ)
+                               error = copyout(cp, iov->iov_base, cnt);
+                       else
+                               error = copyin(iov->iov_base, cp, cnt);
+                       if (error)
+                               goto out;
+                       break;
+               case UIO_SYSSPACE:
+                       if (uio->uio_rw == UIO_READ)
+                               bcopy(cp, iov->iov_base, cnt);
+                       else
+                               bcopy(iov->iov_base, cp, cnt);
+                       break;
+               case UIO_NOCOPY:
+                       break;
+               }
+               sf_buf_free((void *)sf->kva, PAGE_SIZE);
+               iov->iov_base = (char *)iov->iov_base + cnt;
+               iov->iov_len -= cnt;
+               uio->uio_resid -= cnt;
+               uio->uio_offset += cnt;
+               offset += cnt;
+               n -= cnt;
+       }
+out:
+       if (save == 0) {
+               crit_enter();
+               td->td_flags &= ~TDF_DEADLKTREAT;
+               crit_exit();
+       }
+       return (error);
+}
index be468c8..ee7b8c5 100644 (file)
@@ -17,7 +17,7 @@
  *    are met.
  *
  * $FreeBSD: src/sys/kern/sys_pipe.c,v 1.60.2.13 2002/08/05 15:05:15 des Exp $
- * $DragonFly: src/sys/kern/sys_pipe.c,v 1.14 2004/02/20 17:11:07 dillon Exp $
+ * $DragonFly: src/sys/kern/sys_pipe.c,v 1.15 2004/03/28 08:25:48 dillon Exp $
  */
 
 /*
@@ -155,17 +155,12 @@ MALLOC_DEFINE(M_PIPE, "pipe", "pipe structures");
 static int pipe_maxbig = LIMITBIGPIPES;
 static int pipe_maxcache = PIPEQ_MAX_CACHE;
 static int pipe_nbig;
-static int pipe_kva;
 static int pipe_bcache_alloc;
 static int pipe_bkmem_alloc;
-static int pipe_dcache_alloc;
-static int pipe_dkmem_alloc;
 
 SYSCTL_NODE(_kern, OID_AUTO, pipe, CTLFLAG_RW, 0, "Pipe operation");
 SYSCTL_INT(_kern_pipe, OID_AUTO, nbig,
         CTLFLAG_RD, &pipe_nbig, 0, "numer of big pipes allocated");
-SYSCTL_INT(_kern_pipe, OID_AUTO, kva,
-        CTLFLAG_RD, &pipe_kva, 0, "kva reserved by pipes");
 SYSCTL_INT(_kern_pipe, OID_AUTO, maxcache,
         CTLFLAG_RW, &pipe_maxcache, 0, "max pipes cached per-cpu");
 SYSCTL_INT(_kern_pipe, OID_AUTO, maxbig,
@@ -173,12 +168,8 @@ SYSCTL_INT(_kern_pipe, OID_AUTO, maxbig,
 #if !defined(NO_PIPE_SYSCTL_STATS)
 SYSCTL_INT(_kern_pipe, OID_AUTO, bcache_alloc,
         CTLFLAG_RW, &pipe_bcache_alloc, 0, "pipe buffer from pcpu cache");
-SYSCTL_INT(_kern_pipe, OID_AUTO, dcache_alloc,
-        CTLFLAG_RW, &pipe_dcache_alloc, 0, "pipe direct buf from pcpu cache");
 SYSCTL_INT(_kern_pipe, OID_AUTO, bkmem_alloc,
         CTLFLAG_RW, &pipe_bkmem_alloc, 0, "pipe buffer from kmem");
-SYSCTL_INT(_kern_pipe, OID_AUTO, dkmem_alloc,
-        CTLFLAG_RW, &pipe_dkmem_alloc, 0, "pipe direct buf from kmem");
 #endif
 
 static void pipeclose (struct pipe *cpipe);
@@ -302,7 +293,6 @@ pipespace(struct pipe *cpipe, int size)
                        vm_object_deallocate(object);
                        return (ENOMEM);
                }
-               pipe_kva += size;
                pipe_free_kmem(cpipe);
                cpipe->pipe_buffer.object = object;
                cpipe->pipe_buffer.buffer = buffer;
@@ -310,8 +300,6 @@ pipespace(struct pipe *cpipe, int size)
                ++pipe_bkmem_alloc;
        } else {
                ++pipe_bcache_alloc;
-               if (cpipe->pipe_map.kva)
-                       ++pipe_dcache_alloc;
        }
        cpipe->pipe_buffer.in = 0;
        cpipe->pipe_buffer.out = 0;
@@ -451,13 +439,10 @@ pipe_read(struct file *fp, struct uio *uio, struct ucred *cred,
                 */
                } else if ((size = rpipe->pipe_map.cnt) &&
                           (rpipe->pipe_state & PIPE_DIRECTW)) {
-                       caddr_t va;
                        if (size > (u_int) uio->uio_resid)
                                size = (u_int) uio->uio_resid;
-
-                       va = (caddr_t) rpipe->pipe_map.kva +
-                           rpipe->pipe_map.pos;
-                       error = uiomove(va, size, uio);
+                       error = uiomove_fromphys(rpipe->pipe_map.ms,
+                                       rpipe->pipe_map.pos, size, uio);
                        if (error)
                                break;
                        nread += size;
@@ -581,34 +566,17 @@ pipe_build_write_buffer(wpipe, uio)
                wpipe->pipe_map.ms[i] = m;
        }
 
-/*
- * set up the control block
- */
+       /*
       * set up the control block
       */
        wpipe->pipe_map.npages = i;
        wpipe->pipe_map.pos =
            ((vm_offset_t) uio->uio_iov->iov_base) & PAGE_MASK;
        wpipe->pipe_map.cnt = size;
 
-/*
- * and map the buffer
- */
-       if (wpipe->pipe_map.kva == 0) {
-               /*
-                * We need to allocate space for an extra page because the
-                * address range might (will) span pages at times.
-                */
-               wpipe->pipe_map.kva = kmem_alloc_pageable(kernel_map,
-                       wpipe->pipe_buffer.size + PAGE_SIZE);
-               pipe_kva += wpipe->pipe_buffer.size + PAGE_SIZE;
-               ++pipe_dkmem_alloc;
-       }
-       pmap_qenter(wpipe->pipe_map.kva, wpipe->pipe_map.ms,
-               wpipe->pipe_map.npages);
-
-/*
- * and update the uio data
- */
-
+       /*
+        * and update the uio data
+        */
        uio->uio_iov->iov_len -= size;
        uio->uio_iov->iov_base += size;
        if (uio->uio_iov->iov_len == 0)
@@ -627,19 +595,10 @@ pipe_destroy_write_buffer(wpipe)
 {
        int i;
 
-       if (wpipe->pipe_map.kva) {
-               pmap_qremove(wpipe->pipe_map.kva, wpipe->pipe_map.npages);
-
-               if (pipe_kva > MAXPIPEKVA) {
-                       vm_offset_t kva = wpipe->pipe_map.kva;
-                       wpipe->pipe_map.kva = 0;
-                       kmem_free(kernel_map, kva,
-                               wpipe->pipe_buffer.size + PAGE_SIZE);
-                       pipe_kva -= wpipe->pipe_buffer.size + PAGE_SIZE;
-               }
-       }
-       for (i = 0; i < wpipe->pipe_map.npages; i++)
+       for (i = 0; i < wpipe->pipe_map.npages; i++) {
                vm_page_unhold(wpipe->pipe_map.ms[i]);
+               wpipe->pipe_map.ms[i] = NULL;   /* sanity */
+       }
        wpipe->pipe_map.npages = 0;
 }
 
@@ -652,19 +611,30 @@ static void
 pipe_clone_write_buffer(wpipe)
        struct pipe *wpipe;
 {
+       struct uio uio;
+       struct iovec iov;
        int size;
        int pos;
 
        size = wpipe->pipe_map.cnt;
        pos = wpipe->pipe_map.pos;
-       bcopy((caddr_t) wpipe->pipe_map.kva + pos,
-           (caddr_t) wpipe->pipe_buffer.buffer, size);
 
        wpipe->pipe_buffer.in = size;
        wpipe->pipe_buffer.out = 0;
        wpipe->pipe_buffer.cnt = size;
        wpipe->pipe_state &= ~PIPE_DIRECTW;
 
+       iov.iov_base = wpipe->pipe_buffer.buffer;
+       iov.iov_len = size;
+       uio.uio_iov = &iov;
+       uio.uio_iovcnt = 1;
+       uio.uio_offset = 0;
+       uio.uio_resid = size;
+       uio.uio_segflg = UIO_SYSSPACE;
+       uio.uio_rw = UIO_READ;
+       uio.uio_td = curthread;
+       uiomove_fromphys(wpipe->pipe_map.ms, pos, size, &uio);
+
        pipe_destroy_write_buffer(wpipe);
 }
 
@@ -715,14 +685,21 @@ retry:
                goto retry;
        }
 
+       /*
+        * Build our direct-write buffer
+        */
        wpipe->pipe_state |= PIPE_DIRECTW;
-
        error = pipe_build_write_buffer(wpipe, uio);
        if (error) {
                wpipe->pipe_state &= ~PIPE_DIRECTW;
                goto error1;
        }
 
+       /*
+        * Wait until the receiver has snarfed the data.  Since we are likely
+        * going to sleep we optimize the case and yield synchronously,
+        * possibly avoiding the tsleep().
+        */
        error = 0;
        while (!error && (wpipe->pipe_state & PIPE_DIRECTW)) {
                if (wpipe->pipe_state & PIPE_EOF) {
@@ -828,9 +805,7 @@ pipe_write(struct file *fp, struct uio *uio, struct ucred *cred,
                 * away on us.
                 */
                if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) &&
-                   (fp->f_flag & FNONBLOCK) == 0 &&
-                       (wpipe->pipe_map.kva || (pipe_kva < LIMITPIPEKVA)) &&
-                       (uio->uio_iov->iov_len >= PIPE_MINDIRECT)) {
+                   (fp->f_flag & FNONBLOCK) == 0) {
                        error = pipe_direct_write( wpipe, uio);
                        if (error)
                                break;
@@ -868,7 +843,12 @@ pipe_write(struct file *fp, struct uio *uio, struct ucred *cred,
                if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF))
                        space = 0;
 
-               if (space > 0 && (wpipe->pipe_buffer.cnt < PIPE_SIZE)) {
+               /* 
+                * Write to fill, read size handles write hysteresis.  Also
+                * additional restrictions can cause select-based non-blocking
+                * writes to spin.
+                */
+               if (space > 0) {
                        if ((error = pipelock(wpipe,1)) == 0) {
                                int size;       /* Transfer size */
                                int segsize;    /* first segment to transfer */
@@ -953,7 +933,9 @@ pipe_write(struct file *fp, struct uio *uio, struct ucred *cred,
 
                } else {
                        /*
-                        * If the "read-side" has been blocked, wake it up now.
+                        * If the "read-side" has been blocked, wake it up now
+                        * and yield to let it drain synchronously rather
+                        * then block.
                         */
                        if (wpipe->pipe_state & PIPE_WANTR) {
                                wpipe->pipe_state &= ~PIPE_WANTR;
@@ -1155,7 +1137,6 @@ pipe_free_kmem(struct pipe *cpipe)
        if (cpipe->pipe_buffer.buffer != NULL) {
                if (cpipe->pipe_buffer.size > PIPE_SIZE)
                        --pipe_nbig;
-               pipe_kva -= cpipe->pipe_buffer.size;
                kmem_free(kernel_map,
                        (vm_offset_t)cpipe->pipe_buffer.buffer,
                        cpipe->pipe_buffer.size);
@@ -1163,16 +1144,9 @@ pipe_free_kmem(struct pipe *cpipe)
                cpipe->pipe_buffer.object = NULL;
        }
 #ifndef PIPE_NODIRECT
-       if (cpipe->pipe_map.kva != NULL) {
-               pipe_kva -= cpipe->pipe_buffer.size + PAGE_SIZE;
-               kmem_free(kernel_map,
-                       cpipe->pipe_map.kva,
-                       cpipe->pipe_buffer.size + PAGE_SIZE);
-               cpipe->pipe_map.cnt = 0;
-               cpipe->pipe_map.kva = 0;
-               cpipe->pipe_map.pos = 0;
-               cpipe->pipe_map.npages = 0;
-       }
+       cpipe->pipe_map.cnt = 0;
+       cpipe->pipe_map.pos = 0;
+       cpipe->pipe_map.npages = 0;
 #endif
 }
 
diff --git a/sys/platform/pc32/i386/uio_machdep.c b/sys/platform/pc32/i386/uio_machdep.c
new file mode 100644 (file)
index 0000000..a5fba34
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu>
+ * 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.
+ *
+ * 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. 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, Berkeley and its contributors.
+ * 4. 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.3 (Berkeley) 1/21/94
+ * $FreeBSD: src/sys/i386/i386/uio_machdep.c,v 1.1 2004/03/21 20:28:36 alc Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/Attic/uio_machdep.c,v 1.1 2004/03/28 08:25:52 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/sfbuf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/thread2.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+/*
+ * Implement uiomove(9) from physical memory using sf_bufs to reduce
+ * the creation and destruction of ephemeral mappings.
+ */
+int
+uiomove_fromphys(vm_page_t *ma, vm_offset_t offset, int n, struct uio *uio)
+{
+       struct sf_buf *sf;
+       struct thread *td = curthread;
+       struct iovec *iov;
+       void *cp;
+       vm_offset_t page_offset;
+       vm_page_t m;
+       size_t cnt;
+       int error = 0;
+       int save = 0;
+
+       KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
+           ("uiomove_fromphys: mode"));
+       KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
+           ("uiomove_fromphys proc"));
+
+       crit_enter();
+       save = td->td_flags & TDF_DEADLKTREAT;
+       td->td_flags |= TDF_DEADLKTREAT;
+       crit_exit();
+
+       while (n > 0 && uio->uio_resid) {
+               iov = uio->uio_iov;
+               cnt = iov->iov_len;
+               if (cnt == 0) {
+                       uio->uio_iov++;
+                       uio->uio_iovcnt--;
+                       continue;
+               }
+               if (cnt > n)
+                       cnt = n;
+               page_offset = offset & PAGE_MASK;
+               cnt = min(cnt, PAGE_SIZE - page_offset);
+               m = ma[offset >> PAGE_SHIFT];
+               vm_page_wire(m);        /* sf_buf_free() cruft from 4.x */
+               sf = sf_buf_alloc(m);
+               cp = (char *)sf_buf_kva(sf) + page_offset;
+               switch (uio->uio_segflg) {
+               case UIO_USERSPACE:
+                       /*
+                        * note: removed uioyield (it was the wrong place to
+                        * put it).
+                        */
+                       if (uio->uio_rw == UIO_READ)
+                               error = copyout(cp, iov->iov_base, cnt);
+                       else
+                               error = copyin(iov->iov_base, cp, cnt);
+                       if (error)
+                               goto out;
+                       break;
+               case UIO_SYSSPACE:
+                       if (uio->uio_rw == UIO_READ)
+                               bcopy(cp, iov->iov_base, cnt);
+                       else
+                               bcopy(iov->iov_base, cp, cnt);
+                       break;
+               case UIO_NOCOPY:
+                       break;
+               }
+               sf_buf_free((void *)sf->kva, PAGE_SIZE);
+               iov->iov_base = (char *)iov->iov_base + cnt;
+               iov->iov_len -= cnt;
+               uio->uio_resid -= cnt;
+               uio->uio_offset += cnt;
+               offset += cnt;
+               n -= cnt;
+       }
+out:
+       if (save == 0) {
+               crit_enter();
+               td->td_flags &= ~TDF_DEADLKTREAT;
+               crit_exit();
+       }
+       return (error);
+}
index 9a7266e..7fdcceb 100644 (file)
@@ -19,7 +19,7 @@
  *    are met.
  *
  * $FreeBSD: src/sys/sys/pipe.h,v 1.16 1999/12/29 04:24:45 peter Exp $
- * $DragonFly: src/sys/sys/pipe.h,v 1.3 2004/02/20 17:11:08 dillon Exp $
+ * $DragonFly: src/sys/sys/pipe.h,v 1.4 2004/03/28 08:25:46 dillon Exp $
  */
 
 #ifndef _SYS_PIPE_H_
@@ -71,7 +71,6 @@ struct pipebuf {
  * Information to support direct transfers between processes for pipes.
  */
 struct pipemapping {
-       vm_offset_t     kva;            /* kernel virtual address */
        vm_size_t       cnt;            /* number of chars in buffer */
        vm_size_t       pos;            /* current position of transfer */
        int             npages;         /* number of pages */
index 3821805..e3c525d 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/sfbuf.h,v 1.1 2003/12/10 23:48:07 hsu Exp $
+ * $DragonFly: src/sys/sys/sfbuf.h,v 1.2 2004/03/28 08:25:46 dillon Exp $
  */
 
 #ifndef _SFBUF_H_
@@ -37,6 +37,21 @@ struct sf_buf {
        int             refcnt;         /* usage of this mapping */
 };
 
+static __inline vm_offset_t
+sf_buf_kva(struct sf_buf *sf)
+{
+       return(sf->kva);
+}
+
+static __inline struct vm_page *
+sf_buf_page(struct sf_buf *sf)
+{
+        return(sf->m);
+}
+
+
+#if defined(_KERNEL)
+
 extern int nsfbufs;
 
 struct sf_buf  *sf_buf_alloc(struct vm_page *);
@@ -44,3 +59,5 @@ void          sf_buf_free(caddr_t addr, u_int size);
 void           sf_buf_ref(caddr_t addr, u_int size);
 
 #endif
+
+#endif
index 0ad513c..8b287af 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)uio.h       8.5 (Berkeley) 2/22/94
  * $FreeBSD: src/sys/sys/uio.h,v 1.11.2.1 2001/09/28 16:58:35 dillon Exp $
- * $DragonFly: src/sys/sys/uio.h,v 1.7 2003/10/08 20:05:39 dillon Exp $
+ * $DragonFly: src/sys/sys/uio.h,v 1.8 2004/03/28 08:25:46 dillon Exp $
  */
 
 #ifndef _SYS_UIO_H_
@@ -90,6 +90,8 @@ struct vm_object;
 void   uio_yield (void);
 int    uiomove (caddr_t, int, struct uio *);
 int    uiomove_frombuf (void *buf, int buflen, struct uio *uio);
+int     uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n,
+                           struct uio *uio);
 int    uiomoveco (caddr_t, int, struct uio *, struct vm_object *);
 int    uioread (int, struct uio *, struct vm_object *, int *);
 int    iovec_copyin(struct iovec *, struct iovec **, struct iovec *,