diff options
author | pjd <pjd@FreeBSD.org> | 2007-04-26 12:58:17 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2007-04-26 12:58:17 +0000 |
commit | f3cd86d5486530fd7dae66b904fd1f4cbbc5773f (patch) | |
tree | a04e4bf64ecbb27bb9a3efa83fad3fd273ea2d9d | |
parent | c594b142825770b52798d97d81cac5876301266e (diff) | |
download | FreeBSD-src-f3cd86d5486530fd7dae66b904fd1f4cbbc5773f.zip FreeBSD-src-f3cd86d5486530fd7dae66b904fd1f4cbbc5773f.tar.gz |
- Always try to write one whole page at a time.
- vm_page_undirty() is enough (instead of vm_page_set_validclean()), but it has
to be called before we write the data in case someone makes page dirty after
our write, but before our vm_page_undirty() call.
- Always dmu_write, not matter if uiomove() succeeded, because it could
partially be ok and we would lose some changes.
All good ideas from: ups
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c | 16 | ||||
-rw-r--r-- | sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c | 16 |
2 files changed, 18 insertions, 14 deletions
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 d434cfc..77e6545 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 @@ -298,29 +298,31 @@ mappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx) VM_OBJECT_LOCK(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { uint64_t bytes = MIN(PAGESIZE - off, len); - uint64_t woff = uio->uio_loffset; again: if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && vm_page_is_valid(m, (vm_offset_t)off, bytes)) { + uint64_t woff, dmubytes; caddr_t va; if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb")) goto again; + woff = uio->uio_loffset; + dmubytes = MIN(PAGESIZE, + obj->un_pager.vnp.vnp_size - (woff - off)); vm_page_busy(m); + vm_page_lock_queues(); + vm_page_undirty(m); + vm_page_unlock_queues(); VM_OBJECT_UNLOCK(obj); sched_pin(); sf = sf_buf_alloc(m, SFB_CPUPRIVATE); va = (caddr_t)sf_buf_kva(sf); - error = uiomove(va+off, bytes, UIO_WRITE, uio); - if (error == 0) - dmu_write(os, zp->z_id, woff, bytes, va+off, tx); + error = uiomove(va + off, bytes, UIO_WRITE, uio); + dmu_write(os, zp->z_id, woff - off, dmubytes, va, tx); sf_buf_free(sf); sched_unpin(); VM_OBJECT_LOCK(obj); - vm_page_lock_queues(); - vm_page_set_validclean(m, off, bytes); - vm_page_unlock_queues(); vm_page_wakeup(m); } else { VM_OBJECT_UNLOCK(obj); diff --git a/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index d434cfc..77e6545 100644 --- a/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -298,29 +298,31 @@ mappedwrite(vnode_t *vp, int nbytes, uio_t *uio, dmu_tx_t *tx) VM_OBJECT_LOCK(obj); for (start &= PAGEMASK; len > 0; start += PAGESIZE) { uint64_t bytes = MIN(PAGESIZE - off, len); - uint64_t woff = uio->uio_loffset; again: if ((m = vm_page_lookup(obj, OFF_TO_IDX(start))) != NULL && vm_page_is_valid(m, (vm_offset_t)off, bytes)) { + uint64_t woff, dmubytes; caddr_t va; if (vm_page_sleep_if_busy(m, FALSE, "zfsmwb")) goto again; + woff = uio->uio_loffset; + dmubytes = MIN(PAGESIZE, + obj->un_pager.vnp.vnp_size - (woff - off)); vm_page_busy(m); + vm_page_lock_queues(); + vm_page_undirty(m); + vm_page_unlock_queues(); VM_OBJECT_UNLOCK(obj); sched_pin(); sf = sf_buf_alloc(m, SFB_CPUPRIVATE); va = (caddr_t)sf_buf_kva(sf); - error = uiomove(va+off, bytes, UIO_WRITE, uio); - if (error == 0) - dmu_write(os, zp->z_id, woff, bytes, va+off, tx); + error = uiomove(va + off, bytes, UIO_WRITE, uio); + dmu_write(os, zp->z_id, woff - off, dmubytes, va, tx); sf_buf_free(sf); sched_unpin(); VM_OBJECT_LOCK(obj); - vm_page_lock_queues(); - vm_page_set_validclean(m, off, bytes); - vm_page_unlock_queues(); vm_page_wakeup(m); } else { VM_OBJECT_UNLOCK(obj); |