diff options
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r-- | mm/memcontrol.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 9a6a51a7c416..4be518d4e68a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1740,17 +1740,22 @@ static DEFINE_MUTEX(percpu_charge_mutex); | |||
1740 | static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages) | 1740 | static bool consume_stock(struct mem_cgroup *memcg, unsigned int nr_pages) |
1741 | { | 1741 | { |
1742 | struct memcg_stock_pcp *stock; | 1742 | struct memcg_stock_pcp *stock; |
1743 | unsigned long flags; | ||
1743 | bool ret = false; | 1744 | bool ret = false; |
1744 | 1745 | ||
1745 | if (nr_pages > CHARGE_BATCH) | 1746 | if (nr_pages > CHARGE_BATCH) |
1746 | return ret; | 1747 | return ret; |
1747 | 1748 | ||
1748 | stock = &get_cpu_var(memcg_stock); | 1749 | local_irq_save(flags); |
1750 | |||
1751 | stock = this_cpu_ptr(&memcg_stock); | ||
1749 | if (memcg == stock->cached && stock->nr_pages >= nr_pages) { | 1752 | if (memcg == stock->cached && stock->nr_pages >= nr_pages) { |
1750 | stock->nr_pages -= nr_pages; | 1753 | stock->nr_pages -= nr_pages; |
1751 | ret = true; | 1754 | ret = true; |
1752 | } | 1755 | } |
1753 | put_cpu_var(memcg_stock); | 1756 | |
1757 | local_irq_restore(flags); | ||
1758 | |||
1754 | return ret; | 1759 | return ret; |
1755 | } | 1760 | } |
1756 | 1761 | ||
@@ -1771,15 +1776,18 @@ static void drain_stock(struct memcg_stock_pcp *stock) | |||
1771 | stock->cached = NULL; | 1776 | stock->cached = NULL; |
1772 | } | 1777 | } |
1773 | 1778 | ||
1774 | /* | ||
1775 | * This must be called under preempt disabled or must be called by | ||
1776 | * a thread which is pinned to local cpu. | ||
1777 | */ | ||
1778 | static void drain_local_stock(struct work_struct *dummy) | 1779 | static void drain_local_stock(struct work_struct *dummy) |
1779 | { | 1780 | { |
1780 | struct memcg_stock_pcp *stock = this_cpu_ptr(&memcg_stock); | 1781 | struct memcg_stock_pcp *stock; |
1782 | unsigned long flags; | ||
1783 | |||
1784 | local_irq_save(flags); | ||
1785 | |||
1786 | stock = this_cpu_ptr(&memcg_stock); | ||
1781 | drain_stock(stock); | 1787 | drain_stock(stock); |
1782 | clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags); | 1788 | clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags); |
1789 | |||
1790 | local_irq_restore(flags); | ||
1783 | } | 1791 | } |
1784 | 1792 | ||
1785 | /* | 1793 | /* |
@@ -1788,14 +1796,19 @@ static void drain_local_stock(struct work_struct *dummy) | |||
1788 | */ | 1796 | */ |
1789 | static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages) | 1797 | static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages) |
1790 | { | 1798 | { |
1791 | struct memcg_stock_pcp *stock = &get_cpu_var(memcg_stock); | 1799 | struct memcg_stock_pcp *stock; |
1800 | unsigned long flags; | ||
1801 | |||
1802 | local_irq_save(flags); | ||
1792 | 1803 | ||
1804 | stock = this_cpu_ptr(&memcg_stock); | ||
1793 | if (stock->cached != memcg) { /* reset if necessary */ | 1805 | if (stock->cached != memcg) { /* reset if necessary */ |
1794 | drain_stock(stock); | 1806 | drain_stock(stock); |
1795 | stock->cached = memcg; | 1807 | stock->cached = memcg; |
1796 | } | 1808 | } |
1797 | stock->nr_pages += nr_pages; | 1809 | stock->nr_pages += nr_pages; |
1798 | put_cpu_var(memcg_stock); | 1810 | |
1811 | local_irq_restore(flags); | ||
1799 | } | 1812 | } |
1800 | 1813 | ||
1801 | /* | 1814 | /* |