summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2007-04-26 12:58:17 +0000
committerpjd <pjd@FreeBSD.org>2007-04-26 12:58:17 +0000
commitf3cd86d5486530fd7dae66b904fd1f4cbbc5773f (patch)
treea04e4bf64ecbb27bb9a3efa83fad3fd273ea2d9d
parentc594b142825770b52798d97d81cac5876301266e (diff)
downloadFreeBSD-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.c16
-rw-r--r--sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c16
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);
OpenPOWER on IntegriCloud