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

Reply via email to