svn commit: r338012 - in stable/11/sys: kern sys vm

Konstantin Belousov kib at FreeBSD.org
Sat Aug 18 10:14:04 UTC 2018


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);


More information about the svn-src-stable-11 mailing list