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