vm_object: allow paging_in_progress to be acquired after object termination.

The vm objects are type-stable, and can be accessed even after the
last reference is dropped, or in case of vnode objects, after vgone()
destroyed it as well.

Stop asserting that pip == 0 after vm_object_terminate() waited for
existing owners to drop it, we only want to drain them before setting
OBJ_DEAD flag.  Also stop asserting pip == 0 in object destructor.

Update comments explaining the interaction between paging_in_progress
and termination.

Reviewed by:	markj
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
Differential revision:	https://reviews.freebsd.org/D25968
This commit is contained in:
Konstantin Belousov 2020-08-16 20:57:02 +00:00
parent 419e5698a0
commit ffae7ea935

View file

@ -192,9 +192,6 @@ vm_object_zdtor(void *mem, int size, void *arg)
("object %p has reservations",
object));
#endif
KASSERT(blockcount_read(&object->paging_in_progress) == 0,
("object %p paging_in_progress = %d",
object, blockcount_read(&object->paging_in_progress)));
KASSERT(!vm_object_busied(object),
("object %p busy = %d", object, blockcount_read(&object->busy)));
KASSERT(object->resident_page_count == 0,
@ -294,6 +291,9 @@ vm_object_init(void)
* The lock portion of struct vm_object must be type stable due
* to vm_pageout_fallback_object_lock locking a vm object
* without holding any references to it.
*
* paging_in_progress is valid always. Lockless references to
* the objects may acquire pip and then check OBJ_DEAD.
*/
obj_zone = uma_zcreate("VM OBJECT", sizeof (struct vm_object), NULL,
#ifdef INVARIANTS
@ -936,13 +936,14 @@ vm_object_terminate(vm_object_t object)
("terminating shadow obj %p", object));
/*
* wait for the pageout daemon to be done with the object
* Wait for the pageout daemon and other current users to be
* done with the object. Note that new paging_in_progress
* users can come after this wait, but they must check
* OBJ_DEAD flag set (without unlocking the object), and avoid
* the object being terminated.
*/
vm_object_pip_wait(object, "objtrm");
KASSERT(!blockcount_read(&object->paging_in_progress),
("vm_object_terminate: pageout in progress"));
KASSERT(object->ref_count == 0,
("vm_object_terminate: object with references, ref_count=%d",
object->ref_count));