Module Name: src
Committed By: ad
Date: Sat Jan 18 15:21:32 UTC 2020
Modified Files:
src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_vnops.c
Log Message:
Track page dirtyness for ZFS (yamt-pagecache). I had forgotten that it had
its own cache. Thanks to hannken@ for the repro.
To generate a diff of this commit:
cvs rdiff -u -r1.55 -r1.56 \
src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c
diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.55 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.56
--- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.55 Wed Jan 15 17:55:43 2020
+++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Sat Jan 18 15:21:32 2020
@@ -779,7 +779,7 @@ update_pages(vnode_t *vp, int64_t start,
struct uvm_object *uobj = &vp->v_uobj;
kmutex_t *mtx = uobj->vmobjlock;
caddr_t va;
- int off;
+ int off, status;
ASSERT(vp->v_mount != NULL);
@@ -796,6 +796,26 @@ update_pages(vnode_t *vp, int64_t start,
found = uvn_findpages(uobj, start, &npages, &pp, NULL,
UFP_NOALLOC);
if (found) {
+ /*
+ * We're about to zap the page's contents and don't
+ * care about any existing modifications. We must
+ * keep track of any new modifications past this
+ * point. Clear the modified bit in the pmap, and
+ * if the page is marked dirty revert to tracking
+ * the modified bit.
+ */
+ switch (uvm_pagegetdirty(pp)) {
+ case UVM_PAGE_STATUS_DIRTY:
+ /* Does pmap_clear_modify(). */
+ uvm_pagemarkdirty(pp, UVM_PAGE_STATUS_UNKNOWN);
+ break;
+ case UVM_PAGE_STATUS_UNKNOWN:
+ pmap_clear_modify(pp);
+ break;
+ case UVM_PAGE_STATUS_CLEAN:
+ /* Nothing to do. */
+ break;
+ }
mutex_exit(mtx);
va = zfs_map_page(pp, S_WRITE);
@@ -5990,10 +6010,13 @@ zfs_netbsd_getpages(void *v)
mutex_enter(mtx);
pg->flags &= ~(PG_FAKE);
- pmap_clear_modify(pg);
}
if (memwrite) {
+ if (uvm_pagegetdirty(pg) == UVM_PAGE_STATUS_CLEAN) {
+ /* For write faults, start dirtiness tracking. */
+ uvm_pagemarkdirty(pg, UVM_PAGE_STATUS_UNKNOWN);
+ }
if ((vp->v_iflag & VI_ONWORKLST) == 0) {
vn_syncer_add_to_worklist(vp, filedelay);
}