diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 82 |
1 files changed, 78 insertions, 4 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 04729647f359..71cb253368cb 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -1679,6 +1679,30 @@ struct mempolicy *get_vma_policy(struct task_struct *task, | |||
1679 | return pol; | 1679 | return pol; |
1680 | } | 1680 | } |
1681 | 1681 | ||
1682 | bool vma_policy_mof(struct task_struct *task, struct vm_area_struct *vma) | ||
1683 | { | ||
1684 | struct mempolicy *pol = get_task_policy(task); | ||
1685 | if (vma) { | ||
1686 | if (vma->vm_ops && vma->vm_ops->get_policy) { | ||
1687 | bool ret = false; | ||
1688 | |||
1689 | pol = vma->vm_ops->get_policy(vma, vma->vm_start); | ||
1690 | if (pol && (pol->flags & MPOL_F_MOF)) | ||
1691 | ret = true; | ||
1692 | mpol_cond_put(pol); | ||
1693 | |||
1694 | return ret; | ||
1695 | } else if (vma->vm_policy) { | ||
1696 | pol = vma->vm_policy; | ||
1697 | } | ||
1698 | } | ||
1699 | |||
1700 | if (!pol) | ||
1701 | return default_policy.flags & MPOL_F_MOF; | ||
1702 | |||
1703 | return pol->flags & MPOL_F_MOF; | ||
1704 | } | ||
1705 | |||
1682 | static int apply_policy_zone(struct mempolicy *policy, enum zone_type zone) | 1706 | static int apply_policy_zone(struct mempolicy *policy, enum zone_type zone) |
1683 | { | 1707 | { |
1684 | enum zone_type dynamic_policy_zone = policy_zone; | 1708 | enum zone_type dynamic_policy_zone = policy_zone; |
@@ -2277,6 +2301,35 @@ static void sp_free(struct sp_node *n) | |||
2277 | kmem_cache_free(sn_cache, n); | 2301 | kmem_cache_free(sn_cache, n); |
2278 | } | 2302 | } |
2279 | 2303 | ||
2304 | #ifdef CONFIG_NUMA_BALANCING | ||
2305 | static bool numa_migrate_deferred(struct task_struct *p, int last_cpupid) | ||
2306 | { | ||
2307 | /* Never defer a private fault */ | ||
2308 | if (cpupid_match_pid(p, last_cpupid)) | ||
2309 | return false; | ||
2310 | |||
2311 | if (p->numa_migrate_deferred) { | ||
2312 | p->numa_migrate_deferred--; | ||
2313 | return true; | ||
2314 | } | ||
2315 | return false; | ||
2316 | } | ||
2317 | |||
2318 | static inline void defer_numa_migrate(struct task_struct *p) | ||
2319 | { | ||
2320 | p->numa_migrate_deferred = sysctl_numa_balancing_migrate_deferred; | ||
2321 | } | ||
2322 | #else | ||
2323 | static inline bool numa_migrate_deferred(struct task_struct *p, int last_cpupid) | ||
2324 | { | ||
2325 | return false; | ||
2326 | } | ||
2327 | |||
2328 | static inline void defer_numa_migrate(struct task_struct *p) | ||
2329 | { | ||
2330 | } | ||
2331 | #endif /* CONFIG_NUMA_BALANCING */ | ||
2332 | |||
2280 | /** | 2333 | /** |
2281 | * mpol_misplaced - check whether current page node is valid in policy | 2334 | * mpol_misplaced - check whether current page node is valid in policy |
2282 | * | 2335 | * |
@@ -2300,6 +2353,8 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long | |||
2300 | struct zone *zone; | 2353 | struct zone *zone; |
2301 | int curnid = page_to_nid(page); | 2354 | int curnid = page_to_nid(page); |
2302 | unsigned long pgoff; | 2355 | unsigned long pgoff; |
2356 | int thiscpu = raw_smp_processor_id(); | ||
2357 | int thisnid = cpu_to_node(thiscpu); | ||
2303 | int polnid = -1; | 2358 | int polnid = -1; |
2304 | int ret = -1; | 2359 | int ret = -1; |
2305 | 2360 | ||
@@ -2348,9 +2403,11 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long | |||
2348 | 2403 | ||
2349 | /* Migrate the page towards the node whose CPU is referencing it */ | 2404 | /* Migrate the page towards the node whose CPU is referencing it */ |
2350 | if (pol->flags & MPOL_F_MORON) { | 2405 | if (pol->flags & MPOL_F_MORON) { |
2351 | int last_nid; | 2406 | int last_cpupid; |
2407 | int this_cpupid; | ||
2352 | 2408 | ||
2353 | polnid = numa_node_id(); | 2409 | polnid = thisnid; |
2410 | this_cpupid = cpu_pid_to_cpupid(thiscpu, current->pid); | ||
2354 | 2411 | ||
2355 | /* | 2412 | /* |
2356 | * Multi-stage node selection is used in conjunction | 2413 | * Multi-stage node selection is used in conjunction |
@@ -2373,8 +2430,25 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long | |||
2373 | * it less likely we act on an unlikely task<->page | 2430 | * it less likely we act on an unlikely task<->page |
2374 | * relation. | 2431 | * relation. |
2375 | */ | 2432 | */ |
2376 | last_nid = page_nid_xchg_last(page, polnid); | 2433 | last_cpupid = page_cpupid_xchg_last(page, this_cpupid); |
2377 | if (last_nid != polnid) | 2434 | if (!cpupid_pid_unset(last_cpupid) && cpupid_to_nid(last_cpupid) != thisnid) { |
2435 | |||
2436 | /* See sysctl_numa_balancing_migrate_deferred comment */ | ||
2437 | if (!cpupid_match_pid(current, last_cpupid)) | ||
2438 | defer_numa_migrate(current); | ||
2439 | |||
2440 | goto out; | ||
2441 | } | ||
2442 | |||
2443 | /* | ||
2444 | * The quadratic filter above reduces extraneous migration | ||
2445 | * of shared pages somewhat. This code reduces it even more, | ||
2446 | * reducing the overhead of page migrations of shared pages. | ||
2447 | * This makes workloads with shared pages rely more on | ||
2448 | * "move task near its memory", and less on "move memory | ||
2449 | * towards its task", which is exactly what we want. | ||
2450 | */ | ||
2451 | if (numa_migrate_deferred(current, last_cpupid)) | ||
2378 | goto out; | 2452 | goto out; |
2379 | } | 2453 | } |
2380 | 2454 | ||