diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/mempolicy.c | 13 | ||||
| -rw-r--r-- | mm/page_alloc.c | 16 | ||||
| -rw-r--r-- | mm/vmscan.c | 19 |
3 files changed, 45 insertions, 3 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 1511786462f3..871d9584d9cf 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -67,6 +67,7 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/nodemask.h> +#include <linux/cpuset.h> #include <linux/gfp.h> #include <linux/slab.h> #include <linux/string.h> @@ -167,6 +168,10 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask, if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long))) return -EFAULT; nodes[nlongs-1] &= endmask; + /* Update current mems_allowed */ + cpuset_update_current_mems_allowed(); + /* Ignore nodes not set in current->mems_allowed */ + cpuset_restrict_to_mems_allowed(nodes); return mpol_check_policy(mode, nodes); } @@ -655,8 +660,10 @@ static struct zonelist *zonelist_policy(unsigned gfp, struct mempolicy *policy) break; case MPOL_BIND: /* Lower zones don't get a policy applied */ + /* Careful: current->mems_allowed might have moved */ if (gfp >= policy_zone) - return policy->v.zonelist; + if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist)) + return policy->v.zonelist; /*FALL THROUGH*/ case MPOL_INTERLEAVE: /* should not happen */ case MPOL_DEFAULT: @@ -747,6 +754,8 @@ alloc_page_vma(unsigned gfp, struct vm_area_struct *vma, unsigned long addr) { struct mempolicy *pol = get_vma_policy(vma, addr); + cpuset_update_current_mems_allowed(); + if (unlikely(pol->policy == MPOL_INTERLEAVE)) { unsigned nid; if (vma) { @@ -784,6 +793,8 @@ struct page *alloc_pages_current(unsigned gfp, unsigned order) { struct mempolicy *pol = current->mempolicy; + if (!in_interrupt()) + cpuset_update_current_mems_allowed(); if (!pol || in_interrupt()) pol = &default_policy; if (pol->policy == MPOL_INTERLEAVE) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b68d7d8d7ac8..c8c1560871cf 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -31,6 +31,7 @@ #include <linux/topology.h> #include <linux/sysctl.h> #include <linux/cpu.h> +#include <linux/cpuset.h> #include <linux/nodemask.h> #include <linux/vmalloc.h> @@ -765,6 +766,9 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, classzone_idx, 0, 0)) continue; + if (!cpuset_zone_allowed(z)) + continue; + page = buffered_rmqueue(z, order, gfp_mask); if (page) goto got_pg; @@ -783,6 +787,9 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, gfp_mask & __GFP_HIGH)) continue; + if (!cpuset_zone_allowed(z)) + continue; + page = buffered_rmqueue(z, order, gfp_mask); if (page) goto got_pg; @@ -792,6 +799,8 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) && !in_interrupt()) { /* go through the zonelist yet again, ignoring mins */ for (i = 0; (z = zones[i]) != NULL; i++) { + if (!cpuset_zone_allowed(z)) + continue; page = buffered_rmqueue(z, order, gfp_mask); if (page) goto got_pg; @@ -831,6 +840,9 @@ rebalance: gfp_mask & __GFP_HIGH)) continue; + if (!cpuset_zone_allowed(z)) + continue; + page = buffered_rmqueue(z, order, gfp_mask); if (page) goto got_pg; @@ -847,6 +859,9 @@ rebalance: classzone_idx, 0, 0)) continue; + if (!cpuset_zone_allowed(z)) + continue; + page = buffered_rmqueue(z, order, gfp_mask); if (page) goto got_pg; @@ -1490,6 +1505,7 @@ void __init build_all_zonelists(void) for_each_online_node(i) build_zonelists(NODE_DATA(i)); printk("Built %i zonelists\n", num_online_nodes()); + cpuset_init_current_mems_allowed(); } /* diff --git a/mm/vmscan.c b/mm/vmscan.c index e28c0232920d..aa9daa5651c2 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -30,6 +30,7 @@ #include <linux/rmap.h> #include <linux/topology.h> #include <linux/cpu.h> +#include <linux/cpuset.h> #include <linux/notifier.h> #include <linux/rwsem.h> @@ -865,6 +866,9 @@ shrink_caches(struct zone **zones, struct scan_control *sc) if (zone->present_pages == 0) continue; + if (!cpuset_zone_allowed(zone)) + continue; + zone->temp_priority = sc->priority; if (zone->prev_priority > sc->priority) zone->prev_priority = sc->priority; @@ -908,6 +912,9 @@ int try_to_free_pages(struct zone **zones, for (i = 0; zones[i] != NULL; i++) { struct zone *zone = zones[i]; + if (!cpuset_zone_allowed(zone)) + continue; + zone->temp_priority = DEF_PRIORITY; lru_pages += zone->nr_active + zone->nr_inactive; } @@ -948,8 +955,14 @@ int try_to_free_pages(struct zone **zones, blk_congestion_wait(WRITE, HZ/10); } out: - for (i = 0; zones[i] != 0; i++) - zones[i]->prev_priority = zones[i]->temp_priority; + for (i = 0; zones[i] != 0; i++) { + struct zone *zone = zones[i]; + + if (!cpuset_zone_allowed(zone)) + continue; + + zone->prev_priority = zone->temp_priority; + } return ret; } @@ -1210,6 +1223,8 @@ void wakeup_kswapd(struct zone *zone, int order) return; if (pgdat->kswapd_max_order < order) pgdat->kswapd_max_order = order; + if (!cpuset_zone_allowed(zone)) + return; if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait)) return; wake_up_interruptible(&zone->zone_pgdat->kswapd_wait); |
