kernel - Use different queue iterator for emergency pager
[dragonfly.git] / sys / kern / kern_xio.c
index 374e9da..9749ed2 100644 (file)
@@ -54,7 +54,8 @@
 #include <sys/vmmeter.h>
 #include <sys/vnode.h>
 #include <sys/xio.h>
-#include <sys/sfbuf.h>
+
+#include <cpu/lwbuf.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -83,81 +84,15 @@ xio_init(xio_t xio)
     xio->xio_pages = xio->xio_internal_pages;
 }
 
-/*
- * Initialize an XIO given a userspace buffer.  0 is returned on success,
- * an error code on failure.  The actual number of bytes that could be
- * accomodated in the XIO will be stored in xio_bytes and the page offset
- * will be stored in xio_offset.
- */
-int
-xio_init_ubuf(xio_t xio, void *ubase, size_t ubytes, int flags)
-{
-    vm_offset_t addr;
-    vm_page_t m;
-    vm_page_t m0;
-    int error;
-    int i;
-    int n;
-    int vmprot;
-
-    addr = trunc_page((vm_offset_t)ubase);
-    xio->xio_flags = flags;
-    xio->xio_bytes = 0;
-    xio->xio_error = 0;
-    if (ubytes == 0) {
-       xio->xio_offset = 0;
-       xio->xio_npages = 0;
-    } else {
-       vmprot = (flags & XIOF_WRITE) ? VM_PROT_WRITE : VM_PROT_READ;
-       xio->xio_offset = (vm_offset_t)ubase & PAGE_MASK;
-       xio->xio_pages = xio->xio_internal_pages;
-       if ((n = PAGE_SIZE - xio->xio_offset) > ubytes)
-           n = ubytes;
-       m0 = NULL;
-       for (i = 0; n && i < XIO_INTERNAL_PAGES; ++i) {
-           m = vm_fault_page_quick(addr, vmprot, &error);
-           if (m == NULL)
-               break;
-           xio->xio_pages[i] = m;
-           ubytes -= n;
-           xio->xio_bytes += n;
-           if ((n = ubytes) > PAGE_SIZE)
-               n = PAGE_SIZE;
-           addr += PAGE_SIZE;
-
-           /*
-            * Check linearity, used by syslink to memory map DMA buffers.
-            */
-           if (flags & XIOF_VMLINEAR) {
-               if (i == 0) {
-                   m0 = m;
-               } else 
-               if (m->object != m0->object || m->pindex != m0->pindex + i) {
-                   error = EINVAL;
-                   break;
-               }
-           }
-       }
-       xio->xio_npages = i;
-
-       /*
-        * If a failure occured clean out what we loaded and return EFAULT.
-        * Return 0 on success.  Do not dirty the pages.
-        */
-       if (i < XIO_INTERNAL_PAGES && n) {
-           xio->xio_flags &= ~XIOF_WRITE;
-           xio_release(xio);
-           xio->xio_error = EFAULT;
-       }
-    }
-    return(xio->xio_error);
-}
-
 /*
  * Initialize an XIO given a kernelspace buffer.  0 is returned on success,
  * an error code on failure.  The actual number of bytes that could be
  * accomodated in the XIO will be stored in xio_bytes and the page offset
  * will be stored in xio_offset.
+ *
+ * WARNING! We cannot map user memory directly into an xio unless we also
+ *         make the mapping use managed pages, otherwise modifications to
+ *         the memory will race against pageouts and flushes.
  */
 int
 xio_init_kbuf(xio_t xio, void *kbase, size_t kbytes)
@@ -179,10 +114,8 @@ xio_init_kbuf(xio_t xio, void *kbase, size_t kbytes)
     for (i = 0; n && i < XIO_INTERNAL_PAGES; ++i) {
        if ((paddr = pmap_kextract(addr)) == 0)
            break;
-       crit_enter();
        m = PHYS_TO_VM_PAGE(paddr);
        vm_page_hold(m);
-       crit_exit();
        xio->xio_pages[i] = m;
        kbytes -= n;
        xio->xio_bytes += n;
@@ -220,12 +153,10 @@ xio_init_pages(xio_t xio, struct vm_page **mbase, int npages, int xflags)
     xio->xio_pages = xio->xio_internal_pages;
     xio->xio_npages = npages;
     xio->xio_error = 0;
-    crit_enter();
     for (i = 0; i < npages; ++i) {
        vm_page_hold(mbase[i]);
        xio->xio_pages[i] = mbase[i];
     }
-    crit_exit();
     return(0);
 }
 
@@ -239,14 +170,12 @@ xio_release(xio_t xio)
     int i;
     vm_page_t m;
 
-    crit_enter();
     for (i = 0; i < xio->xio_npages; ++i) {
        m = xio->xio_pages[i];
        if (xio->xio_flags & XIOF_WRITE)
                vm_page_dirty(m);
        vm_page_unhold(m);
     }
-    crit_exit();
     xio->xio_offset = 0;
     xio->xio_npages = 0;
     xio->xio_bytes = 0;
@@ -301,7 +230,8 @@ xio_copy_xtou(xio_t xio, int uoffset, void *uptr, int bytes)
     int error;
     int offset;
     vm_page_t m;
-    struct sf_buf *sf;
+    struct lwbuf *lwb;
+    struct lwbuf lwb_cache;
 
     if (uoffset + bytes > xio->xio_bytes)
        return(EFAULT);
@@ -316,9 +246,9 @@ xio_copy_xtou(xio_t xio, int uoffset, void *uptr, int bytes)
         ++i
     ) {
        m = xio->xio_pages[i];
-       sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
-       error = copyout((char *)sf_buf_kva(sf) + offset, uptr, n);
-       sf_buf_free(sf);
+       lwb = lwbuf_alloc(m, &lwb_cache);
+       error = copyout((char *)lwbuf_kva(lwb) + offset, uptr, n);
+       lwbuf_free(lwb);
        if (error)
            break;
        bytes -= n;
@@ -349,7 +279,8 @@ xio_copy_xtok(xio_t xio, int uoffset, void *kptr, int bytes)
     int error;
     int offset;
     vm_page_t m;
-    struct sf_buf *sf;
+    struct lwbuf *lwb;
+    struct lwbuf lwb_cache;
 
     if (bytes + uoffset > xio->xio_bytes)
        return(EFAULT);
@@ -364,9 +295,9 @@ xio_copy_xtok(xio_t xio, int uoffset, void *kptr, int bytes)
         ++i
     ) {
        m = xio->xio_pages[i];
-       sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
-       bcopy((char *)sf_buf_kva(sf) + offset, kptr, n);
-       sf_buf_free(sf);
+       lwb = lwbuf_alloc(m, &lwb_cache);
+       bcopy((char *)lwbuf_kva(lwb) + offset, kptr, n);
+       lwbuf_free(lwb);
        bytes -= n;
        kptr = (char *)kptr + n;
        if (bytes == 0)
@@ -395,7 +326,8 @@ xio_copy_utox(xio_t xio, int uoffset, const void *uptr, int bytes)
     int error;
     int offset;
     vm_page_t m;
-    struct sf_buf *sf;
+    struct lwbuf *lwb;
+    struct lwbuf lwb_cache;
 
     if (uoffset + bytes > xio->xio_bytes)
        return(EFAULT);
@@ -410,9 +342,9 @@ xio_copy_utox(xio_t xio, int uoffset, const void *uptr, int bytes)
         ++i
     ) {
        m = xio->xio_pages[i];
-       sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
-       error = copyin(uptr, (char *)sf_buf_kva(sf) + offset, n);
-       sf_buf_free(sf);
+       lwb = lwbuf_alloc(m, &lwb_cache);
+       error = copyin(uptr, (char *)lwbuf_kva(lwb) + offset, n);
+       lwbuf_free(lwb);
        if (error)
            break;
        bytes -= n;
@@ -443,7 +375,8 @@ xio_copy_ktox(xio_t xio, int uoffset, const void *kptr, int bytes)
     int error;
     int offset;
     vm_page_t m;
-    struct sf_buf *sf;
+    struct lwbuf *lwb;
+    struct lwbuf lwb_cache;
 
     if (uoffset + bytes > xio->xio_bytes)
        return(EFAULT);
@@ -458,9 +391,9 @@ xio_copy_ktox(xio_t xio, int uoffset, const void *kptr, int bytes)
         ++i
     ) {
        m = xio->xio_pages[i];
-       sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
-       bcopy(kptr, (char *)sf_buf_kva(sf) + offset, n);
-       sf_buf_free(sf);
+       lwb = lwbuf_alloc(m, &lwb_cache);
+       bcopy(kptr, (char *)lwbuf_kva(lwb) + offset, n);
+       lwbuf_free(lwb);
        bytes -= n;
        kptr = (const char *)kptr + n;
        if (bytes == 0)