The branch stable/13 has been updated by kib:

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

commit 08d995ca8f6f1008a10e4bf4d924824c040f842a
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2021-11-26 23:22:27 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2021-12-06 00:29:43 +0000

    swapoff_one(): only check free pages count manually turning swap off
    
    (cherry picked from commit 0190c38b9dfaa16de1bc61e829b9a1221fed7896)
---
 sys/vm/swap_pager.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 78533c9fb5e6..473d950dafbf 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -469,7 +469,8 @@ static bool swp_pager_swblk_empty(struct swblk *sb, int 
start, int limit);
 static void    swp_pager_free_empty_swblk(vm_object_t, struct swblk *sb);
 static int     swapongeom(struct vnode *);
 static int     swaponvp(struct thread *, struct vnode *, u_long);
-static int     swapoff_one(struct swdevt *sp, struct ucred *cred);
+static int     swapoff_one(struct swdevt *sp, struct ucred *cred,
+                   bool ignore_check);
 
 /*
  * Swap bitmap functions
@@ -2518,14 +2519,14 @@ sys_swapoff(struct thread *td, struct swapoff_args *uap)
                error = EINVAL;
                goto done;
        }
-       error = swapoff_one(sp, td->td_ucred);
+       error = swapoff_one(sp, td->td_ucred, false);
 done:
        sx_xunlock(&swdev_syscall_lock);
        return (error);
 }
 
 static int
-swapoff_one(struct swdevt *sp, struct ucred *cred)
+swapoff_one(struct swdevt *sp, struct ucred *cred, bool ignore_check)
 {
        u_long nblks;
 #ifdef MAC
@@ -2547,8 +2548,16 @@ swapoff_one(struct swdevt *sp, struct ucred *cred)
         * available virtual memory in the system will fit the amount
         * of data we will have to page back in, plus an epsilon so
         * the system doesn't become critically low on swap space.
+        * The vm_free_count() part does not account e.g. for clean
+        * pages that can be immediately reclaimed without paging, so
+        * this is a very rough estimation.
+        *
+        * On the other hand, not turning swap off on swapoff_all()
+        * means that we can lose swap data when filesystems go away,
+        * which is arguably worse.
         */
-       if (vm_free_count() + swap_pager_avail < nblks + nswap_lowat)
+       if (!ignore_check &&
+           vm_free_count() + swap_pager_avail < nblks + nswap_lowat)
                return (ENOMEM);
 
        /*
@@ -2598,7 +2607,7 @@ swapoff_all(void)
                        devname = devtoname(sp->sw_vp->v_rdev);
                else
                        devname = "[file]";
-               error = swapoff_one(sp, thread0.td_ucred);
+               error = swapoff_one(sp, thread0.td_ucred, true);
                if (error != 0) {
                        printf("Cannot remove swap device %s (error=%d), "
                            "skipping.\n", devname, error);

Reply via email to