.. | .. |
---|
69 | 69 | #include <net/sock.h> |
---|
70 | 70 | #include <net/ip.h> |
---|
71 | 71 | #include "slab.h" |
---|
| 72 | +#include <linux/locallock.h> |
---|
72 | 73 | |
---|
73 | 74 | #include <linux/uaccess.h> |
---|
74 | 75 | |
---|
.. | .. |
---|
93 | 94 | #else |
---|
94 | 95 | #define do_swap_account 0 |
---|
95 | 96 | #endif |
---|
| 97 | + |
---|
| 98 | +static DEFINE_LOCAL_IRQ_LOCK(event_lock); |
---|
96 | 99 | |
---|
97 | 100 | /* Whether legacy memory+swap accounting is active */ |
---|
98 | 101 | static bool do_memsw_account(void) |
---|
.. | .. |
---|
2084 | 2087 | * as well as workers from this path always operate on the local |
---|
2085 | 2088 | * per-cpu data. CPU up doesn't touch memcg_stock at all. |
---|
2086 | 2089 | */ |
---|
2087 | | - curcpu = get_cpu(); |
---|
| 2090 | + curcpu = get_cpu_light(); |
---|
2088 | 2091 | for_each_online_cpu(cpu) { |
---|
2089 | 2092 | struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu); |
---|
2090 | 2093 | struct mem_cgroup *memcg; |
---|
.. | .. |
---|
2104 | 2107 | } |
---|
2105 | 2108 | css_put(&memcg->css); |
---|
2106 | 2109 | } |
---|
2107 | | - put_cpu(); |
---|
| 2110 | + put_cpu_light(); |
---|
2108 | 2111 | mutex_unlock(&percpu_charge_mutex); |
---|
2109 | 2112 | } |
---|
2110 | 2113 | |
---|
.. | .. |
---|
4933 | 4936 | |
---|
4934 | 4937 | ret = 0; |
---|
4935 | 4938 | |
---|
4936 | | - local_irq_disable(); |
---|
| 4939 | + local_lock_irq(event_lock); |
---|
4937 | 4940 | mem_cgroup_charge_statistics(to, page, compound, nr_pages); |
---|
4938 | 4941 | memcg_check_events(to, page); |
---|
4939 | 4942 | mem_cgroup_charge_statistics(from, page, compound, -nr_pages); |
---|
4940 | 4943 | memcg_check_events(from, page); |
---|
4941 | | - local_irq_enable(); |
---|
| 4944 | + local_unlock_irq(event_lock); |
---|
4942 | 4945 | out_unlock: |
---|
4943 | 4946 | unlock_page(page); |
---|
4944 | 4947 | out: |
---|
.. | .. |
---|
6057 | 6060 | |
---|
6058 | 6061 | commit_charge(page, memcg, lrucare); |
---|
6059 | 6062 | |
---|
6060 | | - local_irq_disable(); |
---|
| 6063 | + local_lock_irq(event_lock); |
---|
6061 | 6064 | mem_cgroup_charge_statistics(memcg, page, compound, nr_pages); |
---|
6062 | 6065 | memcg_check_events(memcg, page); |
---|
6063 | | - local_irq_enable(); |
---|
| 6066 | + local_unlock_irq(event_lock); |
---|
6064 | 6067 | |
---|
6065 | 6068 | if (do_memsw_account() && PageSwapCache(page)) { |
---|
6066 | 6069 | swp_entry_t entry = { .val = page_private(page) }; |
---|
.. | .. |
---|
6129 | 6132 | memcg_oom_recover(ug->memcg); |
---|
6130 | 6133 | } |
---|
6131 | 6134 | |
---|
6132 | | - local_irq_save(flags); |
---|
| 6135 | + local_lock_irqsave(event_lock, flags); |
---|
6133 | 6136 | __mod_memcg_state(ug->memcg, MEMCG_RSS, -ug->nr_anon); |
---|
6134 | 6137 | __mod_memcg_state(ug->memcg, MEMCG_CACHE, -ug->nr_file); |
---|
6135 | 6138 | __mod_memcg_state(ug->memcg, MEMCG_RSS_HUGE, -ug->nr_huge); |
---|
.. | .. |
---|
6137 | 6140 | __count_memcg_events(ug->memcg, PGPGOUT, ug->pgpgout); |
---|
6138 | 6141 | __this_cpu_add(ug->memcg->stat_cpu->nr_page_events, nr_pages); |
---|
6139 | 6142 | memcg_check_events(ug->memcg, ug->dummy_page); |
---|
6140 | | - local_irq_restore(flags); |
---|
| 6143 | + local_unlock_irqrestore(event_lock, flags); |
---|
6141 | 6144 | |
---|
6142 | 6145 | if (!mem_cgroup_is_root(ug->memcg)) |
---|
6143 | 6146 | css_put_many(&ug->memcg->css, nr_pages); |
---|
.. | .. |
---|
6300 | 6303 | |
---|
6301 | 6304 | commit_charge(newpage, memcg, false); |
---|
6302 | 6305 | |
---|
6303 | | - local_irq_save(flags); |
---|
| 6306 | + local_lock_irqsave(event_lock, flags); |
---|
6304 | 6307 | mem_cgroup_charge_statistics(memcg, newpage, compound, nr_pages); |
---|
6305 | 6308 | memcg_check_events(memcg, newpage); |
---|
6306 | | - local_irq_restore(flags); |
---|
| 6309 | + local_unlock_irqrestore(event_lock, flags); |
---|
6307 | 6310 | } |
---|
6308 | 6311 | |
---|
6309 | 6312 | DEFINE_STATIC_KEY_FALSE(memcg_sockets_enabled_key); |
---|
.. | .. |
---|
6485 | 6488 | struct mem_cgroup *memcg, *swap_memcg; |
---|
6486 | 6489 | unsigned int nr_entries; |
---|
6487 | 6490 | unsigned short oldid; |
---|
| 6491 | + unsigned long flags; |
---|
6488 | 6492 | |
---|
6489 | 6493 | VM_BUG_ON_PAGE(PageLRU(page), page); |
---|
6490 | 6494 | VM_BUG_ON_PAGE(page_count(page), page); |
---|
.. | .. |
---|
6530 | 6534 | * important here to have the interrupts disabled because it is the |
---|
6531 | 6535 | * only synchronisation we have for updating the per-CPU variables. |
---|
6532 | 6536 | */ |
---|
| 6537 | + local_lock_irqsave(event_lock, flags); |
---|
| 6538 | +#ifndef CONFIG_PREEMPT_RT_BASE |
---|
6533 | 6539 | VM_BUG_ON(!irqs_disabled()); |
---|
| 6540 | +#endif |
---|
6534 | 6541 | mem_cgroup_charge_statistics(memcg, page, PageTransHuge(page), |
---|
6535 | 6542 | -nr_entries); |
---|
6536 | 6543 | memcg_check_events(memcg, page); |
---|
| 6544 | + local_unlock_irqrestore(event_lock, flags); |
---|
6537 | 6545 | |
---|
6538 | 6546 | if (!mem_cgroup_is_root(memcg)) |
---|
6539 | 6547 | css_put_many(&memcg->css, nr_entries); |
---|