[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <52259F09.30409@linux.vnet.ibm.com>
Date: Tue, 03 Sep 2013 14:04:17 +0530
From: "Srivatsa S. Bhat" <srivatsa.bhat@...ux.vnet.ibm.com>
To: Yasuaki Ishimatsu <isimatu.yasuaki@...fujitsu.com>
CC: akpm@...ux-foundation.org, mgorman@...e.de, hannes@...xchg.org,
tony.luck@...el.com, matthew.garrett@...ula.com, dave@...1.net,
riel@...hat.com, arjan@...ux.intel.com,
srinivas.pandruvada@...ux.intel.com, willy@...ux.intel.com,
kamezawa.hiroyu@...fujitsu.com, lenb@...nel.org, rjw@...k.pl,
gargankita@...il.com, paulmck@...ux.vnet.ibm.com,
svaidy@...ux.vnet.ibm.com, andi@...stfloor.org,
santosh.shilimkar@...com, kosaki.motohiro@...il.com,
linux-pm@...r.kernel.org, linux-mm@...ck.org,
linux-kernel@...r.kernel.org
Subject: Re: [RFC PATCH v3 06/35] mm: Add helpers to retrieve node region
and zone region for a given page
On 09/03/2013 11:26 AM, Yasuaki Ishimatsu wrote:
> (2013/08/30 22:15), Srivatsa S. Bhat wrote:
>> Given a page, we would like to have an efficient mechanism to find out
>> the node memory region and the zone memory region to which it belongs.
>>
>> Since the node is assumed to be divided into equal-sized node memory
>> regions, the node memory region can be obtained by simply right-shifting
>> the page's pfn by 'MEM_REGION_SHIFT'.
>>
>> But finding the corresponding zone memory region's index in the zone is
>> not that straight-forward. To have a O(1) algorithm to find it out,
>> define a
>> zone_region_idx[] array to store the zone memory region indices for every
>> node memory region.
>>
>> To illustrate, consider the following example:
>>
>> |<----------------------Node---------------------->|
>> __________________________________________________
>> | Node mem reg 0 | Node mem reg 1 | (Absolute
>> region
>> |________________________|_________________________| boundaries)
>>
>> __________________________________________________
>> | ZONE_DMA | ZONE_NORMAL |
>> | | |
>> |<--- ZMR 0 --->|<-ZMR0->|<-------- ZMR 1 -------->|
>> |_______________|________|_________________________|
>>
>>
>> In the above figure,
>>
>> Node mem region 0:
>> ------------------
>> This region corresponds to the first zone mem region in ZONE_DMA and also
>> the first zone mem region in ZONE_NORMAL. Hence its index array would
>> look
>> like this:
>> node_regions[0].zone_region_idx[ZONE_DMA] == 0
>> node_regions[0].zone_region_idx[ZONE_NORMAL] == 0
>>
>>
>> Node mem region 1:
>> ------------------
>> This region corresponds to the second zone mem region in ZONE_NORMAL.
>> Hence
>> its index array would look like this:
>> node_regions[1].zone_region_idx[ZONE_NORMAL] == 1
>>
>>
>> Using this index array, we can quickly obtain the zone memory region to
>> which a given page belongs.
>>
>> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@...ux.vnet.ibm.com>
>> ---
>>
>> include/linux/mm.h | 24 ++++++++++++++++++++++++
>> include/linux/mmzone.h | 7 +++++++
>> mm/page_alloc.c | 1 +
>> 3 files changed, 32 insertions(+)
>>
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index 18fdec4..52329d1 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -723,6 +723,30 @@ static inline struct zone *page_zone(const struct
>> page *page)
>> return
>> &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
>> }
>>
>> +static inline int page_node_region_id(const struct page *page,
>> + const pg_data_t *pgdat)
>> +{
>> + return (page_to_pfn(page) - pgdat->node_start_pfn) >>
>> MEM_REGION_SHIFT;
>> +}
>> +
>> +/**
>> + * Return the index of the zone memory region to which the page belongs.
>> + *
>> + * Given a page, find the absolute (node) memory region as well as
>> the zone to
>> + * which it belongs. Then find the region within the zone that
>> corresponds to
>> + * that node memory region, and return its index.
>> + */
>> +static inline int page_zone_region_id(const struct page *page)
>> +{
>> + pg_data_t *pgdat = NODE_DATA(page_to_nid(page));
>> + enum zone_type z_num = page_zonenum(page);
>> + unsigned long node_region_idx;
>> +
>> + node_region_idx = page_node_region_id(page, pgdat);
>> +
>> + return pgdat->node_regions[node_region_idx].zone_region_idx[z_num];
>> +}
>> +
>> #ifdef SECTION_IN_PAGE_FLAGS
>> static inline void set_page_section(struct page *page, unsigned long
>> section)
>> {
>> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
>> index 010ab5b..76d9ed2 100644
>> --- a/include/linux/mmzone.h
>> +++ b/include/linux/mmzone.h
>> @@ -726,6 +726,13 @@ struct node_mem_region {
>> unsigned long end_pfn;
>> unsigned long present_pages;
>> unsigned long spanned_pages;
>
>> +
>> + /*
>> + * A physical (node) region could be split across multiple zones.
>> + * Store the indices of the corresponding regions of each such
>> + * zone for this physical (node) region.
>> + */
>> + int zone_region_idx[MAX_NR_ZONES];
>
> You should initialize the zone_region_id[] as negative value.
Oh, I missed that.
> If the zone_region_id is initialized as 0, region 0 belongs to all zones.
>
In fact, if it is initialized as zero, every node region will appear to
map to every zone's first zone-mem-region. But luckily, since we never index
the zone_region_idx[] array with incorrect zone-number, I didn't encounter
any wrong values in practice. But thanks for pointing it out, I'll fix it.
Regards,
Srivatsa S. Bhat
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists