Module Name: src Committed By: martin Date: Tue Jul 6 04:22:35 UTC 2021
Modified Files: src/external/cddl/osnet/dist/uts/common/fs/zfs [netbsd-9]: zfs_vnops.c src/sys/rump/librump/rumpkern [netbsd-9]: vm.c src/sys/rump/librump/rumpvfs [netbsd-9]: vm_vfs.c src/sys/uvm [netbsd-9]: uvm_anon.c uvm_page.c uvm_pager.c src/tests/rump/rumpkern [netbsd-9]: t_vm.c Log Message: Pull up following revision(s) - all via patch - (requested by riastradh in ticket #1317): sys/uvm/uvm_page.c: revision 1.248 sys/uvm/uvm_anon.c: revision 1.80 sys/rump/librump/rumpvfs/vm_vfs.c: revision 1.40 sys/rump/librump/rumpvfs/vm_vfs.c: revision 1.41 sys/rump/librump/rumpkern/vm.c: revision 1.191 sys/uvm/uvm_pager.c: revision 1.130 external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c: revision 1.71 tests/rump/rumpkern/t_vm.c: revision 1.5 tests/rump/rumpkern/t_vm.c: revision 1.6 sys/rump/librump/rumpvfs/vm_vfs.c: revision 1.39 Move the handling of PG_PAGEOUT from uvm_aio_aiodone_pages() to uvm_page_unbusy() so that all callers of uvm_page_unbusy() don't need to handle this flag separately. Split out the pages part of uvm_aio_aiodone() into uvm_aio_aiodone_pages() in rump just like in the real kernel. In ZFS functions that can fail to copy data between the ARC and VM pages, use uvm_aio_aiodone_pages() rather than uvm_page_unbusy() so that we can handle these "I/O" errors. Fixes PR 55702. fix an incorrect assertion in the previous commit. Handle PG_PAGEOUT in uvm_anon_release() too. Commit the ZFS file that I forgot in this previous commit: Move the handling of PG_PAGEOUT from uvm_aio_aiodone_pages() to uvm_page_unbusy() so that all callers of uvm_page_unbusy() don't need to handle this flag separately. Split out the pages part of uvm_aio_aiodone() into uvm_aio_aiodone_pages() in rump just like in the real kernel. In ZFS functions that can fail to copy data between the ARC and VM pages, use uvm_aio_aiodone_pages() rather than uvm_page_unbusy() so that we can handle these "I/O" errors. Fixes PR 55702. update the rump copy of uvm_page_unbusy() to match the real version, in particular handle PG_PAGEOUT. fixes a few atf tests. the busypage test is buggy, expect it to fail. make rump's uvm_aio_aiodone_pages() look more like the kernel version. fixes some more rumpy assertions. for the busypage test, replace atf_tc_expect_fail() with atf_tc_skip() because atf apparently has no way to expect a test program to crash. fixes PR 55945. To generate a diff of this commit: cvs rdiff -u -r1.50.2.9 -r1.50.2.10 \ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c cvs rdiff -u -r1.173 -r1.173.14.1 src/sys/rump/librump/rumpkern/vm.c cvs rdiff -u -r1.34 -r1.34.34.1 src/sys/rump/librump/rumpvfs/vm_vfs.c cvs rdiff -u -r1.64 -r1.64.8.1 src/sys/uvm/uvm_anon.c cvs rdiff -u -r1.199 -r1.199.4.1 src/sys/uvm/uvm_page.c cvs rdiff -u -r1.111.8.1 -r1.111.8.2 src/sys/uvm/uvm_pager.c cvs rdiff -u -r1.4 -r1.4.16.1 src/tests/rump/rumpkern/t_vm.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.50.2.9 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.50.2.10 --- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.50.2.9 Wed May 13 12:41:43 2020 +++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Tue Jul 6 04:22:34 2021 @@ -6007,6 +6007,12 @@ zfs_netbsd_getpages(void *v) va, DMU_READ_PREFETCH); zfs_unmap_page(pg, va); + if (err != 0) { + uvm_aio_aiodone_pages(ap->a_m, npages, false, err); + memset(ap->a_m, 0, sizeof(ap->a_m[0]) * + npages); + goto out; + } mutex_enter(mtx); pg->flags &= ~(PG_FAKE); pmap_clear_modify(pg); @@ -6023,6 +6029,7 @@ zfs_netbsd_getpages(void *v) mutex_exit(mtx); ap->a_m[ap->a_centeridx] = pg; +out: ZFS_EXIT(zfsvfs); fstrans_done(mp); @@ -6039,14 +6046,13 @@ zfs_putapage(vnode_t *vp, page_t **pp, i voff_t len, klen; int err; - bool async = (flags & PGO_SYNCIO) == 0; bool *cleanedp; struct uvm_object *uobj = &vp->v_uobj; kmutex_t *mtx = uobj->vmobjlock; if (zp->z_sa_hdl == NULL) { err = 0; - goto out_unbusy; + goto out; } /* @@ -6120,14 +6126,8 @@ zfs_putapage(vnode_t *vp, page_t **pp, i } dmu_tx_commit(tx); -out_unbusy: - mutex_enter(mtx); - mutex_enter(&uvm_pageqlock); - uvm_page_unbusy(pp, count); - mutex_exit(&uvm_pageqlock); - mutex_exit(mtx); - out: + uvm_aio_aiodone_pages(pp, count, true, err); return (err); } Index: src/sys/rump/librump/rumpkern/vm.c diff -u src/sys/rump/librump/rumpkern/vm.c:1.173 src/sys/rump/librump/rumpkern/vm.c:1.173.14.1 --- src/sys/rump/librump/rumpkern/vm.c:1.173 Sun May 14 13:49:55 2017 +++ src/sys/rump/librump/rumpkern/vm.c Tue Jul 6 04:22:34 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: vm.c,v 1.173 2017/05/14 13:49:55 nat Exp $ */ +/* $NetBSD: vm.c,v 1.173.14.1 2021/07/06 04:22:34 martin Exp $ */ /* * Copyright (c) 2007-2011 Antti Kantee. All Rights Reserved. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.173 2017/05/14 13:49:55 nat Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vm.c,v 1.173.14.1 2021/07/06 04:22:34 martin Exp $"); #include <sys/param.h> #include <sys/atomic.h> @@ -632,23 +632,50 @@ void uvm_page_unbusy(struct vm_page **pgs, int npgs) { struct vm_page *pg; - int i; + int i, pageout_done; KASSERT(npgs > 0); - KASSERT(mutex_owned(pgs[0]->uobject->vmobjlock)); + pageout_done = 0; for (i = 0; i < npgs; i++) { pg = pgs[i]; - if (pg == NULL) + if (pg == NULL || pg == PGO_DONTCARE) { continue; + } +#if 0 + KASSERT(uvm_page_owner_locked_p(pg, true)); +#else + /* + * uvm_page_owner_locked_p() is not available in rump, + * and rump doesn't support amaps anyway. + */ + KASSERT(mutex_owned(pg->uobject->vmobjlock)); +#endif KASSERT(pg->flags & PG_BUSY); - if (pg->flags & PG_WANTED) + + if (pg->flags & PG_PAGEOUT) { + pg->flags &= ~PG_PAGEOUT; + pg->flags |= PG_RELEASED; + pageout_done++; + atomic_inc_uint(&uvmexp.pdfreed); + } + if (pg->flags & PG_WANTED) { wakeup(pg); - if (pg->flags & PG_RELEASED) + } + if (pg->flags & PG_RELEASED) { + KASSERT(pg->uobject != NULL || + (pg->uanon != NULL && pg->uanon->an_ref > 0)); + pg->flags &= ~PG_RELEASED; uvm_pagefree(pg); - else + } else { + KASSERT((pg->flags & PG_FAKE) == 0); pg->flags &= ~(PG_WANTED|PG_BUSY); + UVM_PAGE_OWN(pg, NULL); + } + } + if (pageout_done != 0) { + uvm_pageout_done(pageout_done); } } Index: src/sys/rump/librump/rumpvfs/vm_vfs.c diff -u src/sys/rump/librump/rumpvfs/vm_vfs.c:1.34 src/sys/rump/librump/rumpvfs/vm_vfs.c:1.34.34.1 --- src/sys/rump/librump/rumpvfs/vm_vfs.c:1.34 Fri Oct 18 19:56:11 2013 +++ src/sys/rump/librump/rumpvfs/vm_vfs.c Tue Jul 6 04:22:34 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: vm_vfs.c,v 1.34 2013/10/18 19:56:11 christos Exp $ */ +/* $NetBSD: vm_vfs.c,v 1.34.34.1 2021/07/06 04:22:34 martin Exp $ */ /* * Copyright (c) 2008-2011 Antti Kantee. All Rights Reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.34 2013/10/18 19:56:11 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1.34.34.1 2021/07/06 04:22:34 martin Exp $"); #include <sys/param.h> @@ -36,19 +36,47 @@ __KERNEL_RCSID(0, "$NetBSD: vm_vfs.c,v 1 #include <uvm/uvm.h> #include <uvm/uvm_readahead.h> +void +uvm_aio_aiodone_pages(struct vm_page **pgs, int npages, bool write, int error) +{ + struct uvm_object *uobj = pgs[0]->uobject; + struct vm_page *pg; + int i; + + mutex_enter(uobj->vmobjlock); + for (i = 0; i < npages; i++) { + pg = pgs[i]; + KASSERT((pg->flags & PG_PAGEOUT) == 0 || + (pg->flags & PG_FAKE) == 0); + + if (pg->flags & PG_FAKE) { + KASSERT(!write); + pg->flags &= ~PG_FAKE; + KASSERT((pg->flags & PG_CLEAN) != 0); + uvm_pageenqueue(pg); + pmap_clear_modify(pg); + } + + } + uvm_page_unbusy(pgs, npages); + mutex_exit(uobj->vmobjlock); +} + /* - * release resources held during async io. this is almost the - * same as uvm_aio_aiodone() from uvm_pager.c and only lacks the - * call to uvm_aio_aiodone_pages(): unbusies pages directly here. + * Release resources held during async io. */ void uvm_aio_aiodone(struct buf *bp) { struct uvm_object *uobj = NULL; - int i, npages = bp->b_bufsize >> PAGE_SHIFT; + int npages = bp->b_bufsize >> PAGE_SHIFT; struct vm_page **pgs; vaddr_t va; - int pageout = 0; + int i, error; + bool write; + + error = bp->b_error; + write = BUF_ISWRITE(bp); KASSERT(npages > 0); pgs = kmem_alloc(npages * sizeof(*pgs), KM_SLEEP); @@ -59,29 +87,15 @@ uvm_aio_aiodone(struct buf *bp) if (uobj == NULL) { uobj = pgs[i]->uobject; KASSERT(uobj != NULL); - mutex_enter(uobj->vmobjlock); } else { KASSERT(uobj == pgs[i]->uobject); } - - if (pgs[i]->flags & PG_PAGEOUT) { - KASSERT((pgs[i]->flags & PG_FAKE) == 0); - pageout++; - pgs[i]->flags &= ~PG_PAGEOUT; - pgs[i]->flags |= PG_RELEASED; - } } - KASSERT(mutex_owned(uobj->vmobjlock)); - - mutex_enter(&uvm_pageqlock); - uvm_page_unbusy(pgs, npages); - mutex_exit(&uvm_pageqlock); - mutex_exit(uobj->vmobjlock); - uvm_pagermapout((vaddr_t)bp->b_data, npages); - uvm_pageout_done(pageout); - if (BUF_ISWRITE(bp) && (bp->b_cflags & BC_AGE) != 0) { + uvm_aio_aiodone_pages(pgs, npages, write, error); + + if (write && (bp->b_cflags & BC_AGE) != 0) { mutex_enter(bp->b_objlock); vwakeup(bp); mutex_exit(bp->b_objlock); Index: src/sys/uvm/uvm_anon.c diff -u src/sys/uvm/uvm_anon.c:1.64 src/sys/uvm/uvm_anon.c:1.64.8.1 --- src/sys/uvm/uvm_anon.c:1.64 Sat Oct 28 00:37:13 2017 +++ src/sys/uvm/uvm_anon.c Tue Jul 6 04:22:34 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_anon.c,v 1.64 2017/10/28 00:37:13 pgoyette Exp $ */ +/* $NetBSD: uvm_anon.c,v 1.64.8.1 2021/07/06 04:22:34 martin Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_anon.c,v 1.64 2017/10/28 00:37:13 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_anon.c,v 1.64.8.1 2021/07/06 04:22:34 martin Exp $"); #include "opt_uvmhist.h" @@ -443,6 +443,11 @@ uvm_anon_release(struct vm_anon *anon) KASSERT(pg->loan_count == 0); KASSERT(anon->an_ref == 0); + if ((pg->flags & PG_PAGEOUT) != 0) { + pg->flags &= ~PG_PAGEOUT; + uvm_pageout_done(1); + } + mutex_enter(&uvm_pageqlock); uvm_pagefree(pg); mutex_exit(&uvm_pageqlock); Index: src/sys/uvm/uvm_page.c diff -u src/sys/uvm/uvm_page.c:1.199 src/sys/uvm/uvm_page.c:1.199.4.1 --- src/sys/uvm/uvm_page.c:1.199 Thu Mar 14 19:10:04 2019 +++ src/sys/uvm/uvm_page.c Tue Jul 6 04:22:34 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_page.c,v 1.199 2019/03/14 19:10:04 kre Exp $ */ +/* $NetBSD: uvm_page.c,v 1.199.4.1 2021/07/06 04:22:34 martin Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.199 2019/03/14 19:10:04 kre Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.199.4.1 2021/07/06 04:22:34 martin Exp $"); #include "opt_ddb.h" #include "opt_uvm.h" @@ -1362,9 +1362,10 @@ void uvm_page_unbusy(struct vm_page **pgs, int npgs) { struct vm_page *pg; - int i; + int i, pageout_done; UVMHIST_FUNC("uvm_page_unbusy"); UVMHIST_CALLED(ubchist); + pageout_done = 0; for (i = 0; i < npgs; i++) { pg = pgs[i]; if (pg == NULL || pg == PGO_DONTCARE) { @@ -1373,7 +1374,13 @@ uvm_page_unbusy(struct vm_page **pgs, in KASSERT(uvm_page_locked_p(pg)); KASSERT(pg->flags & PG_BUSY); - KASSERT((pg->flags & PG_PAGEOUT) == 0); + + if (pg->flags & PG_PAGEOUT) { + pg->flags &= ~PG_PAGEOUT; + pg->flags |= PG_RELEASED; + pageout_done++; + atomic_inc_uint(&uvmexp.pdfreed); + } if (pg->flags & PG_WANTED) { wakeup(pg); } @@ -1392,6 +1399,9 @@ uvm_page_unbusy(struct vm_page **pgs, in UVM_PAGE_OWN(pg, NULL); } } + if (pageout_done != 0) { + uvm_pageout_done(pageout_done); + } } #if defined(UVM_PAGE_TRKOWN) Index: src/sys/uvm/uvm_pager.c diff -u src/sys/uvm/uvm_pager.c:1.111.8.1 src/sys/uvm/uvm_pager.c:1.111.8.2 --- src/sys/uvm/uvm_pager.c:1.111.8.1 Fri Dec 27 06:58:56 2019 +++ src/sys/uvm/uvm_pager.c Tue Jul 6 04:22:34 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_pager.c,v 1.111.8.1 2019/12/27 06:58:56 martin Exp $ */ +/* $NetBSD: uvm_pager.c,v 1.111.8.2 2021/07/06 04:22:34 martin Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_pager.c,v 1.111.8.1 2019/12/27 06:58:56 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_pager.c,v 1.111.8.2 2021/07/06 04:22:34 martin Exp $"); #include "opt_uvmhist.h" #include "opt_readahead.h" @@ -428,18 +428,6 @@ uvm_aio_aiodone_pages(struct vm_page **p pmap_clear_modify(pg); } - /* - * do accounting for pagedaemon i/o and arrange to free - * the pages instead of just unbusying them. - */ - - if (pg->flags & PG_PAGEOUT) { - pg->flags &= ~PG_PAGEOUT; - pageout_done++; - uvmexp.pdfreed++; - pg->flags |= PG_RELEASED; - } - #if defined(VMSWAP) /* * for swap pages, unlock everything for this page now. Index: src/tests/rump/rumpkern/t_vm.c diff -u src/tests/rump/rumpkern/t_vm.c:1.4 src/tests/rump/rumpkern/t_vm.c:1.4.16.1 --- src/tests/rump/rumpkern/t_vm.c:1.4 Fri Jan 13 21:30:43 2017 +++ src/tests/rump/rumpkern/t_vm.c Tue Jul 6 04:22:34 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: t_vm.c,v 1.4 2017/01/13 21:30:43 christos Exp $ */ +/* $NetBSD: t_vm.c,v 1.4.16.1 2021/07/06 04:22:34 martin Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -50,6 +50,10 @@ ATF_TC_HEAD(busypage, tc) ATF_TC_BODY(busypage, tc) { +#if 0 + atf_tc_expect_fail("test bug: unbusies an uninitialized page"); +#endif + atf_tc_skip("this test is buggy and hits an assertion, but atf doesn't provide any way to expect that a test program crashes, this all we can do is skip"); rump_init(); rump_schedule();