2004-06-25 22:04:14

by Andy Whitcroft

[permalink] [raw]
Subject: [PATCH] convert uses of ZONE_HIGHMEM to is_highmem

As the comments in mmzone.h indicate is_highmem() is designed to
reduce the proliferation of the constant ZONE_HIGHMEM. This patch
updates three references to ZONE_HIGHMEM to use is_highmem().
None appear to be on critical paths.

Revision: $Rev: 305 $

Signed-off-by: Andy Whitcroft <[email protected]>

---
arch/i386/mm/discontig.c | 17 +++++++++++------
mm/page_alloc.c | 9 +++++----
2 files changed, 16 insertions(+), 10 deletions(-)

diff -upN reference/arch/i386/mm/discontig.c current/arch/i386/mm/discontig.c
--- reference/arch/i386/mm/discontig.c 2004-06-25 22:26:08.000000000 +0100
+++ current/arch/i386/mm/discontig.c 2004-06-25 22:26:50.000000000 +0100
@@ -411,17 +411,22 @@ void __init zone_sizes_init(void)
void __init set_highmem_pages_init(int bad_ppro)
{
#ifdef CONFIG_HIGHMEM
- int nid;
+ struct zone *zone;

- for (nid = 0; nid < numnodes; nid++) {
+ for_each_zone(zone) {
unsigned long node_pfn, node_high_size, zone_start_pfn;
struct page * zone_mem_map;

- node_high_size = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].spanned_pages;
- zone_mem_map = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_mem_map;
- zone_start_pfn = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_start_pfn;
+ if (!is_highmem(zone))
+ continue;
+
+ printk("Initializing %s for node %d\n", zone->name,
+ zone->zone_pgdat->node_id);
+
+ node_high_size = zone->spanned_pages;
+ zone_mem_map = zone->zone_mem_map;
+ zone_start_pfn = zone->zone_start_pfn;

- printk("Initializing highpages for node %d\n", nid);
for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
one_highpage_init((struct page *)(zone_mem_map + node_pfn),
zone_start_pfn + node_pfn, bad_ppro);
diff -upN reference/mm/page_alloc.c current/mm/page_alloc.c
--- reference/mm/page_alloc.c 2004-06-25 22:26:08.000000000 +0100
+++ current/mm/page_alloc.c 2004-06-25 22:26:50.000000000 +0100
@@ -930,11 +930,12 @@ unsigned int nr_free_pagecache_pages(voi
#ifdef CONFIG_HIGHMEM
unsigned int nr_free_highpages (void)
{
- pg_data_t *pgdat;
+ struct zone *zone;
unsigned int pages = 0;

- for_each_pgdat(pgdat)
- pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
+ for_each_zone(zone)
+ if (is_highmem(zone))
+ pages += zone->free_pages;

return pages;
}
@@ -1422,7 +1423,7 @@ void __init memmap_init_zone(struct page
INIT_LIST_HEAD(&page->lru);
#ifdef WANT_PAGE_VIRTUAL
/* The shift won't overflow because ZONE_NORMAL is below 4G. */
- if (zone != ZONE_HIGHMEM)
+ if (!is_highmem(zone))
set_page_address(page, __va(start_pfn << PAGE_SHIFT));
#endif
start_pfn++;


2004-06-25 22:24:41

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] convert uses of ZONE_HIGHMEM to is_highmem

Andy Whitcroft <[email protected]> wrote:
>
> As the comments in mmzone.h indicate is_highmem() is designed to
> reduce the proliferation of the constant ZONE_HIGHMEM. This patch
> updates three references to ZONE_HIGHMEM to use is_highmem().
> None appear to be on critical paths.
>
> Revision: $Rev: 305 $
>
> void __init set_highmem_pages_init(int bad_ppro)
> {
> #ifdef CONFIG_HIGHMEM
> - int nid;
> + struct zone *zone;
>
> - for (nid = 0; nid < numnodes; nid++) {
> + for_each_zone(zone) {
> unsigned long node_pfn, node_high_size, zone_start_pfn;
> struct page * zone_mem_map;
>
> - node_high_size = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].spanned_pages;
> - zone_mem_map = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_mem_map;
> - zone_start_pfn = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_start_pfn;
> + if (!is_highmem(zone))
> + continue;
> +
> + printk("Initializing %s for node %d\n", zone->name,
> + zone->zone_pgdat->node_id);
> +
> + node_high_size = zone->spanned_pages;
> + zone_mem_map = zone->zone_mem_map;
> + zone_start_pfn = zone->zone_start_pfn;
>
> - printk("Initializing highpages for node %d\n", nid);
> for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
> one_highpage_init((struct page *)(zone_mem_map + node_pfn),
> zone_start_pfn + node_pfn, bad_ppro);

Fair enough.

> @@ -930,11 +930,12 @@ unsigned int nr_free_pagecache_pages(voi
> #ifdef CONFIG_HIGHMEM
> unsigned int nr_free_highpages (void)
> {
> - pg_data_t *pgdat;
> + struct zone *zone;
> unsigned int pages = 0;
>
> - for_each_pgdat(pgdat)
> - pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
> + for_each_zone(zone)
> + if (is_highmem(zone))
> + pages += zone->free_pages;

but that's slower.

2004-06-25 22:47:08

by Andy Whitcroft

[permalink] [raw]
Subject: Re: [PATCH] convert uses of ZONE_HIGHMEM to is_highmem

--On 25 June 2004 15:27 -0700 Andrew Morton <[email protected]> wrote:

> Andy Whitcroft <[email protected]> wrote:
>>
>> As the comments in mmzone.h indicate is_highmem() is designed to
>> reduce the proliferation of the constant ZONE_HIGHMEM. This patch
>> updates three references to ZONE_HIGHMEM to use is_highmem().
>> None appear to be on critical paths.
>>
>> Revision: $Rev: 305 $
>>
>> void __init set_highmem_pages_init(int bad_ppro)
>> {
>> # ifdef CONFIG_HIGHMEM
>> - int nid;
>> + struct zone *zone;
>>
>> - for (nid = 0; nid < numnodes; nid++) {
>> + for_each_zone(zone) {
>> unsigned long node_pfn, node_high_size, zone_start_pfn;
>> struct page * zone_mem_map;
>>
>> - node_high_size =
>> NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].spanned_pages; - zone_mem_map
>> = NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_mem_map; -
>> zone_start_pfn =
>> NODE_DATA(nid)->node_zones[ZONE_HIGHMEM].zone_start_pfn; + if
>> (!is_highmem(zone))
>> + continue;
>> +
>> + printk("Initializing %s for node %d\n", zone->name,
>> + zone->zone_pgdat->node_id);
>> +
>> + node_high_size = zone->spanned_pages;
>> + zone_mem_map = zone->zone_mem_map;
>> + zone_start_pfn = zone->zone_start_pfn;
>>
>> - printk("Initializing highpages for node %d\n", nid);
>> for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
>> one_highpage_init((struct page *)(zone_mem_map + node_pfn),
>> zone_start_pfn + node_pfn, bad_ppro);
>
> Fair enough.
>
>> @@ -930,11 +930,12 @@ unsigned int nr_free_pagecache_pages(voi
>> # ifdef CONFIG_HIGHMEM
>> unsigned int nr_free_highpages (void)
>> {
>> - pg_data_t *pgdat;
>> + struct zone *zone;
>> unsigned int pages = 0;
>>
>> - for_each_pgdat(pgdat)
>> - pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
>> + for_each_zone(zone)
>> + if (is_highmem(zone))
>> + pages += zone->free_pages;
>
> but that's slower.

Yes. Although I didn't think any of the users were particularly
performance critical. The routine counts the number of free pages in the
zones which count as highmem, ie memory not direct mapped into KVA. In
theory there could be more than one zone per node which was highmem,
ZONE_HIGHMEM is currently the only one.

I'll have a think if there is a more performant way to 'fix' that.

-apw