patch-2.1.132 linux/mm/vmscan.c

Next file: linux/net/802/tr.c
Previous file: linux/mm/swap_state.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.131/linux/mm/vmscan.c linux/mm/vmscan.c
@@ -418,45 +418,6 @@
 }
 
 /*
- * We are much more aggressive about trying to swap out than we used
- * to be.  This works out OK, because we now do proper aging on page
- * contents. 
- */
-static int do_try_to_free_page(int gfp_mask)
-{
-	static int state = 0;
-	int i=6;
-
-	/* Always trim SLAB caches when memory gets low. */
-	kmem_cache_reap(gfp_mask);
-
-	if (buffer_over_borrow() || pgcache_over_borrow())
-		state = 0;
-
-	switch (state) {
-		do {
-		case 0:
-			if (shrink_mmap(i, gfp_mask))
-				return 1;
-			state = 1;
-		case 1:
-			if (shm_swap(i, gfp_mask))
-				return 1;
-			state = 2;
-		case 2:
-			if (swap_out(i, gfp_mask))
-				return 1;
-			state = 3;
-		case 3:
-			shrink_dcache_memory(i, gfp_mask);
-			state = 0;
-		i--;
-		} while (i >= 0);
-	}
-	return 0;
-}
-
-/*
  * Before we start the kernel thread, print out the 
  * kswapd initialization message (otherwise the init message 
  * may be printed in the middle of another driver's init 
@@ -467,6 +428,8 @@
        int i;
        char *revision="$Revision: 1.5 $", *s, *e;
 
+       swap_setup();
+       
        if ((s = strchr(revision, ':')) &&
            (e = strchr(s, '$')))
                s++, i = e - s;
@@ -475,6 +438,44 @@
        printk ("Starting kswapd v%.*s\n", i, s);
 }
 
+#define free_memory(fn) \
+	count++; do { if (!--count) goto done; } while (fn)
+
+static int kswapd_free_pages(int kswapd_state)
+{
+	unsigned long end_time;
+
+	/* Always trim SLAB caches when memory gets low. */
+	kmem_cache_reap(0);
+
+	/* max one hundreth of a second */
+	end_time = jiffies + (HZ-1)/100;
+	do {
+		int priority = 5;
+		int count = pager_daemon.swap_cluster;
+
+		switch (kswapd_state) {
+			do {
+			default:
+				free_memory(shrink_mmap(priority, 0));
+				kswapd_state++;
+			case 1:
+				free_memory(shm_swap(priority, 0));
+				kswapd_state++;
+			case 2:
+				free_memory(swap_out(priority, 0));
+				shrink_dcache_memory(priority, 0);
+				kswapd_state = 0;
+			} while (--priority >= 0);
+			return kswapd_state;
+		}
+done:
+		if (nr_free_pages > freepages.high + pager_daemon.swap_cluster)
+			break;
+	} while (time_before_eq(jiffies,end_time));
+	return kswapd_state;
+}
+
 /*
  * The background pageout daemon.
  * Started as a kernel thread from the init process.
@@ -517,22 +518,14 @@
 	init_swap_timer();
 	kswapd_task = current;
 	while (1) {
-		unsigned long end_time;
+		int state = 0;
 
 		current->state = TASK_INTERRUPTIBLE;
 		flush_signals(current);
 		run_task_queue(&tq_disk);
 		schedule();
 		swapstats.wakeups++;
-
-		/* max one hundreth of a second */
-		end_time = jiffies + (HZ-1)/100;
-		do {
-			if (!do_try_to_free_page(0))
-				break;
-			if (nr_free_pages > freepages.high + SWAP_CLUSTER_MAX)
-				break;
-		} while (time_before_eq(jiffies,end_time));
+		state = kswapd_free_pages(state);
 	}
 	/* As if we could ever get here - maybe we want to make this killable */
 	kswapd_task = NULL;
@@ -549,23 +542,39 @@
  * if we need more memory as part of a swap-out effort we
  * will just silently return "success" to tell the page
  * allocator to accept the allocation.
+ *
+ * We want to try to free "count" pages, and we need to 
+ * cluster them so that we get good swap-out behaviour. See
+ * the "free_memory()" macro for details.
  */
 int try_to_free_pages(unsigned int gfp_mask, int count)
 {
-	int retval = 1;
+	int retval;
 
 	lock_kernel();
+
+	/* Always trim SLAB caches when memory gets low. */
+	kmem_cache_reap(gfp_mask);
+
+	retval = 1;
 	if (!(current->flags & PF_MEMALLOC)) {
+		int priority;
+
 		current->flags |= PF_MEMALLOC;
+	
+		priority = 5;
 		do {
-			retval = do_try_to_free_page(gfp_mask);
-			if (!retval)
-				break;
-			count--;
-		} while (count > 0);
+			free_memory(shrink_mmap(priority, gfp_mask));
+			free_memory(shm_swap(priority, gfp_mask));
+			free_memory(swap_out(priority, gfp_mask));
+			shrink_dcache_memory(priority, gfp_mask);
+		} while (--priority >= 0);
+		retval = 0;
+done:
 		current->flags &= ~PF_MEMALLOC;
 	}
 	unlock_kernel();
+
 	return retval;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov