aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mempolicy.c
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2008-04-28 05:12:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:18 -0400
commitdd1a239f6f2d4d3eedd318583ec319aa145b324c (patch)
treeaff4224c96b5e2e67588c3946858a724863eeaf9 /mm/mempolicy.c
parent54a6eb5c4765aa573a030ceeba2c14e3d2ea5706 (diff)
mm: have zonelist contains structs with both a zone pointer and zone_idx
Filtering zonelists requires very frequent use of zone_idx(). This is costly as it involves a lookup of another structure and a substraction operation. As the zone_idx is often required, it should be quickly accessible. The node idx could also be stored here if it was found that accessing zone->node is significant which may be the case on workloads where nodemasks are heavily used. This patch introduces a struct zoneref to store a zone pointer and a zone index. The zonelist then consists of an array of these struct zonerefs which are looked up as necessary. Helpers are given for accessing the zone index as well as the node index. [kamezawa.hiroyu@jp.fujitsu.com: Suggested struct zoneref instead of embedding information in pointers] [hugh@veritas.com: mm-have-zonelist: fix memcg ooms] [hugh@veritas.com: just return do_try_to_free_pages] [hugh@veritas.com: do_try_to_free_pages gfp_mask redundant] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Christoph Lameter <clameter@sgi.com> Acked-by: David Rientjes <rientjes@google.com> Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Christoph Lameter <clameter@sgi.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r--mm/mempolicy.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 5d20bf44062f..90193a2a915b 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -186,7 +186,7 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
186 for_each_node_mask(nd, *nodes) { 186 for_each_node_mask(nd, *nodes) {
187 struct zone *z = &NODE_DATA(nd)->node_zones[k]; 187 struct zone *z = &NODE_DATA(nd)->node_zones[k];
188 if (z->present_pages > 0) 188 if (z->present_pages > 0)
189 zl->zones[num++] = z; 189 zoneref_set_zone(z, &zl->_zonerefs[num++]);
190 } 190 }
191 if (k == 0) 191 if (k == 0)
192 break; 192 break;
@@ -196,7 +196,8 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
196 kfree(zl); 196 kfree(zl);
197 return ERR_PTR(-EINVAL); 197 return ERR_PTR(-EINVAL);
198 } 198 }
199 zl->zones[num] = NULL; 199 zl->_zonerefs[num].zone = NULL;
200 zl->_zonerefs[num].zone_idx = 0;
200 return zl; 201 return zl;
201} 202}
202 203
@@ -504,9 +505,11 @@ static void get_zonemask(struct mempolicy *p, nodemask_t *nodes)
504 nodes_clear(*nodes); 505 nodes_clear(*nodes);
505 switch (p->policy) { 506 switch (p->policy) {
506 case MPOL_BIND: 507 case MPOL_BIND:
507 for (i = 0; p->v.zonelist->zones[i]; i++) 508 for (i = 0; p->v.zonelist->_zonerefs[i].zone; i++) {
508 node_set(zone_to_nid(p->v.zonelist->zones[i]), 509 struct zoneref *zref;
509 *nodes); 510 zref = &p->v.zonelist->_zonerefs[i];
511 node_set(zonelist_node_idx(zref), *nodes);
512 }
510 break; 513 break;
511 case MPOL_DEFAULT: 514 case MPOL_DEFAULT:
512 break; 515 break;
@@ -1212,12 +1215,13 @@ unsigned slab_node(struct mempolicy *policy)
1212 case MPOL_INTERLEAVE: 1215 case MPOL_INTERLEAVE:
1213 return interleave_nodes(policy); 1216 return interleave_nodes(policy);
1214 1217
1215 case MPOL_BIND: 1218 case MPOL_BIND: {
1216 /* 1219 /*
1217 * Follow bind policy behavior and start allocation at the 1220 * Follow bind policy behavior and start allocation at the
1218 * first node. 1221 * first node.
1219 */ 1222 */
1220 return zone_to_nid(policy->v.zonelist->zones[0]); 1223 return zonelist_node_idx(policy->v.zonelist->_zonerefs);
1224 }
1221 1225
1222 case MPOL_PREFERRED: 1226 case MPOL_PREFERRED:
1223 if (policy->v.preferred_node >= 0) 1227 if (policy->v.preferred_node >= 0)
@@ -1323,7 +1327,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
1323 1327
1324 zl = node_zonelist(nid, gfp); 1328 zl = node_zonelist(nid, gfp);
1325 page = __alloc_pages(gfp, order, zl); 1329 page = __alloc_pages(gfp, order, zl);
1326 if (page && page_zone(page) == zl->zones[0]) 1330 if (page && page_zone(page) == zonelist_zone(&zl->_zonerefs[0]))
1327 inc_zone_page_state(page, NUMA_INTERLEAVE_HIT); 1331 inc_zone_page_state(page, NUMA_INTERLEAVE_HIT);
1328 return page; 1332 return page;
1329} 1333}
@@ -1463,10 +1467,14 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b)
1463 return a->v.preferred_node == b->v.preferred_node; 1467 return a->v.preferred_node == b->v.preferred_node;
1464 case MPOL_BIND: { 1468 case MPOL_BIND: {
1465 int i; 1469 int i;
1466 for (i = 0; a->v.zonelist->zones[i]; i++) 1470 for (i = 0; a->v.zonelist->_zonerefs[i].zone; i++) {
1467 if (a->v.zonelist->zones[i] != b->v.zonelist->zones[i]) 1471 struct zone *za, *zb;
1472 za = zonelist_zone(&a->v.zonelist->_zonerefs[i]);
1473 zb = zonelist_zone(&b->v.zonelist->_zonerefs[i]);
1474 if (za != zb)
1468 return 0; 1475 return 0;
1469 return b->v.zonelist->zones[i] == NULL; 1476 }
1477 return b->v.zonelist->_zonerefs[i].zone == NULL;
1470 } 1478 }
1471 default: 1479 default:
1472 BUG(); 1480 BUG();
@@ -1785,12 +1793,12 @@ static void mpol_rebind_policy(struct mempolicy *pol,
1785 break; 1793 break;
1786 case MPOL_BIND: { 1794 case MPOL_BIND: {
1787 nodemask_t nodes; 1795 nodemask_t nodes;
1788 struct zone **z; 1796 struct zoneref *z;
1789 struct zonelist *zonelist; 1797 struct zonelist *zonelist;
1790 1798
1791 nodes_clear(nodes); 1799 nodes_clear(nodes);
1792 for (z = pol->v.zonelist->zones; *z; z++) 1800 for (z = pol->v.zonelist->_zonerefs; z->zone; z++)
1793 node_set(zone_to_nid(*z), nodes); 1801 node_set(zonelist_node_idx(z), nodes);
1794 nodes_remap(tmp, nodes, *mpolmask, *newmask); 1802 nodes_remap(tmp, nodes, *mpolmask, *newmask);
1795 nodes = tmp; 1803 nodes = tmp;
1796 1804