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:[EMAIL PROTECTED] | http://login.dknet.dk/~pho/
-[ Member of the BSD-Dk User Group / http://www.bsd-dk.dk/ ] -
*** 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;
}