diff options
-rw-r--r-- | mm/memcontrol.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 31a1d3b71eee..52840adae62a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1132,11 +1132,14 @@ static unsigned int get_swappiness(struct mem_cgroup *memcg) | |||
1132 | static void mem_cgroup_start_move(struct mem_cgroup *mem) | 1132 | static void mem_cgroup_start_move(struct mem_cgroup *mem) |
1133 | { | 1133 | { |
1134 | int cpu; | 1134 | int cpu; |
1135 | /* Because this is for moving account, reuse mc.lock */ | 1135 | |
1136 | spin_lock(&mc.lock); | 1136 | get_online_cpus(); |
1137 | for_each_possible_cpu(cpu) | 1137 | spin_lock(&mem->pcp_counter_lock); |
1138 | for_each_online_cpu(cpu) | ||
1138 | per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) += 1; | 1139 | per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) += 1; |
1139 | spin_unlock(&mc.lock); | 1140 | mem->nocpu_base.count[MEM_CGROUP_ON_MOVE] += 1; |
1141 | spin_unlock(&mem->pcp_counter_lock); | ||
1142 | put_online_cpus(); | ||
1140 | 1143 | ||
1141 | synchronize_rcu(); | 1144 | synchronize_rcu(); |
1142 | } | 1145 | } |
@@ -1147,10 +1150,13 @@ static void mem_cgroup_end_move(struct mem_cgroup *mem) | |||
1147 | 1150 | ||
1148 | if (!mem) | 1151 | if (!mem) |
1149 | return; | 1152 | return; |
1150 | spin_lock(&mc.lock); | 1153 | get_online_cpus(); |
1151 | for_each_possible_cpu(cpu) | 1154 | spin_lock(&mem->pcp_counter_lock); |
1155 | for_each_online_cpu(cpu) | ||
1152 | per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) -= 1; | 1156 | per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) -= 1; |
1153 | spin_unlock(&mc.lock); | 1157 | mem->nocpu_base.count[MEM_CGROUP_ON_MOVE] -= 1; |
1158 | spin_unlock(&mem->pcp_counter_lock); | ||
1159 | put_online_cpus(); | ||
1154 | } | 1160 | } |
1155 | /* | 1161 | /* |
1156 | * 2 routines for checking "mem" is under move_account() or not. | 1162 | * 2 routines for checking "mem" is under move_account() or not. |
@@ -1751,6 +1757,17 @@ static void mem_cgroup_drain_pcp_counter(struct mem_cgroup *mem, int cpu) | |||
1751 | per_cpu(mem->stat->count[i], cpu) = 0; | 1757 | per_cpu(mem->stat->count[i], cpu) = 0; |
1752 | mem->nocpu_base.count[i] += x; | 1758 | mem->nocpu_base.count[i] += x; |
1753 | } | 1759 | } |
1760 | /* need to clear ON_MOVE value, works as a kind of lock. */ | ||
1761 | per_cpu(mem->stat->count[MEM_CGROUP_ON_MOVE], cpu) = 0; | ||
1762 | spin_unlock(&mem->pcp_counter_lock); | ||
1763 | } | ||
1764 | |||
1765 | static void synchronize_mem_cgroup_on_move(struct mem_cgroup *mem, int cpu) | ||
1766 | { | ||
1767 | int idx = MEM_CGROUP_ON_MOVE; | ||
1768 | |||
1769 | spin_lock(&mem->pcp_counter_lock); | ||
1770 | per_cpu(mem->stat->count[idx], cpu) = mem->nocpu_base.count[idx]; | ||
1754 | spin_unlock(&mem->pcp_counter_lock); | 1771 | spin_unlock(&mem->pcp_counter_lock); |
1755 | } | 1772 | } |
1756 | 1773 | ||
@@ -1762,6 +1779,12 @@ static int __cpuinit memcg_cpu_hotplug_callback(struct notifier_block *nb, | |||
1762 | struct memcg_stock_pcp *stock; | 1779 | struct memcg_stock_pcp *stock; |
1763 | struct mem_cgroup *iter; | 1780 | struct mem_cgroup *iter; |
1764 | 1781 | ||
1782 | if ((action == CPU_ONLINE)) { | ||
1783 | for_each_mem_cgroup_all(iter) | ||
1784 | synchronize_mem_cgroup_on_move(iter, cpu); | ||
1785 | return NOTIFY_OK; | ||
1786 | } | ||
1787 | |||
1765 | if ((action != CPU_DEAD) || action != CPU_DEAD_FROZEN) | 1788 | if ((action != CPU_DEAD) || action != CPU_DEAD_FROZEN) |
1766 | return NOTIFY_OK; | 1789 | return NOTIFY_OK; |
1767 | 1790 | ||