From: Mel Gorman Date: Mon, 28 Apr 2008 09:12:14 +0000 (-0700) Subject: mm: introduce node_zonelist() for accessing the zonelist for a GFP mask X-Git-Tag: v2.6.26-rc1~1000 X-Git-Url: http://ftp.safe.ca/?p=safe%2Fjmp%2Flinux-2.6;a=commitdiff_plain;h=0e88460da6ab7bb6a7ef83675412ed5b6315d741 mm: introduce node_zonelist() for accessing the zonelist for a GFP mask Introduce a node_zonelist() helper function. It is used to lookup the appropriate zonelist given a node and a GFP mask. The patch on its own is a cleanup but it helps clarify parts of the two-zonelist-per-node patchset. If necessary, it can be merged with the next patch in this set without problems. Reviewed-by: Christoph Lameter Signed-off-by: Mel Gorman Signed-off-by: Lee Schermerhorn Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Christoph Lameter Cc: Hugh Dickins Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index de60e1e..1ade193 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -271,8 +271,7 @@ static struct sysrq_key_op sysrq_term_op = { static void moom_callback(struct work_struct *ignored) { - out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], - GFP_KERNEL, 0); + out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0); } static DECLARE_WORK(moom_work, moom_callback); diff --git a/fs/buffer.c b/fs/buffer.c index 1dae94a..7135849 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -361,13 +361,13 @@ void invalidate_bdev(struct block_device *bdev) static void free_more_memory(void) { struct zonelist *zonelist; - pg_data_t *pgdat; + int nid; wakeup_pdflush(1024); yield(); - for_each_online_pgdat(pgdat) { - zonelist = &pgdat->node_zonelists[gfp_zone(GFP_NOFS)]; + for_each_online_node(nid) { + zonelist = node_zonelist(nid, GFP_NOFS); if (zonelist->zones[0]) try_to_free_pages(zonelist, 0, GFP_NOFS); } diff --git a/include/linux/gfp.h b/include/linux/gfp.h index c17ba49..e865d51 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -154,10 +154,15 @@ static inline enum zone_type gfp_zone(gfp_t flags) /* * We get the zone list from the current node and the gfp_mask. * This zone list contains a maximum of MAXNODES*MAX_NR_ZONES zones. + * There are many zonelists per node, two for each active zone. * * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets * optimized to &contig_page_data at compile-time. */ +static inline struct zonelist *node_zonelist(int nid, gfp_t flags) +{ + return NODE_DATA(nid)->node_zonelists + gfp_zone(flags); +} #ifndef HAVE_ARCH_FREE_PAGE static inline void arch_free_page(struct page *page, int order) { } @@ -178,8 +183,7 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, if (nid < 0) nid = numa_node_id(); - return __alloc_pages(gfp_mask, order, - NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask)); + return __alloc_pages(gfp_mask, order, node_zonelist(nid, gfp_mask)); } #ifdef CONFIG_NUMA diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 59c4865..69160dc 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -241,7 +241,7 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p) static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol) { - return NODE_DATA(0)->node_zonelists + gfp_zone(gfp_flags); + return node_zonelist(0, gfp_flags); } static inline int do_migrate_pages(struct mm_struct *mm, diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 3c36011..5d20bf4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1183,7 +1183,7 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) nd = 0; BUG(); } - return NODE_DATA(nd)->node_zonelists + gfp_zone(gfp); + return node_zonelist(nd, gfp); } /* Do dynamic interleaving for a process */ @@ -1299,7 +1299,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, if (unlikely(pol != &default_policy && pol != current->mempolicy)) __mpol_free(pol); /* finished with pol */ - return NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_flags); + return node_zonelist(nid, gfp_flags); } zl = zonelist_policy(GFP_HIGHUSER, pol); @@ -1321,7 +1321,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, struct zonelist *zl; struct page *page; - zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp); + zl = node_zonelist(nid, gfp); page = __alloc_pages(gfp, order, zl); if (page && page_zone(page) == zl->zones[0]) inc_zone_page_state(page, NUMA_INTERLEAVE_HIT); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 1bda771..63ff718 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1713,10 +1713,9 @@ EXPORT_SYMBOL(free_pages); static unsigned int nr_free_zone_pages(int offset) { /* Just pick one node, since fallback list is circular */ - pg_data_t *pgdat = NODE_DATA(numa_node_id()); unsigned int sum = 0; - struct zonelist *zonelist = pgdat->node_zonelists + offset; + struct zonelist *zonelist = node_zonelist(numa_node_id(), GFP_KERNEL); struct zone **zonep = zonelist->zones; struct zone *zone; diff --git a/mm/slab.c b/mm/slab.c index 03927cb..5488c54 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3249,8 +3249,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) if (flags & __GFP_THISNODE) return NULL; - zonelist = &NODE_DATA(slab_node(current->mempolicy)) - ->node_zonelists[gfp_zone(flags)]; + zonelist = node_zonelist(slab_node(current->mempolicy), flags); local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); retry: diff --git a/mm/slub.c b/mm/slub.c index 39592b5..19ebbfb 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1309,8 +1309,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags) get_cycles() % 1024 > s->remote_node_defrag_ratio) return NULL; - zonelist = &NODE_DATA( - slab_node(current->mempolicy))->node_zonelists[gfp_zone(flags)]; + zonelist = node_zonelist(slab_node(current->mempolicy), flags); for (z = zonelist->zones; *z; z++) { struct kmem_cache_node *n;