Commit a8f60772 authored by Mel Gorman's avatar Mel Gorman

mm: numa: Rate limit the amount of memory that is migrated between nodes

NOTE: This is very heavily based on similar logic in autonuma. It should
	be signed off by Andrea but because there was no standalone
	patch and it's sufficiently different from what he did that
	the signed-off is omitted. Will be added back if requested.

If a large number of pages are misplaced then the memory bus can be
saturated just migrating pages between nodes. This patch rate-limits
the amount of memory that can be migrating between nodes.
Signed-off-by: default avatarMel Gorman <mgorman@suse.de>
parent 8177a420
...@@ -1460,6 +1460,14 @@ static struct page *alloc_misplaced_dst_page(struct page *page, ...@@ -1460,6 +1460,14 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
return newpage; return newpage;
} }
/*
* page migration rate limiting control.
* Do not migrate more than @pages_to_migrate in a @migrate_interval_millisecs
* window of time. Default here says do not migrate more than 1280M per second.
*/
static unsigned int migrate_interval_millisecs __read_mostly = 100;
static unsigned int ratelimit_pages __read_mostly = 128 << (20 - PAGE_SHIFT);
/* /*
* Attempt to migrate a misplaced page to the specified destination * Attempt to migrate a misplaced page to the specified destination
* node. Caller is expected to have an elevated reference count on * node. Caller is expected to have an elevated reference count on
...@@ -1467,6 +1475,7 @@ static struct page *alloc_misplaced_dst_page(struct page *page, ...@@ -1467,6 +1475,7 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
*/ */
int migrate_misplaced_page(struct page *page, int node) int migrate_misplaced_page(struct page *page, int node)
{ {
pg_data_t *pgdat = NODE_DATA(node);
int isolated = 0; int isolated = 0;
LIST_HEAD(migratepages); LIST_HEAD(migratepages);
...@@ -1479,8 +1488,27 @@ int migrate_misplaced_page(struct page *page, int node) ...@@ -1479,8 +1488,27 @@ int migrate_misplaced_page(struct page *page, int node)
goto out; goto out;
} }
/*
* Rate-limit the amount of data that is being migrated to a node.
* Optimal placement is no good if the memory bus is saturated and
* all the time is being spent migrating!
*/
spin_lock(&pgdat->numabalancing_migrate_lock);
if (time_after(jiffies, pgdat->numabalancing_migrate_next_window)) {
pgdat->numabalancing_migrate_nr_pages = 0;
pgdat->numabalancing_migrate_next_window = jiffies +
msecs_to_jiffies(migrate_interval_millisecs);
}
if (pgdat->numabalancing_migrate_nr_pages > ratelimit_pages) {
spin_unlock(&pgdat->numabalancing_migrate_lock);
put_page(page);
goto out;
}
pgdat->numabalancing_migrate_nr_pages++;
spin_unlock(&pgdat->numabalancing_migrate_lock);
/* Avoid migrating to a node that is nearly full */ /* Avoid migrating to a node that is nearly full */
if (migrate_balanced_pgdat(NODE_DATA(node), 1)) { if (migrate_balanced_pgdat(pgdat, 1)) {
int page_lru; int page_lru;
if (isolate_lru_page(page)) { if (isolate_lru_page(page)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment