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>