Date: Sat, 17 Jul 1999 15:00:02 +0200 From: Peter Holm <peter@holm.cc> To: Freebsd-current@freebsd.org Subject: Out of swap handling Message-ID: <37907E52.7A257D9E@holm.cc>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------2FD23224575AA298CF8FBAE3 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit I have tested out of swap handling in current. The situation is that the system just lockes up, "looping" in vm_pageout_scan. I have experimented with some modifications to vm_pageout.c that seems to improve the chances for a recovery drastically. All tests were done on my 128Mb RAM / 256 Mb swap box. The changes consists of: * Killing all running user processes when less than 1024 pages swap left. * Sleeping after each kill to allow the user process to run. * Pausing the vmdaemon when in kill mode. I have tried different strategies for when to stop killing but only this one seems to guaranty recovery. I have included my changes. Regards, -- Peter Holm | mailto:peter@holm.cc | http://login.dknet.dk/~pho/ -[ Member of the BSD-Dk User Group / http://www.bsd-dk.dk/ ] - --------------2FD23224575AA298CF8FBAE3 Content-Type: text/plain; charset=us-ascii; name="patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="patch" *** sys/vm/vm_pageout.c~ Sun Jul 4 13:53:49 1999 --- sys/vm/vm_pageout.c Sat Jul 17 13:51:39 1999 *************** *** 154,159 **** --- 154,162 ---- static int vm_swap_idle_enabled=0; #endif + static int kill_mode = 0; + static pid_t last_killed_pid = 0; + SYSCTL_INT(_vm, VM_PAGEOUT_ALGORITHM, pageout_algorithm, CTLFLAG_RW, &vm_pageout_algorithm_lru, 0, "LRU page mgmt"); *************** *** 204,209 **** --- 207,213 ---- #endif static void vm_pageout_page_stats(void); + /* * vm_pageout_clean: * *************** *** 1126,1175 **** } /* ! * make sure that we have swap space -- if we are low on memory and * swap -- then kill the biggest process. */ ! if ((vm_swap_size == 0 || swap_pager_full) && ! ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min)) { ! bigproc = NULL; ! bigsize = 0; ! for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { ! /* ! * if this is a system process, skip it ! */ ! if ((p->p_flag & P_SYSTEM) || (p->p_lock > 0) || ! (p->p_pid == 1) || ! ((p->p_pid < 48) && (vm_swap_size != 0))) { ! continue; ! } ! /* ! * if the process is in a non-running type state, ! * don't touch it. ! */ ! if (p->p_stat != SRUN && p->p_stat != SSLEEP) { ! continue; } ! /* ! * get the process size ! */ ! size = vmspace_resident_count(p->p_vmspace); ! /* ! * if the this process is bigger than the biggest one ! * remember it. ! */ ! if (size > bigsize) { ! bigproc = p; ! bigsize = size; } ! } ! if (bigproc != NULL) { ! killproc(bigproc, "out of swap space"); ! bigproc->p_estcpu = 0; ! bigproc->p_nice = PRIO_MIN; ! resetpriority(bigproc); ! wakeup(&cnt.v_free_count); ! } ! } return force_wakeup; } --- 1130,1196 ---- } /* ! * make sure that we have swap space -- if we are low on * swap -- then kill the biggest process. */ ! #ifdef NO_SWAPPING ! if (kill_mode) ! kill_mode = ((cnt.v_free_count + cnt.v_cache_count) < ! 3*cnt.v_free_min); ! else ! kill_mode = ((cnt.v_free_count + cnt.v_cache_count) < ! cnt.v_free_min); ! #else ! if (kill_mode) ! kill_mode = (vm_swap_size < 3072); ! else ! kill_mode = (vm_swap_size < 1024); ! #endif ! ! if (kill_mode) { /* Kill all running user procs, biggest first */ ! do { ! bigproc = NULL; ! bigsize = 0; ! for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { ! /* ! * if this is a system process, skip it ! */ ! if ((p->p_flag & P_SYSTEM) || (p->p_lock > 0) || ! (p->p_pid == 1) || ! ((p->p_pid < 48) && (vm_swap_size != 0))) { ! continue; ! } ! /* ! * if the process is in a non-running type state, ! * don't touch it. ! */ ! if (p->p_stat != SRUN) continue; ! if (p->p_siglist & (SIGKILL | P_WEXIT)) continue; ! if (p->p_cred->p_ruid < 2) continue; ! if (p->p_pid == last_killed_pid) continue; ! /* ! * get the process size ! */ ! size = vmspace_resident_count(p->p_vmspace); ! /* ! * if the this process is bigger than the biggest one ! * remember it. ! */ ! if (size > bigsize) { ! bigproc = p; ! bigsize = size; ! } } ! if (bigproc != NULL) { ! killproc(bigproc, "out of swap space"); ! last_killed_pid = bigproc->p_pid; ! s = splvm(); ! tsleep(&vm_pages_needed, PVM, "psleep", hz/30); ! splx(s); } ! } while (bigproc); ! } /* kill mode */ ! wakeup(&cnt.v_free_count); return force_wakeup; } *************** *** 1404,1411 **** --- 1425,1439 ---- vm_daemon() { struct proc *p; + int s; while (TRUE) { + if (kill_mode) { + /* Give killed user procs a chance to die */ + s = splvm(); + tsleep(&vm_pages_needed, PVM, "psleep", hz); + splx(s); + } tsleep(&vm_daemon_needed, PPAUSE, "psleep", 0); if (vm_pageout_req_swapout) { swapout_procs(vm_pageout_req_swapout); *** sys/vm/swap_pager.c~ Tue Jun 29 21:45:31 1999 --- sys/vm/swap_pager.c Fri Jul 16 17:49:45 1999 *************** *** 214,220 **** --- 214,222 ---- { if (vm_swap_size < nswap_lowat) { if (swap_pager_almost_full == 0) { + #ifdef DISGNOSTIC printf("swap_pager: out of swap space\n"); + #endif swap_pager_almost_full = 1; } } else { *************** *** 470,476 **** --- 472,480 ---- if ((blk = blist_alloc(swapblist, npages)) == SWAPBLK_NONE) { if (swap_pager_full != 2) { + #ifdef DIAGNOSTIC printf("swap_pager_getswapspace: failed\n"); + #endif swap_pager_full = 2; swap_pager_almost_full = 1; } --------------2FD23224575AA298CF8FBAE3-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?37907E52.7A257D9E>