patch-2.2.16 linux/mm/vmscan.c

Next file: linux/net/appletalk/aarp.c
Previous file: linux/mm/page_io.c
Back to the patch index
Back to the overall index

diff -urN v2.2.15/linux/mm/vmscan.c linux/mm/vmscan.c
@@ -333,6 +333,7 @@
 
 	for (; counter >= 0; counter--) {
 		max_cnt = 0;
+		assign = 0;
 		pbest = NULL;
 	select:
 		read_lock(&tasklist_lock);
@@ -377,10 +378,17 @@
  * cluster them so that we get good swap-out behaviour. See
  * the "free_memory()" macro for details.
  */
+#define FLUSH_COUNT	8
 static int do_try_to_free_pages(unsigned int gfp_mask)
 {
-	int priority;
-	int count = SWAP_CLUSTER_MAX;
+	int priority, count, swapcount;
+	int flushcount = FLUSH_COUNT;
+	int ret = 0;
+
+	/* Kswapd does nothing but freeing pages so we can do big bites. */
+	if (gfp_mask == GFP_KSWAPD)
+		flushcount = SWAP_CLUSTER_MAX;
+	count = flushcount;
 
 	lock_kernel();
 
@@ -390,6 +398,7 @@
 	priority = 6;
 	do {
 		while (shrink_mmap(priority, gfp_mask)) {
+			ret = 1;
 			if (!--count)
 				goto done;
 		}
@@ -397,23 +406,36 @@
 		/* Try to get rid of some shared memory pages.. */
 		if (gfp_mask & __GFP_IO) {
 			while (shm_swap(priority, gfp_mask)) {
+				ret = 1;
 				if (!--count)
 					goto done;
 			}
 		}
 
 		/* Then, try to page stuff out.. */
+		swapcount = flushcount;
 		while (swap_out(priority, gfp_mask)) {
-			if (!--count)
-				goto done;
+			if (!--swapcount)
+				break;
 		}
 
 		shrink_dcache_memory(priority, gfp_mask);
 	} while (--priority >= 0);
+
+	/* End with a shrink_mmap() to make sure we free something. */
+	while (shrink_mmap(0, gfp_mask)) {
+		ret = 1;
+		if (!--count)
+			goto done;
+	}
 done:
 	unlock_kernel();
 
-	return priority >= 0;
+	if (!ret)
+		printk("VM: do_try_to_free_pages failed for %s...\n",
+				current->comm);
+	/* Return success if we freed a page. */
+	return ret;
 }
 
 /*
@@ -485,10 +507,18 @@
 		 * the processes needing more memory will wake us
 		 * up on a more timely basis.
 		 */
+		int failed = 0;
+sleep:
 		interruptible_sleep_on(&kswapd_wait);
+		/* Enough free pages? -> call do_try_to_free_pages only once. */
+		if (nr_free_pages > freepages.low) {
+			do_try_to_free_pages(GFP_KSWAPD);
+			goto sleep;
+		}
+		/* Not enough free pages? -> free pages agressively. */
 		while (nr_free_pages < freepages.high)
 		{
-			if (do_try_to_free_pages(GFP_KSWAPD))
+			if (do_try_to_free_pages(GFP_KSWAPD) && failed++ < 10)
 			{
 				if (tsk->need_resched)
 					schedule();

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)