Index: sys/vm/vm_object.h =================================================================== --- sys/vm/vm_object.h +++ sys/vm/vm_object.h @@ -175,6 +175,7 @@ #define OBJ_NOSPLIT 0x0010 /* dont split this object */ #define OBJ_UMTXDEAD 0x0020 /* umtx pshared was terminated */ #define OBJ_PIPWNT 0x0040 /* paging in progress wanted */ +#define OBJ_PG_DTOR 0x0080 /* dont reset object, leave that for dtor */ #define OBJ_MIGHTBEDIRTY 0x0100 /* object might be dirty, only for vnode */ #define OBJ_TMPFS_NODE 0x0200 /* object belongs to tmpfs VREG node */ #define OBJ_TMPFS_DIRTY 0x0400 /* dirty tmpfs obj */ Index: sys/vm/vm_object.c =================================================================== --- sys/vm/vm_object.c +++ sys/vm/vm_object.c @@ -746,40 +746,45 @@ ("vm_object_terminate: object with references, ref_count=%d", object->ref_count)); - /* - * Free any remaining pageable pages. This also removes them from the - * paging queues. However, don't free wired pages, just remove them - * from the object. Rather than incrementally removing each page from - * the object, the page and object are reset to any empty state. - */ - TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) { - vm_page_assert_unbusied(p); - vm_page_lock(p); + if ((object->flags & OBJ_PG_DTOR) == 0) { /* - * Optimize the page's removal from the object by resetting - * its "object" field. Specifically, if the page is not - * wired, then the effect of this assignment is that - * vm_page_free()'s call to vm_page_remove() will return - * immediately without modifying the page or the object. - */ - p->object = NULL; - if (p->wire_count == 0) { - vm_page_free(p); - VM_CNT_INC(v_pfree); + * Free any remaining pageable pages. This also removes them + * from the paging queues. However, don't free wired pages, + * just remove them from the object. Rather than incrementally + * removing each page from the object, the page and object are + * reset to any empty state. + */ + TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) { + vm_page_assert_unbusied(p); + vm_page_lock(p); + /* + * Optimize the page's removal from the object by + * resetting its "object" field. Specifically, if + * the page is not wired, then the effect of this + * assignment is that vm_page_free()'s call to + * vm_page_remove() will return immediately without + * modifying the page or the object. + */ + p->object = NULL; + if (p->wire_count == 0) { + vm_page_free(p); + VM_CNT_INC(v_pfree); + } + vm_page_unlock(p); + } + /* + * If the object contained any pages, then reset it to an + * empty state. None of the object's fields, including + * "resident_page_count", were modified by the preceding + * loop. + */ + if (object->resident_page_count != 0) { + vm_radix_reclaim_allnodes(&object->rtree); + TAILQ_INIT(&object->memq); + object->resident_page_count = 0; + if (object->type == OBJT_VNODE) + vdrop(object->handle); } - vm_page_unlock(p); - } - /* - * If the object contained any pages, then reset it to an empty state. - * None of the object's fields, including "resident_page_count", were - * modified by the preceding loop. - */ - if (object->resident_page_count != 0) { - vm_radix_reclaim_allnodes(&object->rtree); - TAILQ_INIT(&object->memq); - object->resident_page_count = 0; - if (object->type == OBJT_VNODE) - vdrop(object->handle); } #if VM_NRESERVLEVEL > 0