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"