summaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 15af3da5af02..696c6529e900 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1777,6 +1777,10 @@ static void drain_local_stock(struct work_struct *dummy)
1777 struct memcg_stock_pcp *stock; 1777 struct memcg_stock_pcp *stock;
1778 unsigned long flags; 1778 unsigned long flags;
1779 1779
1780 /*
1781 * The only protection from memory hotplug vs. drain_stock races is
1782 * that we always operate on local CPU stock here with IRQ disabled
1783 */
1780 local_irq_save(flags); 1784 local_irq_save(flags);
1781 1785
1782 stock = this_cpu_ptr(&memcg_stock); 1786 stock = this_cpu_ptr(&memcg_stock);
@@ -1821,27 +1825,33 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
1821 /* If someone's already draining, avoid adding running more workers. */ 1825 /* If someone's already draining, avoid adding running more workers. */
1822 if (!mutex_trylock(&percpu_charge_mutex)) 1826 if (!mutex_trylock(&percpu_charge_mutex))
1823 return; 1827 return;
1824 /* Notify other cpus that system-wide "drain" is running */ 1828 /*
1825 get_online_cpus(); 1829 * Notify other cpus that system-wide "drain" is running
1830 * We do not care about races with the cpu hotplug because cpu down
1831 * as well as workers from this path always operate on the local
1832 * per-cpu data. CPU up doesn't touch memcg_stock at all.
1833 */
1826 curcpu = get_cpu(); 1834 curcpu = get_cpu();
1827 for_each_online_cpu(cpu) { 1835 for_each_online_cpu(cpu) {
1828 struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); 1836 struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
1829 struct mem_cgroup *memcg; 1837 struct mem_cgroup *memcg;
1830 1838
1831 memcg = stock->cached; 1839 memcg = stock->cached;
1832 if (!memcg || !stock->nr_pages) 1840 if (!memcg || !stock->nr_pages || !css_tryget(&memcg->css))
1833 continue; 1841 continue;
1834 if (!mem_cgroup_is_descendant(memcg, root_memcg)) 1842 if (!mem_cgroup_is_descendant(memcg, root_memcg)) {
1843 css_put(&memcg->css);
1835 continue; 1844 continue;
1845 }
1836 if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) { 1846 if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
1837 if (cpu == curcpu) 1847 if (cpu == curcpu)
1838 drain_local_stock(&stock->work); 1848 drain_local_stock(&stock->work);
1839 else 1849 else
1840 schedule_work_on(cpu, &stock->work); 1850 schedule_work_on(cpu, &stock->work);
1841 } 1851 }
1852 css_put(&memcg->css);
1842 } 1853 }
1843 put_cpu(); 1854 put_cpu();
1844 put_online_cpus();
1845 mutex_unlock(&percpu_charge_mutex); 1855 mutex_unlock(&percpu_charge_mutex);
1846} 1856}
1847 1857