Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mel Gorman and committed by
Linus Torvalds
dd1a239f 54a6eb5c

+158 -100
+1 -1
arch/parisc/mm/init.c
··· 608 608 for (i = 0; i < npmem_ranges; i++) { 609 609 zl = node_zonelist(i); 610 610 for (j = 0; j < MAX_NR_ZONES; j++) { 611 - struct zone **z; 611 + struct zoneref *z; 612 612 struct zone *zone; 613 613 614 614 printk("Zone list for zone %d on node %d: ", j, i);
+3 -3
fs/buffer.c
··· 360 360 */ 361 361 static void free_more_memory(void) 362 362 { 363 - struct zone **zones; 363 + struct zoneref *zrefs; 364 364 int nid; 365 365 366 366 wakeup_pdflush(1024); 367 367 yield(); 368 368 369 369 for_each_online_node(nid) { 370 - zones = first_zones_zonelist(node_zonelist(nid, GFP_NOFS), 370 + zrefs = first_zones_zonelist(node_zonelist(nid, GFP_NOFS), 371 371 gfp_zone(GFP_NOFS)); 372 - if (*zones) 372 + if (zrefs->zone) 373 373 try_to_free_pages(node_zonelist(nid, GFP_NOFS), 0, 374 374 GFP_NOFS); 375 375 }
+54 -10
include/linux/mmzone.h
··· 469 469 #endif 470 470 471 471 /* 472 + * This struct contains information about a zone in a zonelist. It is stored 473 + * here to avoid dereferences into large structures and lookups of tables 474 + */ 475 + struct zoneref { 476 + struct zone *zone; /* Pointer to actual zone */ 477 + int zone_idx; /* zone_idx(zoneref->zone) */ 478 + }; 479 + 480 + /* 472 481 * One allocation request operates on a zonelist. A zonelist 473 482 * is a list of zones, the first one is the 'goal' of the 474 483 * allocation, the other zones are fallback zones, in decreasing ··· 485 476 * 486 477 * If zlcache_ptr is not NULL, then it is just the address of zlcache, 487 478 * as explained above. If zlcache_ptr is NULL, there is no zlcache. 479 + * * 480 + * To speed the reading of the zonelist, the zonerefs contain the zone index 481 + * of the entry being read. Helper functions to access information given 482 + * a struct zoneref are 483 + * 484 + * zonelist_zone() - Return the struct zone * for an entry in _zonerefs 485 + * zonelist_zone_idx() - Return the index of the zone for an entry 486 + * zonelist_node_idx() - Return the index of the node for an entry 488 487 */ 489 - 490 488 struct zonelist { 491 489 struct zonelist_cache *zlcache_ptr; // NULL or &zlcache 492 - struct zone *zones[MAX_ZONES_PER_ZONELIST + 1]; // NULL delimited 490 + struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1]; 493 491 #ifdef CONFIG_NUMA 494 492 struct zonelist_cache zlcache; // optional ... 495 493 #endif ··· 729 713 zone; \ 730 714 zone = next_zone(zone)) 731 715 716 + static inline struct zone *zonelist_zone(struct zoneref *zoneref) 717 + { 718 + return zoneref->zone; 719 + } 720 + 721 + static inline int zonelist_zone_idx(struct zoneref *zoneref) 722 + { 723 + return zoneref->zone_idx; 724 + } 725 + 726 + static inline int zonelist_node_idx(struct zoneref *zoneref) 727 + { 728 + #ifdef CONFIG_NUMA 729 + /* zone_to_nid not available in this context */ 730 + return zoneref->zone->node; 731 + #else 732 + return 0; 733 + #endif /* CONFIG_NUMA */ 734 + } 735 + 736 + static inline void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref) 737 + { 738 + zoneref->zone = zone; 739 + zoneref->zone_idx = zone_idx(zone); 740 + } 741 + 732 742 /* Returns the first zone at or below highest_zoneidx in a zonelist */ 733 - static inline struct zone **first_zones_zonelist(struct zonelist *zonelist, 743 + static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist, 734 744 enum zone_type highest_zoneidx) 735 745 { 736 - struct zone **z; 746 + struct zoneref *z; 737 747 738 748 /* Find the first suitable zone to use for the allocation */ 739 - z = zonelist->zones; 740 - while (*z && zone_idx(*z) > highest_zoneidx) 749 + z = zonelist->_zonerefs; 750 + while (zonelist_zone_idx(z) > highest_zoneidx) 741 751 z++; 742 752 743 753 return z; 744 754 } 745 755 746 756 /* Returns the next zone at or below highest_zoneidx in a zonelist */ 747 - static inline struct zone **next_zones_zonelist(struct zone **z, 757 + static inline struct zoneref *next_zones_zonelist(struct zoneref *z, 748 758 enum zone_type highest_zoneidx) 749 759 { 750 760 /* Find the next suitable zone to use for the allocation */ 751 - while (*z && zone_idx(*z) > highest_zoneidx) 761 + while (zonelist_zone_idx(z) > highest_zoneidx) 752 762 z++; 753 763 754 764 return z; ··· 790 748 * This iterator iterates though all zones at or below a given zone index. 791 749 */ 792 750 #define for_each_zone_zonelist(zone, z, zlist, highidx) \ 793 - for (z = first_zones_zonelist(zlist, highidx), zone = *z++; \ 751 + for (z = first_zones_zonelist(zlist, highidx), \ 752 + zone = zonelist_zone(z++); \ 794 753 zone; \ 795 - z = next_zones_zonelist(z, highidx), zone = *z++) 754 + z = next_zones_zonelist(z, highidx), \ 755 + zone = zonelist_zone(z++)) 796 756 797 757 #ifdef CONFIG_SPARSEMEM 798 758 #include <asm/sparsemem.h>
+2 -2
include/linux/oom.h
··· 23 23 CONSTRAINT_MEMORY_POLICY, 24 24 }; 25 25 26 - extern int try_set_zone_oom(struct zonelist *zonelist); 27 - extern void clear_zonelist_oom(struct zonelist *zonelist); 26 + extern int try_set_zone_oom(struct zonelist *zonelist, gfp_t gfp_flags); 27 + extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); 28 28 29 29 extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order); 30 30 extern int register_oom_notifier(struct notifier_block *nb);
+2 -2
kernel/cpuset.c
··· 1967 1967 { 1968 1968 int i; 1969 1969 1970 - for (i = 0; zl->zones[i]; i++) { 1971 - int nid = zone_to_nid(zl->zones[i]); 1970 + for (i = 0; zl->_zonerefs[i].zone; i++) { 1971 + int nid = zonelist_node_idx(&zl->_zonerefs[i]); 1972 1972 1973 1973 if (node_isset(nid, current->mems_allowed)) 1974 1974 return 1;
+2 -1
mm/hugetlb.c
··· 97 97 struct mempolicy *mpol; 98 98 struct zonelist *zonelist = huge_zonelist(vma, address, 99 99 htlb_alloc_mask, &mpol); 100 - struct zone *zone, **z; 100 + struct zone *zone; 101 + struct zoneref *z; 101 102 102 103 for_each_zone_zonelist(zone, z, zonelist, MAX_NR_ZONES - 1) { 103 104 nid = zone_to_nid(zone);
+22 -14
mm/mempolicy.c
··· 186 186 for_each_node_mask(nd, *nodes) { 187 187 struct zone *z = &NODE_DATA(nd)->node_zones[k]; 188 188 if (z->present_pages > 0) 189 - zl->zones[num++] = z; 189 + zoneref_set_zone(z, &zl->_zonerefs[num++]); 190 190 } 191 191 if (k == 0) 192 192 break; ··· 196 196 kfree(zl); 197 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 201 return zl; 201 202 } 202 203 ··· 505 504 nodes_clear(*nodes); 506 505 switch (p->policy) { 507 506 case MPOL_BIND: 508 - for (i = 0; p->v.zonelist->zones[i]; i++) 509 - node_set(zone_to_nid(p->v.zonelist->zones[i]), 510 - *nodes); 507 + for (i = 0; p->v.zonelist->_zonerefs[i].zone; i++) { 508 + struct zoneref *zref; 509 + zref = &p->v.zonelist->_zonerefs[i]; 510 + node_set(zonelist_node_idx(zref), *nodes); 511 + } 511 512 break; 512 513 case MPOL_DEFAULT: 513 514 break; ··· 1215 1212 case MPOL_INTERLEAVE: 1216 1213 return interleave_nodes(policy); 1217 1214 1218 - case MPOL_BIND: 1215 + case MPOL_BIND: { 1219 1216 /* 1220 1217 * Follow bind policy behavior and start allocation at the 1221 1218 * first node. 1222 1219 */ 1223 - return zone_to_nid(policy->v.zonelist->zones[0]); 1220 + return zonelist_node_idx(policy->v.zonelist->_zonerefs); 1221 + } 1224 1222 1225 1223 case MPOL_PREFERRED: 1226 1224 if (policy->v.preferred_node >= 0) ··· 1327 1323 1328 1324 zl = node_zonelist(nid, gfp); 1329 1325 page = __alloc_pages(gfp, order, zl); 1330 - if (page && page_zone(page) == zl->zones[0]) 1326 + if (page && page_zone(page) == zonelist_zone(&zl->_zonerefs[0])) 1331 1327 inc_zone_page_state(page, NUMA_INTERLEAVE_HIT); 1332 1328 return page; 1333 1329 } ··· 1467 1463 return a->v.preferred_node == b->v.preferred_node; 1468 1464 case MPOL_BIND: { 1469 1465 int i; 1470 - for (i = 0; a->v.zonelist->zones[i]; i++) 1471 - if (a->v.zonelist->zones[i] != b->v.zonelist->zones[i]) 1466 + for (i = 0; a->v.zonelist->_zonerefs[i].zone; i++) { 1467 + struct zone *za, *zb; 1468 + za = zonelist_zone(&a->v.zonelist->_zonerefs[i]); 1469 + zb = zonelist_zone(&b->v.zonelist->_zonerefs[i]); 1470 + if (za != zb) 1472 1471 return 0; 1473 - return b->v.zonelist->zones[i] == NULL; 1472 + } 1473 + return b->v.zonelist->_zonerefs[i].zone == NULL; 1474 1474 } 1475 1475 default: 1476 1476 BUG(); ··· 1793 1785 break; 1794 1786 case MPOL_BIND: { 1795 1787 nodemask_t nodes; 1796 - struct zone **z; 1788 + struct zoneref *z; 1797 1789 struct zonelist *zonelist; 1798 1790 1799 1791 nodes_clear(nodes); 1800 - for (z = pol->v.zonelist->zones; *z; z++) 1801 - node_set(zone_to_nid(*z), nodes); 1792 + for (z = pol->v.zonelist->_zonerefs; z->zone; z++) 1793 + node_set(zonelist_node_idx(z), nodes); 1802 1794 nodes_remap(tmp, nodes, *mpolmask, *newmask); 1803 1795 nodes = tmp; 1804 1796
+22 -23
mm/oom_kill.c
··· 176 176 { 177 177 #ifdef CONFIG_NUMA 178 178 struct zone *zone; 179 - struct zone **z; 179 + struct zoneref *z; 180 180 enum zone_type high_zoneidx = gfp_zone(gfp_mask); 181 181 nodemask_t nodes = node_states[N_HIGH_MEMORY]; 182 182 ··· 462 462 * if a parallel OOM killing is already taking place that includes a zone in 463 463 * the zonelist. Otherwise, locks all zones in the zonelist and returns 1. 464 464 */ 465 - int try_set_zone_oom(struct zonelist *zonelist) 465 + int try_set_zone_oom(struct zonelist *zonelist, gfp_t gfp_mask) 466 466 { 467 - struct zone **z; 467 + struct zoneref *z; 468 + struct zone *zone; 468 469 int ret = 1; 469 470 470 - z = zonelist->zones; 471 - 472 471 spin_lock(&zone_scan_mutex); 473 - do { 474 - if (zone_is_oom_locked(*z)) { 472 + for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) { 473 + if (zone_is_oom_locked(zone)) { 475 474 ret = 0; 476 475 goto out; 477 476 } 478 - } while (*(++z) != NULL); 477 + } 479 478 480 - /* 481 - * Lock each zone in the zonelist under zone_scan_mutex so a parallel 482 - * invocation of try_set_zone_oom() doesn't succeed when it shouldn't. 483 - */ 484 - z = zonelist->zones; 485 - do { 486 - zone_set_flag(*z, ZONE_OOM_LOCKED); 487 - } while (*(++z) != NULL); 479 + for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) { 480 + /* 481 + * Lock each zone in the zonelist under zone_scan_mutex so a 482 + * parallel invocation of try_set_zone_oom() doesn't succeed 483 + * when it shouldn't. 484 + */ 485 + zone_set_flag(zone, ZONE_OOM_LOCKED); 486 + } 487 + 488 488 out: 489 489 spin_unlock(&zone_scan_mutex); 490 490 return ret; ··· 495 495 * allocation attempts with zonelists containing them may now recall the OOM 496 496 * killer, if necessary. 497 497 */ 498 - void clear_zonelist_oom(struct zonelist *zonelist) 498 + void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask) 499 499 { 500 - struct zone **z; 501 - 502 - z = zonelist->zones; 500 + struct zoneref *z; 501 + struct zone *zone; 503 502 504 503 spin_lock(&zone_scan_mutex); 505 - do { 506 - zone_clear_flag(*z, ZONE_OOM_LOCKED); 507 - } while (*(++z) != NULL); 504 + for_each_zone_zonelist(zone, z, zonelist, gfp_zone(gfp_mask)) { 505 + zone_clear_flag(zone, ZONE_OOM_LOCKED); 506 + } 508 507 spin_unlock(&zone_scan_mutex); 509 508 } 510 509
+38 -30
mm/page_alloc.c
··· 1317 1317 * We are low on memory in the second scan, and should leave no stone 1318 1318 * unturned looking for a free page. 1319 1319 */ 1320 - static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z, 1320 + static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zoneref *z, 1321 1321 nodemask_t *allowednodes) 1322 1322 { 1323 1323 struct zonelist_cache *zlc; /* cached zonelist speedup info */ ··· 1328 1328 if (!zlc) 1329 1329 return 1; 1330 1330 1331 - i = z - zonelist->zones; 1331 + i = z - zonelist->_zonerefs; 1332 1332 n = zlc->z_to_n[i]; 1333 1333 1334 1334 /* This zone is worth trying if it is allowed but not full */ ··· 1340 1340 * zlc->fullzones, so that subsequent attempts to allocate a page 1341 1341 * from that zone don't waste time re-examining it. 1342 1342 */ 1343 - static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z) 1343 + static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) 1344 1344 { 1345 1345 struct zonelist_cache *zlc; /* cached zonelist speedup info */ 1346 1346 int i; /* index of *z in zonelist zones */ ··· 1349 1349 if (!zlc) 1350 1350 return; 1351 1351 1352 - i = z - zonelist->zones; 1352 + i = z - zonelist->_zonerefs; 1353 1353 1354 1354 set_bit(i, zlc->fullzones); 1355 1355 } ··· 1361 1361 return NULL; 1362 1362 } 1363 1363 1364 - static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zone **z, 1364 + static int zlc_zone_worth_trying(struct zonelist *zonelist, struct zoneref *z, 1365 1365 nodemask_t *allowednodes) 1366 1366 { 1367 1367 return 1; 1368 1368 } 1369 1369 1370 - static void zlc_mark_zone_full(struct zonelist *zonelist, struct zone **z) 1370 + static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) 1371 1371 { 1372 1372 } 1373 1373 #endif /* CONFIG_NUMA */ ··· 1380 1380 get_page_from_freelist(gfp_t gfp_mask, unsigned int order, 1381 1381 struct zonelist *zonelist, int high_zoneidx, int alloc_flags) 1382 1382 { 1383 - struct zone **z; 1383 + struct zoneref *z; 1384 1384 struct page *page = NULL; 1385 1385 int classzone_idx; 1386 1386 struct zone *zone, *preferred_zone; ··· 1389 1389 int did_zlc_setup = 0; /* just call zlc_setup() one time */ 1390 1390 1391 1391 z = first_zones_zonelist(zonelist, high_zoneidx); 1392 - classzone_idx = zone_idx(*z); 1393 - preferred_zone = *z; 1392 + classzone_idx = zonelist_zone_idx(z); 1393 + preferred_zone = zonelist_zone(z); 1394 1394 1395 1395 zonelist_scan: 1396 1396 /* ··· 1453 1453 { 1454 1454 const gfp_t wait = gfp_mask & __GFP_WAIT; 1455 1455 enum zone_type high_zoneidx = gfp_zone(gfp_mask); 1456 - struct zone **z; 1456 + struct zoneref *z; 1457 + struct zone *zone; 1457 1458 struct page *page; 1458 1459 struct reclaim_state reclaim_state; 1459 1460 struct task_struct *p = current; ··· 1468 1467 return NULL; 1469 1468 1470 1469 restart: 1471 - z = zonelist->zones; /* the list of zones suitable for gfp_mask */ 1470 + z = zonelist->_zonerefs; /* the list of zones suitable for gfp_mask */ 1472 1471 1473 - if (unlikely(*z == NULL)) { 1472 + if (unlikely(!z->zone)) { 1474 1473 /* 1475 1474 * Happens if we have an empty zonelist as a result of 1476 1475 * GFP_THISNODE being used on a memoryless node ··· 1494 1493 if (NUMA_BUILD && (gfp_mask & GFP_THISNODE) == GFP_THISNODE) 1495 1494 goto nopage; 1496 1495 1497 - for (z = zonelist->zones; *z; z++) 1498 - wakeup_kswapd(*z, order); 1496 + for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) 1497 + wakeup_kswapd(zone, order); 1499 1498 1500 1499 /* 1501 1500 * OK, we're below the kswapd watermark and have kicked background ··· 1576 1575 if (page) 1577 1576 goto got_pg; 1578 1577 } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { 1579 - if (!try_set_zone_oom(zonelist)) { 1578 + if (!try_set_zone_oom(zonelist, gfp_mask)) { 1580 1579 schedule_timeout_uninterruptible(1); 1581 1580 goto restart; 1582 1581 } ··· 1590 1589 page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, 1591 1590 zonelist, high_zoneidx, ALLOC_WMARK_HIGH|ALLOC_CPUSET); 1592 1591 if (page) { 1593 - clear_zonelist_oom(zonelist); 1592 + clear_zonelist_oom(zonelist, gfp_mask); 1594 1593 goto got_pg; 1595 1594 } 1596 1595 1597 1596 /* The OOM killer will not help higher order allocs so fail */ 1598 1597 if (order > PAGE_ALLOC_COSTLY_ORDER) { 1599 - clear_zonelist_oom(zonelist); 1598 + clear_zonelist_oom(zonelist, gfp_mask); 1600 1599 goto nopage; 1601 1600 } 1602 1601 1603 1602 out_of_memory(zonelist, gfp_mask, order); 1604 - clear_zonelist_oom(zonelist); 1603 + clear_zonelist_oom(zonelist, gfp_mask); 1605 1604 goto restart; 1606 1605 } 1607 1606 ··· 1703 1702 1704 1703 static unsigned int nr_free_zone_pages(int offset) 1705 1704 { 1706 - struct zone **z; 1705 + struct zoneref *z; 1707 1706 struct zone *zone; 1708 1707 1709 1708 /* Just pick one node, since fallback list is circular */ ··· 1897 1896 zone_type--; 1898 1897 zone = pgdat->node_zones + zone_type; 1899 1898 if (populated_zone(zone)) { 1900 - zonelist->zones[nr_zones++] = zone; 1899 + zoneref_set_zone(zone, 1900 + &zonelist->_zonerefs[nr_zones++]); 1901 1901 check_highest_zone(zone_type); 1902 1902 } 1903 1903 ··· 2074 2072 struct zonelist *zonelist; 2075 2073 2076 2074 zonelist = &pgdat->node_zonelists[0]; 2077 - for (j = 0; zonelist->zones[j] != NULL; j++) 2075 + for (j = 0; zonelist->_zonerefs[j].zone != NULL; j++) 2078 2076 ; 2079 2077 j = build_zonelists_node(NODE_DATA(node), zonelist, j, 2080 2078 MAX_NR_ZONES - 1); 2081 - zonelist->zones[j] = NULL; 2079 + zonelist->_zonerefs[j].zone = NULL; 2080 + zonelist->_zonerefs[j].zone_idx = 0; 2082 2081 } 2083 2082 2084 2083 /* ··· 2092 2089 2093 2090 zonelist = &pgdat->node_zonelists[1]; 2094 2091 j = build_zonelists_node(pgdat, zonelist, 0, MAX_NR_ZONES - 1); 2095 - zonelist->zones[j] = NULL; 2092 + zonelist->_zonerefs[j].zone = NULL; 2093 + zonelist->_zonerefs[j].zone_idx = 0; 2096 2094 } 2097 2095 2098 2096 /* ··· 2118 2114 node = node_order[j]; 2119 2115 z = &NODE_DATA(node)->node_zones[zone_type]; 2120 2116 if (populated_zone(z)) { 2121 - zonelist->zones[pos++] = z; 2117 + zoneref_set_zone(z, 2118 + &zonelist->_zonerefs[pos++]); 2122 2119 check_highest_zone(zone_type); 2123 2120 } 2124 2121 } 2125 2122 } 2126 - zonelist->zones[pos] = NULL; 2123 + zonelist->_zonerefs[pos].zone = NULL; 2124 + zonelist->_zonerefs[pos].zone_idx = 0; 2127 2125 } 2128 2126 2129 2127 static int default_zonelist_order(void) ··· 2202 2196 /* initialize zonelists */ 2203 2197 for (i = 0; i < MAX_ZONELISTS; i++) { 2204 2198 zonelist = pgdat->node_zonelists + i; 2205 - zonelist->zones[0] = NULL; 2199 + zonelist->_zonerefs[0].zone = NULL; 2200 + zonelist->_zonerefs[0].zone_idx = 0; 2206 2201 } 2207 2202 2208 2203 /* NUMA-aware ordering of nodes */ ··· 2255 2248 { 2256 2249 struct zonelist *zonelist; 2257 2250 struct zonelist_cache *zlc; 2258 - struct zone **z; 2251 + struct zoneref *z; 2259 2252 2260 2253 zonelist = &pgdat->node_zonelists[0]; 2261 2254 zonelist->zlcache_ptr = zlc = &zonelist->zlcache; 2262 2255 bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST); 2263 - for (z = zonelist->zones; *z; z++) 2264 - zlc->z_to_n[z - zonelist->zones] = zone_to_nid(*z); 2256 + for (z = zonelist->_zonerefs; z->zone; z++) 2257 + zlc->z_to_n[z - zonelist->_zonerefs] = zonelist_node_idx(z); 2265 2258 } 2266 2259 2267 2260 ··· 2304 2297 MAX_NR_ZONES - 1); 2305 2298 } 2306 2299 2307 - zonelist->zones[j] = NULL; 2300 + zonelist->_zonerefs[j].zone = NULL; 2301 + zonelist->_zonerefs[j].zone_idx = 0; 2308 2302 } 2309 2303 2310 2304 /* non-NUMA variant of zonelist performance cache - just NULL zlcache_ptr */
+1 -1
mm/slab.c
··· 3242 3242 { 3243 3243 struct zonelist *zonelist; 3244 3244 gfp_t local_flags; 3245 - struct zone **z; 3245 + struct zoneref *z; 3246 3246 struct zone *zone; 3247 3247 enum zone_type high_zoneidx = gfp_zone(flags); 3248 3248 void *obj = NULL;
+1 -1
mm/slub.c
··· 1284 1284 { 1285 1285 #ifdef CONFIG_NUMA 1286 1286 struct zonelist *zonelist; 1287 - struct zone **z; 1287 + struct zoneref *z; 1288 1288 struct zone *zone; 1289 1289 enum zone_type high_zoneidx = gfp_zone(flags); 1290 1290 struct page *page;
+10 -12
mm/vmscan.c
··· 1251 1251 { 1252 1252 enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); 1253 1253 unsigned long nr_reclaimed = 0; 1254 - struct zone **z; 1254 + struct zoneref *z; 1255 1255 struct zone *zone; 1256 1256 1257 1257 sc->all_unreclaimable = 1; ··· 1301 1301 * allocation attempt will fail. 1302 1302 */ 1303 1303 static unsigned long do_try_to_free_pages(struct zonelist *zonelist, 1304 - gfp_t gfp_mask, struct scan_control *sc) 1304 + struct scan_control *sc) 1305 1305 { 1306 1306 int priority; 1307 1307 int ret = 0; ··· 1309 1309 unsigned long nr_reclaimed = 0; 1310 1310 struct reclaim_state *reclaim_state = current->reclaim_state; 1311 1311 unsigned long lru_pages = 0; 1312 - struct zone **z; 1312 + struct zoneref *z; 1313 1313 struct zone *zone; 1314 - enum zone_type high_zoneidx = gfp_zone(gfp_mask); 1314 + enum zone_type high_zoneidx = gfp_zone(sc->gfp_mask); 1315 1315 1316 1316 if (scan_global_lru(sc)) 1317 1317 count_vm_event(ALLOCSTALL); ··· 1339 1339 * over limit cgroups 1340 1340 */ 1341 1341 if (scan_global_lru(sc)) { 1342 - shrink_slab(sc->nr_scanned, gfp_mask, lru_pages); 1342 + shrink_slab(sc->nr_scanned, sc->gfp_mask, lru_pages); 1343 1343 if (reclaim_state) { 1344 1344 nr_reclaimed += reclaim_state->reclaimed_slab; 1345 1345 reclaim_state->reclaimed_slab = 0; ··· 1410 1410 .isolate_pages = isolate_pages_global, 1411 1411 }; 1412 1412 1413 - return do_try_to_free_pages(zonelist, gfp_mask, &sc); 1413 + return do_try_to_free_pages(zonelist, &sc); 1414 1414 } 1415 1415 1416 1416 #ifdef CONFIG_CGROUP_MEM_RES_CTLR ··· 1419 1419 gfp_t gfp_mask) 1420 1420 { 1421 1421 struct scan_control sc = { 1422 - .gfp_mask = gfp_mask, 1423 1422 .may_writepage = !laptop_mode, 1424 1423 .may_swap = 1, 1425 1424 .swap_cluster_max = SWAP_CLUSTER_MAX, ··· 1428 1429 .isolate_pages = mem_cgroup_isolate_pages, 1429 1430 }; 1430 1431 struct zonelist *zonelist; 1431 - int target_zone = gfp_zone(GFP_HIGHUSER_MOVABLE); 1432 1432 1433 - zonelist = &NODE_DATA(numa_node_id())->node_zonelists[target_zone]; 1434 - if (do_try_to_free_pages(zonelist, sc.gfp_mask, &sc)) 1435 - return 1; 1436 - return 0; 1433 + sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | 1434 + (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); 1435 + zonelist = NODE_DATA(numa_node_id())->node_zonelists; 1436 + return do_try_to_free_pages(zonelist, &sc); 1437 1437 } 1438 1438 #endif 1439 1439