Skip to content

Commit

Permalink
swap_pager: swapoff detecting object death
Browse files Browse the repository at this point in the history
In swap_pager_swapoff_object, the object is initially not dead, and
can only become dead while the object lock is not held. Move the test
for object-death so that it is right after the early loop-break that
happens after lock re-acquisition, and before the iterator is
re-initialized, which fails an assertion when the object is dead,
and not swap.

Addresses a problem produced in testing by @pho and diagnosed by @kib.

Reported by:	pho
Reviewed by:	alc, kib
Differential Revision:	https://reviews.freebsd.org/D47064
  • Loading branch information
Doug Moore authored and Doug Moore committed Oct 11, 2024
1 parent 4f2ca36 commit 1107834
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions sys/vm/swap_pager.c
Original file line number Diff line number Diff line change
Expand Up @@ -1910,22 +1910,15 @@ swap_pager_swapoff_object(struct swdevt *sp, vm_object_t object)
VM_OBJECT_ASSERT_WLOCKED(object);
KASSERT((object->flags & OBJ_SWAP) != 0,
("%s: Object not swappable", __func__));
KASSERT((object->flags & OBJ_DEAD) == 0,
("%s: Object already dead", __func__));
KASSERT((sp->sw_flags & SW_CLOSING) != 0,
("%s: Device not blocking further allocations", __func__));

vm_page_iter_init(&pages, object);
swp_pager_init_freerange(&range);
sb = swblk_iter_init(&blks, object, 0);
while (sb != NULL) {
if ((object->flags & OBJ_DEAD) != 0) {
/*
* Make sure that pending writes finish before
* returning.
*/
vm_object_pip_wait(object, "swpoff");
swp_pager_meta_free_all(object);
break;
}
sb_empty = true;
for (i = 0; i < SWAP_META_PAGES; i++) {
/* Skip an invalid block. */
Expand Down Expand Up @@ -1983,8 +1976,21 @@ swap_pager_swapoff_object(struct swdevt *sp, vm_object_t object)
}
if (i < SWAP_META_PAGES) {
/*
* With the object lock released and regained, the
* swapblk could have been freed, so reset the pages
* The object lock has been released and regained.
* Perhaps the object is now dead.
*/
if ((object->flags & OBJ_DEAD) != 0) {
/*
* Make sure that pending writes finish before
* returning.
*/
vm_object_pip_wait(object, "swpoff");
swp_pager_meta_free_all(object);
break;
}

/*
* The swapblk could have been freed, so reset the pages
* iterator and search again for the first swblk at or
* after blks.index.
*/
Expand Down

0 comments on commit 1107834

Please sign in to comment.