git: da0764f23554 - main - vm_swapout: Restore handling of RLIMIT_RSS

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 29 Sep 2026 20:01:56 UTC
The branch main has been updated by markj:

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

commit da0764f23554ef446003b5f2ab4e535a3329b0ab
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-09-29 19:45:25 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-29 20:01:45 +0000

    vm_swapout: Restore handling of RLIMIT_RSS
    
    In commit 13a1129d700c, I removed the mechanism by which the pagedaemon
    signals the swapout thread when page reclamation is unable to keep up
    with demand.  This is because the swapout thread's main action in this
    case is to swap out sleeping processes, but we removed this support.
    
    However, it had the secondary effect of causing the swapout thread to
    enforce RLIMIT_RSS when racct is not enabled.  Without it, if
    racct_enabled is false, nothing ever kicks the swapout thread.
    
    Restore the old behaviour of trying to enforce RLIMIT_RSS when the page
    daemon is unable to keep up with demand.  I'm not at all convinced this
    is a good way to implement the limit, but the change wasn't intentional,
    so let's restore it for now.
    
    Fixes:          13a1129d700c ("vm: Remove kernel stack swapping support, part 1")
    Reviewed by:    olce, kib
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D56142
---
 sys/conf/files      |  2 +-
 sys/vm/vm_pageout.c |  8 +++++++-
 sys/vm/vm_pageout.h |  2 ++
 sys/vm/vm_swapout.c | 18 +++++++++++++++---
 4 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/sys/conf/files b/sys/conf/files
index 495881e7ae0c..9dc3d34f3bd6 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -5413,7 +5413,7 @@ vm/vm_pager.c			standard
 vm/vm_phys.c			standard
 vm/vm_radix.c			standard
 vm/vm_reserv.c			standard
-vm/vm_swapout.c			optional racct
+vm/vm_swapout.c			standard
 vm/vm_unix.c			standard
 vm/vnode_pager.c		standard
 xen/features.c			optional xenhvm
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 418a9cff8abf..fa4c356258f0 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -1683,7 +1683,7 @@ reinsert:
  * results to present a coherent view of paging activity on this domain.
  */
 static int
-vm_pageout_inactive_dispatch(struct vm_domain *vmd, int shortage)
+vm_pageout_inactive_dispatch(struct vm_domain *vmd, u_int shortage)
 {
 	u_int freed, pps, slop, threads, us;
 
@@ -1796,6 +1796,12 @@ vm_pageout_inactive(struct vm_domain *vmd, int shortage, int *addl_shortage)
 	 */
 	vm_pageout_mightbe_oom(vmd, page_shortage, starting_page_shortage);
 
+	/*
+	 * Kick the swapout thread to enforce RSS limits.
+	 */
+	if (page_shortage > 0)
+		vm_swapout_run();
+
 	/*
 	 * See the description of addl_page_shortage above.
 	 */
diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h
index 5cfb6e5ca198..7413960eb9b4 100644
--- a/sys/vm/vm_pageout.h
+++ b/sys/vm/vm_pageout.h
@@ -103,5 +103,7 @@ void vm_wait_severe(void);
 int vm_pageout_flush(vm_page_t *mc, int count, int flags, bool *eio);
 void vm_pageout_oom(int shortage);
 
+void vm_swapout_run(void);
+
 #endif /* _KERNEL */
 #endif	/* _VM_VM_PAGEOUT_H_ */
diff --git a/sys/vm/vm_swapout.c b/sys/vm/vm_swapout.c
index e85a049f46fe..a0c61c33fa5a 100644
--- a/sys/vm/vm_swapout.c
+++ b/sys/vm/vm_swapout.c
@@ -135,6 +135,19 @@ MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
 static void vm_swapout_map_deactivate_pages(vm_map_t, long);
 static void vm_swapout_object_deactivate(pmap_t, vm_object_t, long);
 
+void
+vm_swapout_run(void)
+{
+	static int lastrun = 0;
+
+	mtx_lock(&vm_daemon_mtx);
+	if (ticks - lastrun >= hz || ticks < lastrun) {
+		wakeup(&vm_daemon_needed);
+		lastrun = ticks;
+	}
+	mtx_unlock(&vm_daemon_mtx);
+}
+
 static void
 vm_swapout_object_deactivate_page(pmap_t pmap, vm_page_t m, bool unmap)
 {
@@ -287,15 +300,14 @@ vm_daemon(void)
 	if (racct_enable && vm_daemon_timeout == 0)
 		vm_daemon_timeout = hz;
 
-	while (TRUE) {
+	while (true) {
 		mtx_lock(&vm_daemon_mtx);
 		msleep(&vm_daemon_needed, &vm_daemon_mtx, PPAUSE, "psleep",
 		    vm_daemon_timeout);
 		mtx_unlock(&vm_daemon_mtx);
 
 		/*
-		 * scan the processes for exceeding their rlimits or if
-		 * process is swapped out -- deactivate pages
+		 * Scan for processes exceeding their rlimits.
 		 */
 		tryagain = 0;
 		attempts = 0;