Re: [RFC][PATCH 1/3] radix priority search tree - objrmap complexity fix

Andrea Arcangeli
2004-04-03T15:59:58Z

On Sat, Apr 03, 2004 at 05:20:26PM +0200, Andrea Arcangeli wrote:
> if you want you can give a spin to this patch. As far as the old code
> worked (i.e. with hugetlbfs=n) this should work too, since it disables
> the compound feature completely, but if it works it probably only hides
> the real bug. You can use rc3-aa3 for this (it already has the latest
> robustness fixes I posted to you)
>
> --- x/mm/page_alloc.c.~1~ 2004-04-02 20:37:14.000000000 +0200
> +++ x/mm/page_alloc.c 2004-04-03 17:15:52.647449336 +0200
> @@ -563,7 +563,9 @@ __alloc_pages(unsigned int gfp_mask, uns
> cold = 0;
> if (gfp_mask & __GFP_COLD)
> cold = __GFP_COLD;
> +#if 0
> if (gfp_mask & __GFP_NO_COMP)
> +#endif
> cold |= __GFP_NO_COMP;
>
> zones = zonelist->zones; /* the list of zones suitable for gfp_mask */

I've written another piece of debugging code for you, this is also to
apply on top of rc3-aa3, but of course not at the same time as the above
one. The above one disables compound compeltely, while the below one is
trying to debug what's going wrong in compound.

Basically I store a backup copy of page->private into page->mapping
(arch is 32bit so they're the same size). we know for sure you're not
going to map into userspace those order >0 pages since hugetlbfs is off,
so reusing mapcount as a backup copy of page->private for compound pages
should be ok.

this way when we get the screwed page->private we see what's going on,
and if page->mapping is still pointing to 'page'. If page->mapping ==
page at least we know it's only page->private being corrupt. I don't
really see how can ppc32 corrupt page->private though.

--- x-debug/mm/page_alloc.c.~1~ 2004-04-02 20:37:14.000000000 +0200
+++ x-debug/mm/page_alloc.c 2004-04-03 17:55:16.629069504 +0200
@@ -122,6 +122,7 @@ static void prep_compound_page(struct pa

SetPageCompound(p);
p->private = (unsigned long)page;
+ p->mapcount = (unsigned int)page; /* works 32bit only */
}
}

@@ -130,16 +131,30 @@ static void destroy_compound_page(struct
int i;
int nr_pages = 1 << order;

- if (page[1].index != order)
+ if (page[1].index != order) {
+ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
bad_page(__FUNCTION__, page);
+ }
+ if ((unsigned long) page != page->private || page->private != page->mapcount) {
+ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+ printk("private %lx real %x page %p\n", page->private, page->mapcount, page);
+ bad_page(__FUNCTION__, page);
+ }

for (i = 0; i < nr_pages; i++) {
struct page *p = page + i;

- if (!PageCompound(p))
+ if (!PageCompound(p)) {
+ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+ printk("index %d\n", i);
bad_page(__FUNCTION__, p);
- if (p->private != (unsigned long)page)
+ }
+ if (p->private != (unsigned long)page || p->private != p->mapcount) {
+ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
+ printk("index %d private %lx real %x page %p\n", i, p->private, p->mapcount, page);
bad_page(__FUNCTION__, p);
+
+ }
ClearPageCompound(p);
}
}
@@ -211,7 +226,6 @@ static inline void __free_pages_bulk (st
static inline void free_pages_check(const char *function, struct page *page)
{
if ( page->mapping != NULL ||
- page->mapcount ||
page_count(page) != 0 ||
(page->flags & (
1 << PG_lru |
@@ -316,7 +330,6 @@ static void prep_new_page(struct page *
struct page * page = _page + i;

if (page->mapping ||
- page->mapcount ||
(page->flags & (
1 << PG_private |
1 << PG_locked |
@@ -336,6 +349,7 @@ static void prep_new_page(struct page *
1 << PG_checked | 1 << PG_mappedtodisk |
1 << PG_compound);
page->private = 0;
+ page->mapcount = 0;
set_page_count(page, 1);
}
}