2006-12-19 03:01:38

by Aubrey Li

[permalink] [raw]
Subject: [RFC][PATCH] Fix area->nr_free-- went (-1) issue in buddy system

Hi all,

When I setup two zones (NORMAL and DMA) in my system, I got the
following wired result from /proc/buddyinfo.
-----------------------------------------------------------------------------------------
root:~> cat /proc/buddyinfo
Node 0, zone DMA 2 1 2 1 1 0 0
1 1 2 2 0 0 0
Node 0, zone Normal 1 1 1 1 1 1 0
0 4294967295 0 4294967295 2 0 0
-----------------------------------------------------------------------------------------

As you see, two area->nr_free went -1.

After dig into the code, I found the problem is in the fun
__free_one_page() when the kernel boot up call free_all_bootmem(). If
two zones setup, it's possible NORMAL zone merged a block whose order
=8 at the first time(this time zone[NORMA]->free_area[8].nr_free = 0)
and found its buddy in the DMA zone. So the two blocks will be merged
and area->nr_free went to -1.

My proposed patch is as follows:


Signed-off-by: Aubrey Li <[email protected]>
---------------------------------------------------------------------------------------------------
--- page_alloc.c.orig 2006-12-19 10:45:25.000000000 +0800
+++ page_alloc.c 2006-12-19 10:44:48.000000000 +0800
@@ -407,7 +407,8 @@ static inline void __free_one_page(struc

list_del(&buddy->lru);
area = zone->free_area + order;
- area->nr_free--;
+ if (area->nr_free > 0)
+ area->nr_free--;
rmv_page_order(buddy);
combined_idx = __find_combined_index(page_idx, order);
page = page + (combined_idx - page_idx);
----------------------------------------------------------------------------------------------------
Any comments?

Thanks,
-Aubrey


2006-12-19 04:43:04

by Nick Piggin

[permalink] [raw]
Subject: Re: [RFC][PATCH] Fix area->nr_free-- went (-1) issue in buddy system

Aubrey wrote:
> Hi all,
>
> When I setup two zones (NORMAL and DMA) in my system, I got the
> following wired result from /proc/buddyinfo.
> -----------------------------------------------------------------------------------------
>
> root:~> cat /proc/buddyinfo
> Node 0, zone DMA 2 1 2 1 1 0 0
> 1 1 2 2 0 0 0
> Node 0, zone Normal 1 1 1 1 1 1 0
> 0 4294967295 0 4294967295 2 0 0
> -----------------------------------------------------------------------------------------
>
>
> As you see, two area->nr_free went -1.
>
> After dig into the code, I found the problem is in the fun
> __free_one_page() when the kernel boot up call free_all_bootmem(). If
> two zones setup, it's possible NORMAL zone merged a block whose order
> =8 at the first time(this time zone[NORMA]->free_area[8].nr_free = 0)
> and found its buddy in the DMA zone. So the two blocks will be merged
> and area->nr_free went to -1.

This should not happen because the pages are checked to ensure they are
from the same zone before merging.

What kind of system do you have? What is the dmesg and the .config? It
could be that the zones are not properly aligned and CONFIG_HOLES_IN_ZONE
is not set.

--
SUSE Labs, Novell Inc.
Send instant messages to your online friends http://au.messenger.yahoo.com

2006-12-19 06:17:04

by Aubrey Li

[permalink] [raw]
Subject: Re: [RFC][PATCH] Fix area->nr_free-- went (-1) issue in buddy system

Hi Nick,

Thanks for your reply again, ;-).

On 12/19/06, Nick Piggin <[email protected]> wrote:
>
> This should not happen because the pages are checked to ensure they are
> from the same zone before merging.

How? page_is_buddy() only check if the buddy has the buddy flag and
has the same order.
Where can I find the same zone is checked?

>
> What kind of system do you have? What is the dmesg and the .config?

I'm using the blackfin uclinux. dmesg and .config is attached.

> It could be that the zones are not properly aligned and CONFIG_HOLES_IN_ZONE
> is not set.

I changed the code in paging_init(), see below:
-----------------------------------------
#if 0
zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
zones_size[ZONE_NORMAL] = 0;
#else
zones_size[ZONE_DMA] = (end_mem/2 - PAGE_OFFSET) >> PAGE_SHIFT;
zones_size[ZONE_NORMAL] = (end_mem/2 - PAGE_OFFSET) >>
PAGE_SHIFT;
#endif
-----------------------------------------
This is only what I did the change. I also suspect the zones are not
properly aligned, But how to align it? I think our system doesn't need
CONFIG_HOLES_IN_ZONE.

Thanks,
-Aubrey


Attachments:
(No filename) (1.17 kB)
dmesg.txt (3.24 kB)
kerne.config (17.59 kB)
Download all attachments

2006-12-19 06:35:17

by Nick Piggin

[permalink] [raw]
Subject: Re: [RFC][PATCH] Fix area->nr_free-- went (-1) issue in buddy system

Hi Aubery!

Aubrey wrote:
> Hi Nick,
>
> Thanks for your reply again, ;-).
>
> On 12/19/06, Nick Piggin <[email protected]> wrote:
>
>>
>> This should not happen because the pages are checked to ensure they are
>> from the same zone before merging.
>
>
> How? page_is_buddy() only check if the buddy has the buddy flag and
> has the same order.
> Where can I find the same zone is checked?

Ah OK, you're using 2.6.16? Later kernels have a check for this. I
guess you could backport it?

>
>>
>> What kind of system do you have? What is the dmesg and the .config?
>
>
> I'm using the blackfin uclinux. dmesg and .config is attached.
>
>> It could be that the zones are not properly aligned and
>> CONFIG_HOLES_IN_ZONE
>> is not set.
>
>
> I changed the code in paging_init(), see below:
> -----------------------------------------
> #if 0
> zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >>
> PAGE_SHIFT;
> zones_size[ZONE_NORMAL] = 0;
> #else
> zones_size[ZONE_DMA] = (end_mem/2 - PAGE_OFFSET) >>
> PAGE_SHIFT;
> zones_size[ZONE_NORMAL] = (end_mem/2 - PAGE_OFFSET) >>
> PAGE_SHIFT;
> #endif
> -----------------------------------------
> This is only what I did the change. I also suspect the zones are not
> properly aligned, But how to align it? I think our system doesn't need
> CONFIG_HOLES_IN_ZONE.

That's right. I guess you can either align your zone sizes (must be
aligned to MAX_ORDER size), or add the zone check in page_is_buddy.

Hope that works.

Nick

--
SUSE Labs, Novell Inc.
Send instant messages to your online friends http://au.messenger.yahoo.com

2006-12-19 07:41:16

by Aubrey Li

[permalink] [raw]
Subject: Re: [RFC][PATCH] Fix area->nr_free-- went (-1) issue in buddy system

On 12/19/06, Nick Piggin <[email protected]> wrote:
> Hi Aubery!
>
> That's right. I guess you can either align your zone sizes (must be
> aligned to MAX_ORDER size), or add the zone check in page_is_buddy.
>
Adding the zone check in page_is_buddy fix the problem.
Thanks again, :)

-Aubrey