git: 1107834090be - main - swap_pager: swapoff detecting object death
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 11 Oct 2024 17:48:19 UTC
The branch main has been updated by dougm:
URL: https://cgit.FreeBSD.org/src/commit/?id=1107834090be4df01070028f6a8cdb37ff1f51f1
commit 1107834090be4df01070028f6a8cdb37ff1f51f1
Author: Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2024-10-11 17:45:54 +0000
Commit: Doug Moore <dougm@FreeBSD.org>
CommitDate: 2024-10-11 17:45:54 +0000
swap_pager: swapoff detecting object death
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
---
sys/vm/swap_pager.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index f4db46a32dee..23b5e1c34b07 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -1910,6 +1910,8 @@ 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__));
@@ -1917,15 +1919,6 @@ swap_pager_swapoff_object(struct swdevt *sp, vm_object_t 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. */
@@ -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.
*/