debug: check page refcount in __free_pages_ok()
Subsystems (2)
PATCH 25/27 debug: check page refcount in __free_pages_ok()
Add a BUG() check to __free_pages_ok() - to catch someone freeing a page which has a non-zero refcount. Actually, this check is mainly to catch someone (ie: shrink_cache()) incrementing a page's refcount shortly after it has been freed
Also clean up __free_pages_ok() a bit and convert lots of BUGs to BUG_ON.
page_alloc.c | 80 ++++++++++++++++++++++------------------------------------- 1 files changed, 30 insertions(+), 50 deletions(-)
mm/page_alloc.c renamed from mm/page_alloc.c~free-pages-check +30 -50
@@ -86,23 +86,24 @@ static void __free_pages_ok (struct pagestruct page *base;zone_t *zone; -if (PagePrivate (page)) -BUG (); -if (page->mapping) -BUG (); -if (PageLocked (page)) -BUG (); -if (PageLRU (page)) -BUG (); -if (PageActive (page)) -BUG (); -if (PageWriteback (page)) -BUG (); -ClearPageDirty (page); - -if (current->flags &PF_FREE_PAGES ) - goto local_freelist; - back_local_freelist: +BUG_ON (PagePrivate (page)); +BUG_ON (page->mapping !=NULL ); +BUG_ON (PageLocked (page)); +BUG_ON (PageLRU (page)); +BUG_ON (PageActive (page)); +BUG_ON (PageWriteback (page)); +if (PageDirty (page)) +ClearPageDirty (page); +BUG_ON (page_count (page) !=0 ); + +if (unlikely (current->flags &PF_FREE_PAGES )) { +if (!current->nr_local_pages && !in_interrupt ()) { +list_add (&page->list, ¤t->local_pages); + page->index = order; + current->nr_local_pages++; + goto out; + } + } zone =page_zone (page);
@@ -112,18 +113,14 @@ static void __free_pages_ok (struct pageif (page_idx & ~mask)BUG (); index = page_idx >> (1 + order); - area = zone->free_area + order;spin_lock_irqsave (&zone->lock, flags); - zone->free_pages -= mask; -while (mask + (1 << (MAX_ORDER -1 ))) {struct page *buddy1, *buddy2; -if (area >= zone->free_area +MAX_ORDER ) -BUG (); +BUG_ON (area >= zone->free_area +MAX_ORDER );if (!__test_and_change_bit (index, area->map))/* * the buddy page is still allocated.
@@ -136,11 +133,8 @@ static void __free_pages_ok (struct page*/ buddy1 = base + (page_idx ^ -mask); buddy2 = base + page_idx; -if (bad_range (zone, buddy1)) -BUG (); -if (bad_range (zone, buddy2)) -BUG (); - +BUG_ON (bad_range (zone, buddy1)); +BUG_ON (bad_range (zone, buddy2));list_del (&buddy1->list); mask <<=1 ; area++;
@@ -148,19 +142,9 @@ static void __free_pages_ok (struct page page_idx &= mask; }list_add (&(base + page_idx)->list, &area->free_list); -spin_unlock_irqrestore (&zone->lock, flags); +out:return ; - - local_freelist: -if (current->nr_local_pages) - goto back_local_freelist; -if (in_interrupt ()) - goto back_local_freelist; - -list_add (&page->list, ¤t->local_pages); - page->index = order; - current->nr_local_pages++; }#define MARK_USED (index, order, area) \
@@ -172,8 +156,7 @@ static inline struct page * expand (zoneunsigned long size =1 << high;while (high > low) { -if (bad_range (zone, page)) -BUG (); +BUG_ON (bad_range (zone, page)); area--; high--; size >>=1 ;
@@ -182,8 +165,7 @@ static inline struct page * expand (zone index += size; page += size; } -if (bad_range (zone, page)) -BUG (); +BUG_ON (bad_range (zone, page));return page; }
@@ -223,8 +205,7 @@ static struct page * rmqueue(zone_t *zonunsigned int index; page = list_entry(curr, struct page, list); -if (bad_range (zone, page)) -BUG (); +BUG_ON (bad_range (zone, page));list_del (curr); index = page - zone->zone_mem_map;if (curr_order !=MAX_ORDER -1 )
@@ -279,14 +260,14 @@ struct page *_alloc_pages(unsigned int g }#endif -static struct page *FASTCALL (balance_classzone (zone_t *,unsigned int ,unsigned int ,int *)); -static struct page *balance_classzone (zone_t * classzone,unsigned int gfp_mask,unsigned int order,int * freed) +static /* inline */ struct page * +balance_classzone (zone_t * classzone,unsigned int gfp_mask, +unsigned int order,int * freed) {struct page * page =NULL ;int __freed =0 ; -if (in_interrupt ()) -BUG (); +BUG_ON (in_interrupt ()); current->allocation_order = order; current->flags |=PF_MEMALLOC |PF_FREE_PAGES ;
@@ -793,8 +774,7 @@ void __init free_area_init_core(int nid,unsigned long totalpages, offset, realtotalpages;const unsigned long zone_required_alignment =1UL << (MAX_ORDER -1 ); -if (zone_start_paddr & ~PAGE_MASK ) -BUG (); +BUG_ON (zone_start_paddr & ~PAGE_MASK ); totalpages =0 ;for (i =0 ; i <MAX_NR_ZONES ; i++) {
-