Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Oct 2023 00:58:54 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: aa229a59adea - stable/14 - swap_pager: Fix a race in swap_pager_swapoff_object()
Message-ID:  <202310090058.3990wsmr040210@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by markj:

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

commit aa229a59adeaf49517183c8117a239e2b68012f5
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-10-02 11:49:27 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-10-09 00:41:35 +0000

    swap_pager: Fix a race in swap_pager_swapoff_object()
    
    When we disable swapping to a device, we scan the full VM object list
    looking for objects with swap trie nodes that reference the device in
    question.  The pages corresponding to those nodes are paged in.
    
    While paging in, we drop the VM object lock.  Moreover, we do not hold a
    reference for the object; swap_pager_swapoff_object() merely bumps the
    paging-in-progress counter.  vm_object_terminate() waits for this
    counter to drain before proceeding and freeing pages.
    
    However, swap_pager_swapoff_object() decrements the counter before
    re-acquiring the VM object lock, which means that vm_object_terminate()
    can race to acquire the lock and free the pages.  Then,
    swap_pager_swapoff_object() ends up unbusying a freed page.  Fix the
    problem by acquiring the lock before waking up sleepers.
    
    PR:             273610
    Reported by:    Graham Perrin <grahamperrin@gmail.com>
    Reviewed by:    kib
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D42029
    
    (cherry picked from commit e61568aeeec7667789e6c9d4837e074edecc990e)
---
 sys/vm/swap_pager.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index e548c2d16a0b..38151b3be96f 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -1890,8 +1890,8 @@ swap_pager_swapoff_object(struct swdevt *sp, vm_object_t object)
 			if (rv != VM_PAGER_OK)
 				panic("%s: read from swap failed: %d",
 				    __func__, rv);
-			vm_object_pip_wakeupn(object, 1);
 			VM_OBJECT_WLOCK(object);
+			vm_object_pip_wakeupn(object, 1);
 			vm_page_xunbusy(m);
 
 			/*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202310090058.3990wsmr040210>