patch for 2.1.51 kswapd -- please test

Bill Hawes (whawes@star.net)
Mon, 25 Aug 1997 12:10:37 -0400


This is a multi-part message in MIME format.
--------------1E72547193E6419E0EE08C19
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

It looks like the freeze problem reported by Mike Galbraith was caused
by kswapd endlessly looping, unable to make progress towards the
free_pages_high goal. Under some conditions try_to_free_page will cycle
through all of its operations without ever blocking, so that no other
tasks are able to run. Thus the system appears to be frozen, even
though it's really working very hard :-)

Since there's no way to determine the feasible limit for
free_pages_high, I've added some tests to kswapd to determine whether
progress is being made towards the goal, and to go back to sleep if it
fails after some number of iterations. In the event of a failure it
prints a message so that the user is aware of the problem (perhaps the
free_pages_high is set too high?) I've set the iteration count to 200,
which corresponds to a very large number of searches for freeable pages.

Please give the attached patch a try. It should prevent looping no
matter how high the free_pages_high value is set, and with reasonable
values for the freepages parameters you shouldn't see the warning
message.

Regards,
Bill
--------------1E72547193E6419E0EE08C19
Content-Type: text/plain; charset=us-ascii; name="kswapd_51-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="kswapd_51-patch"

--- mm/vmscan.c.old Thu Jul 24 17:36:08 1997
+++ mm/vmscan.c Mon Aug 25 11:38:27 1997
@@ -424,12 +424,15 @@
printk ("Starting kswapd v%.*s\n", i, s);
}

+#define MAX_SWAP_ITER 200
/*
* The background pageout daemon.
* Started as a kernel thread from the init process.
*/
int kswapd(void *unused)
{
+ int pages, last_pages, wait, iter;
+
current->session = 1;
current->pgrp = 1;
sprintf(current->comm, "kswapd");
@@ -464,10 +467,27 @@
*/
while(nr_free_pages < min_free_pages)
try_to_free_page(GFP_KERNEL, 0, 1);
- while((nr_free_pages + atomic_read(&nr_async_pages)) < free_pages_low)
- try_to_free_page(GFP_KERNEL, 0, 1);
- while((nr_free_pages + atomic_read(&nr_async_pages)) < free_pages_high)
- try_to_free_page(GFP_KERNEL, 0, 0);
+
+ last_pages = nr_free_pages;
+ for (iter = 0; iter++ < MAX_SWAP_ITER; ) {
+ pages = nr_free_pages + atomic_read(&nr_async_pages);
+ if (pages >= free_pages_high)
+ break;
+ wait = (pages < free_pages_low);
+ if (!try_to_free_page(GFP_KERNEL, 0, wait))
+ break;
+ /*
+ * Check whether we made progress toward our goal
+ */
+ if (nr_free_pages > last_pages) {
+ last_pages = nr_free_pages;
+ iter = 0;
+ }
+ }
+ if (pages < free_pages_high) {
+ printk("kswapd: failed after %d tries, got %d of %d\n",
+ iter, nr_free_pages, free_pages_high);
+ }
}
}

--------------1E72547193E6419E0EE08C19--