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);
 		}

Reply via email to