Author: kib
Date: Sat Aug 18 10:14:02 2018
New Revision: 338012
URL: https://svnweb.freebsd.org/changeset/base/338012

Log:
  MFC r337330:
  Swap in WKILLED processes.

Modified:
  stable/11/sys/kern/kern_sig.c
  stable/11/sys/kern/sys_process.c
  stable/11/sys/sys/proc.h
  stable/11/sys/vm/vm_swapout.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/kern/kern_sig.c
==============================================================================
--- stable/11/sys/kern/kern_sig.c       Sat Aug 18 08:32:21 2018        
(r338011)
+++ stable/11/sys/kern/kern_sig.c       Sat Aug 18 10:14:02 2018        
(r338012)
@@ -3075,6 +3075,23 @@ postsig(int sig)
        return (1);
 }
 
+void
+proc_wkilled(struct proc *p)
+{
+
+       PROC_LOCK_ASSERT(p, MA_OWNED);
+       if ((p->p_flag & P_WKILLED) == 0) {
+               p->p_flag |= P_WKILLED;
+               /*
+                * Notify swapper that there is a process to swap in.
+                * The notification is racy, at worst it would take 10
+                * seconds for the swapper process to notice.
+                */
+               if ((p->p_flag & (P_INMEM | P_SWAPPINGIN)) == 0)
+                       wakeup(&proc0);
+       }
+}
+
 /*
  * Kill the current process for stated reason.
  */
@@ -3087,7 +3104,7 @@ killproc(struct proc *p, char *why)
            p->p_comm);
        log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid,
            p->p_comm, p->p_ucred ? p->p_ucred->cr_uid : -1, why);
-       p->p_flag |= P_WKILLED;
+       proc_wkilled(p);
        kern_psignal(p, SIGKILL);
 }
 

Modified: stable/11/sys/kern/sys_process.c
==============================================================================
--- stable/11/sys/kern/sys_process.c    Sat Aug 18 08:32:21 2018        
(r338011)
+++ stable/11/sys/kern/sys_process.c    Sat Aug 18 10:14:02 2018        
(r338012)
@@ -1157,7 +1157,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi
                         * accommodate any new signals.
                         */
                        if (data == SIGKILL)
-                               p->p_flag |= P_WKILLED;
+                               proc_wkilled(p);
 
                        if (req == PT_DETACH) {
                                FOREACH_THREAD_IN_PROC(p, td3)

Modified: stable/11/sys/sys/proc.h
==============================================================================
--- stable/11/sys/sys/proc.h    Sat Aug 18 08:32:21 2018        (r338011)
+++ stable/11/sys/sys/proc.h    Sat Aug 18 10:14:02 2018        (r338012)
@@ -1037,6 +1037,7 @@ struct proc *proc_realparent(struct proc *child);
 void   proc_reap(struct thread *td, struct proc *p, int *status, int options);
 void   proc_reparent(struct proc *child, struct proc *newparent);
 void   proc_set_traced(struct proc *p, bool stop);
+void   proc_wkilled(struct proc *p);
 struct pstats *pstats_alloc(void);
 void   pstats_fork(struct pstats *src, struct pstats *dst);
 void   pstats_free(struct pstats *ps);

Modified: stable/11/sys/vm/vm_swapout.c
==============================================================================
--- stable/11/sys/vm/vm_swapout.c       Sat Aug 18 08:32:21 2018        
(r338011)
+++ stable/11/sys/vm/vm_swapout.c       Sat Aug 18 10:14:02 2018        
(r338012)
@@ -156,13 +156,14 @@ static struct mtx vm_daemon_mtx;
 /* Allow for use by vm_pageout before vm_daemon is initialized. */
 MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF);
 
+static int swapped_cnt;
+
 static void swapclear(struct proc *);
 static int swapout(struct proc *);
 static void vm_swapout_map_deactivate_pages(vm_map_t, long);
 static void vm_swapout_object_deactivate_pages(pmap_t, vm_object_t, long);
 static void swapout_procs(int action);
 static void vm_req_vmdaemon(int req);
-static void vm_thread_swapin(struct thread *td);
 static void vm_thread_swapout(struct thread *td);
 
 /*
@@ -554,7 +555,7 @@ vm_thread_swapout(struct thread *td)
  * Bring the kernel stack for a specified thread back in.
  */
 static void
-vm_thread_swapin(struct thread *td)
+vm_thread_swapin(struct thread *td, int oom_alloc)
 {
        vm_object_t ksobj;
        vm_page_t ma[KSTACK_MAX_PAGES];
@@ -563,7 +564,7 @@ vm_thread_swapin(struct thread *td)
        pages = td->td_kstack_pages;
        ksobj = td->td_kstack_obj;
        VM_OBJECT_WLOCK(ksobj);
-       (void)vm_page_grab_pages(ksobj, 0, VM_ALLOC_NORMAL | VM_ALLOC_WIRED, ma,
+       (void)vm_page_grab_pages(ksobj, 0, oom_alloc | VM_ALLOC_WIRED, ma,
            pages);
        for (i = 0; i < pages;) {
                vm_page_assert_xbusied(ma[i]);
@@ -596,8 +597,10 @@ void
 faultin(struct proc *p)
 {
        struct thread *td;
+       int oom_alloc;
 
        PROC_LOCK_ASSERT(p, MA_OWNED);
+
        /*
         * If another process is swapping in this process,
         * just wait until it finishes.
@@ -607,7 +610,11 @@ faultin(struct proc *p)
                        msleep(&p->p_flag, &p->p_mtx, PVM, "faultin", 0);
                return;
        }
+
        if ((p->p_flag & P_INMEM) == 0) {
+               oom_alloc = (p->p_flag & P_WKILLED) != 0 ? VM_ALLOC_SYSTEM :
+                   VM_ALLOC_NORMAL;
+
                /*
                 * Don't let another thread swap process p out while we are
                 * busy swapping it in.
@@ -615,6 +622,10 @@ faultin(struct proc *p)
                ++p->p_lock;
                p->p_flag |= P_SWAPPINGIN;
                PROC_UNLOCK(p);
+               sx_xlock(&allproc_lock);
+               MPASS(swapped_cnt > 0);
+               swapped_cnt--;
+               sx_xunlock(&allproc_lock);
 
                /*
                 * We hold no lock here because the list of threads
@@ -622,14 +633,14 @@ faultin(struct proc *p)
                 * swapped out.
                 */
                FOREACH_THREAD_IN_PROC(p, td)
-                       vm_thread_swapin(td);
+                       vm_thread_swapin(td, oom_alloc);
+
                PROC_LOCK(p);
                swapclear(p);
                p->p_swtick = ticks;
 
-               wakeup(&p->p_flag);
-
                /* Allow other threads to swap p out now. */
+               wakeup(&p->p_flag);
                --p->p_lock;
        }
 }
@@ -639,29 +650,41 @@ faultin(struct proc *p)
  * is enough space for them.  Of course, if a process waits for a long
  * time, it will be swapped in anyway.
  */
-void
-swapper(void)
+
+static struct proc *
+swapper_selector(void)
 {
-       struct proc *p, *pp;
+       struct proc *p, *res;
        struct thread *td;
-       int ppri, pri, slptime, swtime;
+       int min_flag, ppri, pri, slptime, swtime;
 
-loop:
-       if (vm_page_count_min()) {
-               VM_WAIT;
-               goto loop;
-       }
-
-       pp = NULL;
+       sx_assert(&allproc_lock, SA_SLOCKED);
+       if (swapped_cnt == 0)
+               return (NULL);
+       res = NULL;
        ppri = INT_MIN;
-       sx_slock(&allproc_lock);
+       min_flag = vm_page_count_min();
        FOREACH_PROC_IN_SYSTEM(p) {
                PROC_LOCK(p);
-               if (p->p_state == PRS_NEW ||
-                   p->p_flag & (P_SWAPPINGOUT | P_SWAPPINGIN | P_INMEM)) {
+               if (p->p_state == PRS_NEW || (p->p_flag & (P_SWAPPINGOUT |
+                   P_SWAPPINGIN | P_INMEM)) != 0) {
                        PROC_UNLOCK(p);
                        continue;
                }
+               if (p->p_state == PRS_NORMAL && (p->p_flag & P_WKILLED) != 0) {
+                       /*
+                        * A swapped-out process might have mapped a
+                        * large portion of the system's pages as
+                        * anonymous memory.  There is no other way to
+                        * release the memory other than to kill the
+                        * process, for which we need to swap it in.
+                        */
+                       return (p);
+               }
+               if (min_flag) {
+                       PROC_UNLOCK(p);
+                       continue;
+               }
                swtime = (ticks - p->p_swtick) / hz;
                FOREACH_THREAD_IN_PROC(p, td) {
                        /*
@@ -681,7 +704,7 @@ loop:
                                 * selection.
                                 */
                                if (pri > ppri) {
-                                       pp = p;
+                                       res = p;
                                        ppri = pri;
                                }
                        }
@@ -689,33 +712,40 @@ loop:
                }
                PROC_UNLOCK(p);
        }
-       sx_sunlock(&allproc_lock);
+       if (res != NULL)
+               PROC_LOCK(res);
+       return (res);
+}
 
-       /*
-        * Nothing to do, back to sleep.
-        */
-       if ((p = pp) == NULL) {
-               tsleep(&proc0, PVM, "swapin", MAXSLP * hz / 2);
-               goto loop;
-       }
-       PROC_LOCK(p);
+void
+swapper(void)
+{
+       struct proc *p;
 
-       /*
-        * Another process may be bringing or may have already
-        * brought this process in while we traverse all threads.
-        * Or, this process may even be being swapped out again.
-        */
-       if (p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) {
-               PROC_UNLOCK(p);
-               goto loop;
-       }
+       for (;;) {
+               sx_slock(&allproc_lock);
+               p = swapper_selector();
+               sx_sunlock(&allproc_lock);
 
-       /*
-        * We would like to bring someone in.
-        */
-       faultin(p);
-       PROC_UNLOCK(p);
-       goto loop;
+               if (p == NULL) {
+                       tsleep(&proc0, PVM, "swapin", MAXSLP * hz / 2);
+               } else {
+                       PROC_LOCK_ASSERT(p, MA_OWNED);
+
+                       /*
+                        * Another process may be bringing or may have
+                        * already brought this process in while we
+                        * traverse all threads.  Or, this process may
+                        * have exited or even being swapped out
+                        * again.
+                        */
+                       if (p->p_state == PRS_NORMAL && (p->p_flag & (P_INMEM |
+                           P_SWAPPINGOUT | P_SWAPPINGIN)) == 0) {
+                               faultin(p);
+                       }
+                       PROC_UNLOCK(p);
+               }
+       }
 }
 
 /*
@@ -794,7 +824,12 @@ swapout_procs(int action)
                        didswap = true;
 
                PROC_UNLOCK(p);
-               sx_slock(&allproc_lock);
+               if (didswap) {
+                       sx_xlock(&allproc_lock);
+                       swapped_cnt++;
+                       sx_downgrade(&allproc_lock);
+               } else
+                       sx_slock(&allproc_lock);
                PRELE(p);
        }
        sx_sunlock(&allproc_lock);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to