[another patch] Re: 2.0.31-pre5: Couldn't get a free page.....

Benjamin C R LaHaise (blah@dot.superaje.com)
Fri, 15 Aug 1997 01:32:38 +0000 ( )


On Thu, 14 Aug 1997, Dr. Werner Fink wrote:
...
> > I thought the MM changes had made these a thing of the past?

We can only hope.... And apply more patches!

> > Hmm, I have 64 128 512 in my /proc/sys/vm/freepages, do the
> > recent MM changes require Thomases 128 256 1024 in order to
> > perform as they were designed to?

Please try the below patch, but not with such high numbers... If you
get a couldn't get a free page, keep the first number low (say 8), and
increase the second and third numbers (to something like 8 64 96).
Failure of this to help means I'm smoking something strange in my
understanding of things! ;-)

> > Let me know if you want me to do further testing or if you
> > want more detailed information on my setup.
>
> A simple patch is appended to this mail. I hate it but it seems
> necessary for such a situation.

I saw a later posting mentioning that it didn't help :( Perhaps the
patch below does?

> Ahhh ... you should play lottery :-)

13 million to 1? Hey, and I though certain things in the kernel
were unlikely... Boy was I wrong!

> Linus, maybe is a good(?) idea always to return even if the freed
> page is a shared one ... or return if the priority is less than 4
> to avoid freeing by kswapd.

Hmmm.... Looking at the code, I've always thought the intention was
to reserve a certain number of pages for atomic/buffer allocation
above and beyond what normal GFP_KERNEL allocations can gather. Hence
the following patch - this way a few GFP_ATOMIC/BUFFER allocations will
succeed even after we've hit the low memory point, as I suspect the
couldn't get a free page errors are coming from interrupt allocations
right after we've hit min_free_pages.

This is untested, but I'm using it in my own 2.1 tree. I know we'd
rather like not to penalize GFP_KERNEL allocations as much, but it
seems to help when we're trying to swap out. Maybe free_pages_low
should be i*2 and free_pages_high i*3, with i having a minimum of
say 8.... or leave it at 24 - who can say? It works on my 8 meg machine - that's all.

The change in vmscan.c is important.

-ben

diff -u --recursive 2.0.30-pre6/mm/page_alloc.c linux/mm/page_alloc.c
--- 2.0.30-pre6/mm/page_alloc.c Thu Aug 14 21:13:53 1997
+++ linux/mm/page_alloc.c Thu Aug 14 21:08:59 1997
@@ -203,7 +203,9 @@
}
}
reserved_pages = 5;
- if (priority != GFP_NFS)
+ if (priority == GFP_KERNEL)
+ reserved_pages = free_pages_low;
+ else if (priority != GFP_NFS)
reserved_pages = min_free_pages;
save_flags(flags);
repeat:
@@ -264,11 +266,11 @@

/*
* select nr of pages we try to keep free for important stuff
- * with a minimum of 24 pages. This is totally arbitrary
+ * with a minimum of 16 pages. This is totally arbitrary
*/
i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7);
- if (i < 24)
- i = 24;
+ if (i < 16)
+ i = 16;
min_free_pages = i;
free_pages_low = i + (i>>1);
free_pages_high = i + i;
diff -u --recursive 2.0.30-pre6/mm/vmscan.c linux/mm/vmscan.c
--- 2.0.30-pre6/mm/vmscan.c Thu Aug 14 21:13:31 1997
+++ linux/mm/vmscan.c Thu Aug 14 21:12:49 1997
@@ -118,8 +118,10 @@
if (vma->vm_ops->swapout(vma, address - vma->vm_start + vma->vm_offset, page_table))
kill_proc(pid, SIGBUS, 1);
} else {
+#if 0 /* shared, dirty private mappings are legitimately swappable: see copy_one_pte */
if (page_map->count != 1)
return 0;
+#endif
if (!(entry = get_swap_page()))
return 0;
vma->vm_mm->rss--;