]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] memory leak in current BK
authorAndrew Morton <akpm@zip.com.au>
Thu, 15 Aug 2002 13:40:14 +0000 (06:40 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 15 Aug 2002 13:40:14 +0000 (06:40 -0700)
Well I didn't test that very well.  __page_cache_release() is doing a
__free_page() on a zero-ref page, so __free_pages() sends the refcount
negative and doesn't free it.  With patch #8, page_cache_release()
almost never frees pages, but it must have been leaking a little bit.
Lucky it showed up.

This fixes it, and also adds a missing PageReserved test in put_page().
Which makes put_page() identical to page_cache_release(), but there are
header file woes.  I'll fix that up later.

include/linux/mm.h
mm/page_alloc.c
mm/swap.c

index 4d7de397481ff6c33232fb04c44ed95177c4cd48..c4395b9fe950028ef4e5d0a5b4be6465797b6fa6 100644 (file)
@@ -199,11 +199,12 @@ struct page {
 #define page_count(p)          atomic_read(&(p)->count)
 #define set_page_count(p,v)    atomic_set(&(p)->count, v)
 extern void FASTCALL(__page_cache_release(struct page *));
-#define put_page(p)                                    \
-       do {                                            \
-               if (put_page_testzero(p))               \
-                       __page_cache_release(p);        \
+#define put_page(p)                                                    \
+       do {                                                            \
+               if (!PageReserved(p) && put_page_testzero(p))           \
+                       __page_cache_release(p);                        \
        } while (0)
+void FASTCALL(__free_pages_ok(struct page *page, unsigned int order));
 
 /*
  * Multiple processes may "see" the same page. E.g. for untouched
index c8de0bcaa9f454ec82369cbc14ca843a6c75173c..4f8179b8f57d64d31982c36153b44d23ba37d4d1 100644 (file)
@@ -80,8 +80,7 @@ static inline int bad_range(zone_t *zone, struct page *page)
  * -- wli
  */
 
-static void FASTCALL(__free_pages_ok (struct page *page, unsigned int order));
-static void __free_pages_ok (struct page *page, unsigned int order)
+void __free_pages_ok (struct page *page, unsigned int order)
 {
        unsigned long index, page_idx, mask, flags;
        free_area_t *area;
index f9f7d4adaeec3a35fc04c08d2f1ffbca33ef1215..0e68f056b5adceba9c0c07f8abb81634656f0e7d 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -89,7 +89,7 @@ void __page_cache_release(struct page *page)
                        del_page_from_inactive_list(page);
                spin_unlock_irqrestore(&_pagemap_lru_lock, flags);
        }
-       __free_page(page);
+       __free_pages_ok(page, 0);
 }
 
 /*