Author: avg
Date: Sun Mar 31 13:56:13 2013
New Revision: 248946
URL: http://svnweb.freebsd.org/changeset/base/248946

Log:
  MFC r246293: zfs: fix, improve and re-organize page_lookup and page_unlock
  
  Please note that because of the significant VM API differences between HEAD
  and stable/8 this commit has some additional changes.

Modified:
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/cddl/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sun Mar 
31 13:54:44 2013        (r248945)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sun Mar 
31 13:56:13 2013        (r248946)
@@ -323,7 +323,7 @@ zfs_ioctl(vnode_t *vp, u_long com, intpt
 }
 
 static vm_page_t
-page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
+page_busy(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
 {
        vm_object_t obj;
        vm_page_t pp;
@@ -333,19 +333,23 @@ page_lookup(vnode_t *vp, int64_t start, 
 
        for (;;) {
                if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
-                   vm_page_is_valid(pp, (vm_offset_t)off, nbytes)) {
+                   pp->valid) {
                        if (vm_page_sleep_if_busy(pp, FALSE, "zfsmwb"))
                                continue;
-                       vm_page_busy(pp);
+               } else {
+                       pp = vm_page_alloc(obj, OFF_TO_IDX(start),
+                           VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED |
+                           VM_ALLOC_NOBUSY);
+               }
+
+               if (pp != NULL) {
+                       ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
+                       vm_object_pip_add(obj, 1);
+                       vm_page_io_start(pp);
                        vm_page_lock_queues();
-                       vm_page_undirty(pp);
+                       pmap_remove_write(pp);
+                       vm_page_clear_dirty(pp, off, nbytes);
                        vm_page_unlock_queues();
-               } else {
-                       if (__predict_false(obj->cache != NULL)) {
-                               vm_page_cache_free(obj, OFF_TO_IDX(start),
-                                   OFF_TO_IDX(start) + 1);
-                       }
-                       pp = NULL;
                }
                break;
        }
@@ -353,10 +357,46 @@ page_lookup(vnode_t *vp, int64_t start, 
 }
 
 static void
-page_unlock(vm_page_t pp)
+page_unbusy(vm_page_t pp)
 {
 
-       vm_page_wakeup(pp);
+       vm_page_io_finish(pp);
+       vm_object_pip_subtract(pp->object, 1);
+}
+
+static vm_page_t
+page_hold(vnode_t *vp, int64_t start)
+{
+       vm_object_t obj;
+       vm_page_t pp;
+
+       obj = vp->v_object;
+       VM_OBJECT_LOCK_ASSERT(obj, MA_OWNED);
+
+       for (;;) {
+               if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL &&
+                   pp->valid) {
+                       if (vm_page_sleep_if_busy(pp, FALSE, "zfsmwb"))
+                               continue;
+                       ASSERT3U(pp->valid, ==, VM_PAGE_BITS_ALL);
+                       vm_page_lock_queues();
+                       vm_page_hold(pp);
+                       vm_page_unlock_queues();
+
+               } else
+                       pp = NULL;
+               break;
+       }
+       return (pp);
+}
+
+static void
+page_unhold(vm_page_t pp)
+{
+
+       vm_page_lock_queues();
+       vm_page_unhold(pp);
+       vm_page_unlock_queues();
 }
 
 static caddr_t
@@ -387,6 +427,7 @@ update_pages(vnode_t *vp, int64_t start,
 {
        vm_object_t obj;
        struct sf_buf *sf;
+       caddr_t va;
        int off;
 
        ASSERT(vp->v_mount != NULL);
@@ -397,27 +438,44 @@ update_pages(vnode_t *vp, int64_t start,
        VM_OBJECT_LOCK(obj);
        for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
                vm_page_t pp;
-               int nbytes = MIN(PAGESIZE - off, len);
+               int nbytes = imin(PAGESIZE - off, len);
 
-               if ((pp = page_lookup(vp, start, off, nbytes)) != NULL) {
-                       caddr_t va;
+               if (segflg == UIO_NOCOPY) {
+                       pp = vm_page_lookup(obj, OFF_TO_IDX(start));
+                       KASSERT(pp != NULL,
+                           ("zfs update_pages: NULL page in putpages case"));
+                       KASSERT(off == 0,
+                           ("zfs update_pages: unaligned data in putpages 
case"));
+                       KASSERT(pp->valid == VM_PAGE_BITS_ALL,
+                           ("zfs update_pages: invalid page in putpages 
case"));
+                       KASSERT(pp->busy > 0,
+                           ("zfs update_pages: unbusy page in putpages case"));
+                       KASSERT(!pmap_page_is_write_mapped(pp),
+                           ("zfs update_pages: writable page in putpages 
case"));
+                       VM_OBJECT_UNLOCK(obj);
+
+                       va = zfs_map_page(pp, &sf);
+                       (void) dmu_write(os, oid, start, nbytes, va, tx);
+                       zfs_unmap_page(sf);
 
+                       VM_OBJECT_LOCK(obj);
+                       vm_page_undirty(pp);
+               } else if ((pp = page_busy(vp, start, off, nbytes)) != NULL) {
                        VM_OBJECT_UNLOCK(obj);
+
                        va = zfs_map_page(pp, &sf);
-                       if (segflg == UIO_NOCOPY) {
-                               (void) dmu_write(os, oid, start+off, nbytes,
-                                   va+off, tx);
-                       } else {
-                               (void) dmu_read(os, oid, start+off, nbytes,
-                                   va+off, DMU_READ_PREFETCH);
-                       }
+                       (void) dmu_read(os, oid, start+off, nbytes,
+                           va+off, DMU_READ_PREFETCH);;
                        zfs_unmap_page(sf);
+
                        VM_OBJECT_LOCK(obj);
-                       page_unlock(pp);
+                       page_unbusy(pp);
                }
                len -= nbytes;
                off = 0;
        }
+       if (segflg != UIO_NOCOPY)
+               vm_object_pip_wakeupn(obj, 0);
        VM_OBJECT_UNLOCK(obj);
 }
 
@@ -532,7 +590,7 @@ mappedread(vnode_t *vp, int nbytes, uio_
                vm_page_t pp;
                uint64_t bytes = MIN(PAGESIZE - off, len);
 
-               if (pp = page_lookup(vp, start, off, bytes)) {
+               if (pp = page_hold(vp, start)) {
                        struct sf_buf *sf;
                        caddr_t va;
                        VM_OBJECT_UNLOCK(obj);
@@ -540,7 +598,7 @@ mappedread(vnode_t *vp, int nbytes, uio_
                        error = uiomove(va + off, bytes, UIO_READ, uio);
                        zfs_unmap_page(sf);
                        VM_OBJECT_LOCK(obj);
-                       page_unlock(pp);
+                       page_unhold(pp);
                } else {
                        VM_OBJECT_UNLOCK(obj);
                        error = dmu_read_uio(os, zp->z_id, uio, bytes);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to