The branch main has been updated by dougm:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1107834090be4df01070028f6a8cdb37ff1f51f1

commit 1107834090be4df01070028f6a8cdb37ff1f51f1
Author:     Doug Moore <[email protected]>
AuthorDate: 2024-10-11 17:45:54 +0000
Commit:     Doug Moore <[email protected]>
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.
                         */

Reply via email to