Re: [RFC PATCH v3 06/35] mm: Add helpers to retrieve node region and zone region for a given page

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxxxx>
>> ---
>>
>>   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, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]