diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 180ac4f..e1cf4ae 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -323,8 +323,17 @@ page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes) for (;;) { if ((pp = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && vm_page_is_valid(pp, (vm_offset_t)off, nbytes)) { - if (vm_page_sleep_if_busy(pp, FALSE, "zfsmwb")) + if ((pp->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking and + * sleeping so that the page daemon is less + * likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(pp, PG_REFERENCED); + vm_page_sleep(pp, "zfsmwb"); continue; + } vm_page_busy(pp); vm_page_lock_queues(); vm_page_undirty(pp); @@ -380,7 +389,7 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid, { vm_object_t obj; struct sf_buf *sf; - int64_t off; + int off; ASSERT(vp->v_mount != NULL); obj = vp->v_object; @@ -390,7 +399,7 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid, VM_OBJECT_LOCK(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { vm_page_t pp; - uint64_t nbytes = MIN(PAGESIZE - off, len); + int nbytes = MIN(PAGESIZE - off, len); if ((pp = page_lookup(vp, start, off, nbytes)) != NULL) { caddr_t va; @@ -433,9 +442,10 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio) vm_object_t obj; vm_page_t m; struct sf_buf *sf; - int64_t start, off; + int64_t start; caddr_t va; int len = nbytes; + int off; int error = 0; uint64_t dirbytes; @@ -448,13 +458,23 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio) dirbytes = 0; VM_OBJECT_LOCK(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { - uint64_t bytes = MIN(PAGESIZE - off, len); + int bytes = MIN(PAGESIZE - off, len); again: if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && - vm_page_is_valid(m, (vm_offset_t)off, bytes)) { - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + vm_page_is_valid(m, off, bytes)) { + if ((m->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking and + * sleeping so that the page daemon is less + * likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(m, PG_REFERENCED); + vm_page_sleep(m, "zfsmrb"); goto again; + } + vm_page_busy(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { @@ -462,14 +482,8 @@ again: dirbytes); dirbytes = 0; } - if (error == 0) { - sched_pin(); - sf = sf_buf_alloc(m, SFB_CPUPRIVATE); - va = (caddr_t)sf_buf_kva(sf); - error = uiomove(va + off, bytes, UIO_READ, uio); - sf_buf_free(sf); - sched_unpin(); - } + if (error == 0) + uiomove_fromphys(&m, off, bytes, uio); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { @@ -480,8 +494,17 @@ again: * but it pessimize performance of sendfile/UFS, that's * why I handle this special case in ZFS code. */ - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + if ((m->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking and + * sleeping so that the page daemon is less + * likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(m, PG_REFERENCED); + vm_page_sleep(m, "zfsmrb"); goto again; + } vm_page_busy(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { @@ -500,6 +523,8 @@ again: sched_unpin(); } VM_OBJECT_LOCK(obj); + if (error == 0) + vm_page_set_valid(m, off, bytes); vm_page_wakeup(m); if (error == 0) uio->uio_resid -= bytes; @@ -918,7 +943,8 @@ again: #if 0 if (tx_bytes && vn_has_cached_data(vp)) #else - if (tx_bytes && vp->v_object != NULL) + if (tx_bytes && vp->v_object != NULL && (vp->v_object->resident_page_count > 0 + || vp->v_object->cache != NULL)) #endif { update_pages(vp, woff, tx_bytes, zfsvfs->z_os,