FBSD: Lock vm object before vm_page_undirty 62/14162/4 master
authorAndrew Deason <adeason@dson.org>
Sun, 26 Apr 2020 01:56:01 +0000 (20:56 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 5 Mar 2021 16:45:53 +0000 (11:45 -0500)
We must write-lock the underlying vm object before calling
vm_page_undirty; otherwise vm_page_undirty asserts if INVARIANTS is
defined. For example:

    kernel: panic: Lock vm object not exclusively locked @ /usr/src/sys/vm/vm_page.c:4487
    kernel:
    kernel: cpuid = 0
    kernel: time = 1587858280
    kernel: KDB: stack backtrace:
    kernel: #0 0xffffffff80bf0c07 at kdb_backtrace+0x67
    kernel: #1 0xffffffff80ba7f8d at vpanic+0x19d
    kernel: #2 0xffffffff80ba7d73 at panic+0x43
    kernel: #3 0xffffffff80ba3a7e at __rw_assert+0x17e
    kernel: #4 0xffffffff828da525 at vm_page_undirty+0x15
    kernel: #5 0xffffffff828da33e at afs_vop_putpages+0x36e
    kernel: #6 0xffffffff811ef0ae at VOP_PUTPAGES_APV+0x8e
    kernel: #7 0xffffffff80ef4c2d at vnode_pager_putpages+0x7d
    kernel: #8 0xffffffff80ee77cf at vm_pageout_flush+0xff
    kernel: #9 0xffffffff80edd1b9 at vm_object_page_collect_flush+0x239
    kernel: #10 0xffffffff80edce99 at vm_object_page_clean+0x179
    kernel: #11 0xffffffff828d681c at osi_VM_StoreAllSegments+0x18c
    kernel: #12 0xffffffff828508cd at afs_StoreAllSegments+0x9d
    kernel: #13 0xffffffff8287ae0e at afs_StoreOnLastReference+0x17e
    kernel: #14 0xffffffff8287c3a5 at afs_close+0x245
    kernel: #15 0xffffffff828d7766 at afs_vop_close+0x166
    kernel: #16 0xffffffff811eb7a8 at VOP_CLOSE_APV+0x88
    kernel: #17 0xffffffff80c80ba3 at vn_close1+0xe3

So, lock the vm object before undirtying our pages in
afs_vop_putpages.

Change-Id: Ifd047e3caf8c2b3e624aaf2bbdb1235a8c38a414
Reviewed-on: https://gerrit.openafs.org/14162
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>

src/afs/FBSD/osi_vnodeops.c

index e314e4c..2a0c2ab 100644 (file)
@@ -743,11 +743,13 @@ afs_vop_putpages(struct vop_putpages_args *ap)
     relpbuf(bp, &afs_pbuf_freecnt);
 
     if (!code) {
+       AFS_VM_OBJECT_WLOCK(vp->v_object);
        size = ap->a_count - uio.uio_resid;
        for (i = 0; i < round_page(size) / PAGE_SIZE; i++) {
            ap->a_rtvals[i] = VM_PAGER_OK;
            vm_page_undirty(ap->a_m[i]);
        }
+       AFS_VM_OBJECT_WUNLOCK(vp->v_object);
     }
     return ap->a_rtvals[0];
 }