Skip to content

Commit

Permalink
mm, numa: reclaim from all nodes within reclaim distance
Browse files Browse the repository at this point in the history
RECLAIM_DISTANCE represents the distance between nodes at which it is
deemed too costly to allocate from; it's preferred to try to reclaim from
a local zone before falling back to allocating on a remote node with such
a distance.

To do this, zone_reclaim_mode is set if the distance between any two
nodes on the system is greather than this distance.  This, however, ends
up causing the page allocator to reclaim from every zone regardless of
its affinity.

What we really want is to reclaim only from zones that are closer than
RECLAIM_DISTANCE.  This patch adds a nodemask to each node that
represents the set of nodes that are within this distance.  During the
zone iteration, if the bit for a zone's node is set for the local node,
then reclaim is attempted; otherwise, the zone is skipped.

[[email protected]: fix CONFIG_NUMA=n build]
Signed-off-by: David Rientjes <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: Minchan Kim <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
rientjes authored and torvalds committed Oct 9, 2012
1 parent a0c5e81 commit 957f822
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
1 change: 1 addition & 0 deletions include/linux/mmzone.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ typedef struct pglist_data {
unsigned long node_spanned_pages; /* total size of physical page
range, including holes */
int node_id;
nodemask_t reclaim_nodes; /* Nodes allowed to reclaim from */
wait_queue_head_t kswapd_wait;
wait_queue_head_t pfmemalloc_wait;
struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */
Expand Down
41 changes: 30 additions & 11 deletions mm/page_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,22 @@ static void zlc_clear_zones_full(struct zonelist *zonelist)
bitmap_zero(zlc->fullzones, MAX_ZONES_PER_ZONELIST);
}

static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
{
return node_isset(local_zone->node, zone->zone_pgdat->reclaim_nodes);
}

static void __paginginit init_zone_allows_reclaim(int nid)
{
int i;

for_each_online_node(i)
if (node_distance(nid, i) <= RECLAIM_DISTANCE) {
node_set(i, NODE_DATA(nid)->reclaim_nodes);
zone_reclaim_mode = 1;
}
}

#else /* CONFIG_NUMA */

static nodemask_t *zlc_setup(struct zonelist *zonelist, int alloc_flags)
Expand All @@ -1819,6 +1835,15 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z)
static void zlc_clear_zones_full(struct zonelist *zonelist)
{
}

static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
{
return true;
}

static inline void init_zone_allows_reclaim(int nid)
{
}
#endif /* CONFIG_NUMA */

/*
Expand Down Expand Up @@ -1903,7 +1928,8 @@ get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order,
did_zlc_setup = 1;
}

if (zone_reclaim_mode == 0)
if (zone_reclaim_mode == 0 ||
!zone_allows_reclaim(preferred_zone, zone))
goto this_zone_full;

/*
Expand Down Expand Up @@ -3364,21 +3390,13 @@ static void build_zonelists(pg_data_t *pgdat)
j = 0;

while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
int distance = node_distance(local_node, node);

/*
* If another node is sufficiently far away then it is better
* to reclaim pages in a zone before going off node.
*/
if (distance > RECLAIM_DISTANCE)
zone_reclaim_mode = 1;

/*
* We don't want to pressure a particular node.
* So adding penalty to the first node in same
* distance group to make it round-robin.
*/
if (distance != node_distance(local_node, prev_node))
if (node_distance(local_node, node) !=
node_distance(local_node, prev_node))
node_load[node] = load;

prev_node = node;
Expand Down Expand Up @@ -4552,6 +4570,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,

pgdat->node_id = nid;
pgdat->node_start_pfn = node_start_pfn;
init_zone_allows_reclaim(nid);
calculate_node_totalpages(pgdat, zones_size, zholes_size);

alloc_node_mem_map(pgdat);
Expand Down

0 comments on commit 957f822

Please sign in to comment.