Hi,
the patch below fixes a bug in the OOM killer where the killer
could kick in if the system is out of swap (or has no swap), is
not out of memory yet but simply has a hard time with the cache.
The solution is to test against page_cache.min_percent +
buffer_cache.min_percent, this way we:
1) don't oom_kill() anything if we still have enough memory
left
2) will run oom_kill() BEFORE the system really starts
thrashing so badly that it'll never reach oom_kill()
because of the thrashing
Of course, to implement this we have to count the number of
swapcache pages, but that's a 2-liner ;)
Please apply for the next (pre) kernel.
regards,
Rik
--
Executive summary of a recent Microsoft press release:
"we are concerned about the GNU General Public License (GPL)"
http://www.surriel.com/
http://www.conectiva.com/ http://distro.conectiva.com/
--- linux-2.4.6/mm/oom_kill.c.orig Fri Jul 6 17:32:58 2001
+++ linux-2.4.6/mm/oom_kill.c Fri Jul 6 18:15:59 2001
@@ -191,11 +191,28 @@
*/
int out_of_memory(void)
{
+ long cache_mem, limit;
+
/* Enough free memory? Not OOM. */
if (nr_free_pages() > freepages.min)
return 0;
if (nr_free_pages() + nr_inactive_clean_pages() > freepages.low)
+ return 0;
+
+ /*
+ * If the buffer and page cache (excluding swap cache) are over
+ * their (/proc tunable) minimum, we're still not OOM. We test
+ * this to make sure we don't return OOM when the system simply
+ * has a hard time with the cache.
+ */
+ cache_mem = atomic_read(&page_cache_size);
+ cache_mem += atomic_read(&buffermem_pages);
+ cache_mem -= atomic_read(&nr_swapcache_pages);
+ limit = (page_cache.min_percent + buffer_mem.min_percent);
+ limit *= num_physpages / 100;
+
+ if (cache_mem > limit)
return 0;
/* Enough swap space left? Not OOM. */
--- linux-2.4.6/mm/swap_state.c.orig Fri Jul 6 17:32:58 2001
+++ linux-2.4.6/mm/swap_state.c Fri Jul 6 17:34:59 2001
@@ -51,6 +51,8 @@
&swap_aops,
};
+atomic_t nr_swapcache_pages = ATOMIC_INIT(0);
+
#ifdef SWAP_CACHE_INFO
unsigned long swap_cache_add_total;
unsigned long swap_cache_del_total;
@@ -82,6 +84,7 @@
flags = page->flags & ~((1 << PG_error) | (1 << PG_arch_1));
page->flags = flags | (1 << PG_uptodate);
add_to_page_cache_locked(page, &swapper_space, entry.val);
+ atomic_inc(&nr_swapcache_pages);
}
static inline void remove_from_swap_cache(struct page *page)
@@ -96,6 +99,7 @@
PageClearSwapCache(page);
ClearPageDirty(page);
__remove_inode_page(page);
+ atomic_dec(&nr_swapcache_pages);
}
/*
--- linux-2.4.6/include/linux/swap.h.orig Fri Jul 6 17:33:07 2001
+++ linux-2.4.6/include/linux/swap.h Fri Jul 6 17:33:34 2001
@@ -70,6 +70,7 @@
extern int nr_active_pages;
extern int nr_inactive_dirty_pages;
extern atomic_t nr_async_pages;
+extern atomic_t nr_swapcache_pages;
extern struct address_space swapper_space;
extern atomic_t page_cache_size;
extern atomic_t buffermem_pages;
On Fri, 6 Jul 2001, Rik van Riel wrote:
>
> Of course, to implement this we have to count the number of
> swapcache pages, but that's a 2-liner ;)
swapper_space.nrpages already counts that (as Andrea once pointed out),
no need to add your nr_swapcache_pages.
Hugh
On Fri, 6 Jul 2001, Hugh Dickins wrote:
> On Fri, 6 Jul 2001, Rik van Riel wrote:
> >
> > Of course, to implement this we have to count the number of
> > swapcache pages, but that's a 2-liner ;)
>
> swapper_space.nrpages already counts that (as Andrea once
> pointed out), no need to add your nr_swapcache_pages.
Whoops, indeed...
Rik
--
Executive summary of a recent Microsoft press release:
"we are concerned about the GNU General Public License (GPL)"
http://www.surriel.com/
http://www.conectiva.com/ http://distro.conectiva.com/