Sprinkle uvm_obj_destroy() over UVM object recycling code.
authormpi <mpi@openbsd.org>
Sat, 23 Oct 2021 14:42:07 +0000 (14:42 +0000)
committermpi <mpi@openbsd.org>
Sat, 23 Oct 2021 14:42:07 +0000 (14:42 +0000)
For now, only assert that the tree of pages is empty in uvm_obj_destroy().
This will soon be used to free the per-UVM object lock.

While here call uvm_obj_init() when new vnodes are allocated instead of
in uvn_attach().  Because vnodes and there associated UVM object are
currently never freed, it isn't easy to know where/when to garbage
collect the associated lock.  So simply check that the reference of a
given object is 0 when uvn_attach().

Tested by many as part of a bigger diff.

ok kettenis@

sys/kern/vfs_subr.c
sys/uvm/uvm_aobj.c
sys/uvm/uvm_device.c
sys/uvm/uvm_object.c
sys/uvm/uvm_vnode.c

index af78c42..88e0012 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vfs_subr.c,v 1.310 2021/10/23 14:08:46 mpi Exp $      */
+/*     $OpenBSD: vfs_subr.c,v 1.311 2021/10/23 14:42:07 mpi Exp $      */
 /*     $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $   */
 
 /*
@@ -410,6 +410,7 @@ getnewvnode(enum vtagtype tag, struct mount *mp, const struct vops *vops,
                vp = pool_get(&vnode_pool, PR_WAITOK | PR_ZERO);
                vp->v_uvm = pool_get(&uvm_vnode_pool, PR_WAITOK | PR_ZERO);
                vp->v_uvm->u_vnode = vp;
+               uvm_obj_init(&vp->v_uvm->u_obj, &uvm_vnodeops, 0);
                RBT_INIT(buf_rb_bufs, &vp->v_bufs_tree);
                cache_tree_init(&vp->v_nc_tree);
                TAILQ_INIT(&vp->v_cache_dst);
index 94649a9..70a848d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_aobj.c,v 1.99 2021/06/28 11:19:01 mpi Exp $       */
+/*     $OpenBSD: uvm_aobj.c,v 1.100 2021/10/23 14:42:07 mpi Exp $      */
 /*     $NetBSD: uvm_aobj.c,v 1.39 2001/02/18 21:19:08 chs Exp $        */
 
 /*
@@ -372,6 +372,7 @@ uao_free(struct uvm_aobj *aobj)
        /*
         * finally free the aobj itself
         */
+       uvm_obj_destroy(uobj);
        pool_put(&uvm_aobj_pool, aobj);
 }
 
index 0a8cf7b..e5d035f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_device.c,v 1.64 2021/06/29 01:46:35 jsg Exp $     */
+/*     $OpenBSD: uvm_device.c,v 1.65 2021/10/23 14:42:08 mpi Exp $     */
 /*     $NetBSD: uvm_device.c,v 1.30 2000/11/25 06:27:59 chs Exp $      */
 
 /*
@@ -182,6 +182,7 @@ udv_attach(dev_t device, vm_prot_t accessprot, voff_t off, vsize_t size)
                mtx_leave(&udv_lock);
                /* NOTE: we could sleep in the following malloc() */
                udv = malloc(sizeof(*udv), M_TEMP, M_WAITOK);
+               uvm_obj_init(&udv->u_obj, &uvm_deviceops, 1);
                mtx_enter(&udv_lock);
 
                /*
@@ -199,6 +200,7 @@ udv_attach(dev_t device, vm_prot_t accessprot, voff_t off, vsize_t size)
                 */
                if (lcv) {
                        mtx_leave(&udv_lock);
+                       uvm_obj_destroy(&udv->u_obj);
                        free(udv, M_TEMP, sizeof(*udv));
                        continue;
                }
@@ -207,7 +209,6 @@ udv_attach(dev_t device, vm_prot_t accessprot, voff_t off, vsize_t size)
                 * we have it!   init the data structures, add to list
                 * and return.
                 */
-               uvm_obj_init(&udv->u_obj, &uvm_deviceops, 1);
                udv->u_flags = 0;
                udv->u_device = device;
                LIST_INSERT_HEAD(&udv_list, udv, u_list);
@@ -275,6 +276,8 @@ again:
        if (udv->u_flags & UVM_DEVICE_WANTED)
                wakeup(udv);
        mtx_leave(&udv_lock);
+
+       uvm_obj_destroy(uobj);
        free(udv, M_TEMP, sizeof(*udv));
 }
 
index 20b57df..675cd9d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_object.c,v 1.21 2021/10/12 18:16:51 kettenis Exp $        */
+/*     $OpenBSD: uvm_object.c,v 1.22 2021/10/23 14:42:08 mpi Exp $     */
 
 /*
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -66,9 +66,13 @@ uvm_obj_init(struct uvm_object *uobj, const struct uvm_pagerops *pgops, int refs
        uobj->uo_refs = refs;
 }
 
+/*
+ * uvm_obj_destroy: destroy UVM memory object.
+ */
 void
 uvm_obj_destroy(struct uvm_object *uo)
 {
+       KASSERT(RBT_EMPTY(uvm_objtree, &uo->memt));
 }
 
 #ifndef SMALL_KERNEL
index 7d59844..3cbdd52 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_vnode.c,v 1.118 2021/10/20 06:35:40 semarie Exp $ */
+/*     $OpenBSD: uvm_vnode.c,v 1.119 2021/10/23 14:42:08 mpi Exp $     */
 /*     $NetBSD: uvm_vnode.c,v 1.36 2000/11/24 20:34:01 chs Exp $       */
 
 /*
@@ -229,7 +229,8 @@ uvn_attach(struct vnode *vp, vm_prot_t accessprot)
 #endif
 
        /* now set up the uvn. */
-       uvm_obj_init(&uvn->u_obj, &uvm_vnodeops, 1);
+       KASSERT(uvn->u_obj.uo_refs == 0);
+       uvn->u_obj.uo_refs++;
        oldflags = uvn->u_flags;
        uvn->u_flags = UVM_VNODE_VALID|UVM_VNODE_CANPERSIST;
        uvn->u_nio = 0;