]> Pileus Git - ~andy/linux/blobdiff - mm/memcontrol.c
Bluetooth: Keep chan->state and sk->sk_state in sync
[~andy/linux] / mm / memcontrol.c
index ce7b35d024e9e8701c44f1d6f22a44fc62084fa4..6aff93c98acaf6020eabd37f2e9b49a04135f187 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/bit_spinlock.h>
 #include <linux/rcupdate.h>
 #include <linux/limits.h>
+#include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
 #include <linux/slab.h>
@@ -686,8 +687,8 @@ static bool __memcg_event_check(struct mem_cgroup *memcg, int target)
 {
        unsigned long val, next;
 
-       val = this_cpu_read(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT]);
-       next = this_cpu_read(memcg->stat->targets[target]);
+       val = __this_cpu_read(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT]);
+       next = __this_cpu_read(memcg->stat->targets[target]);
        /* from time_after() in jiffies.h */
        return ((long)next - (long)val < 0);
 }
@@ -696,7 +697,7 @@ static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)
 {
        unsigned long val, next;
 
-       val = this_cpu_read(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT]);
+       val = __this_cpu_read(memcg->stat->events[MEM_CGROUP_EVENTS_COUNT]);
 
        switch (target) {
        case MEM_CGROUP_TARGET_THRESH:
@@ -712,7 +713,7 @@ static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)
                return;
        }
 
-       this_cpu_write(memcg->stat->targets[target], next);
+       __this_cpu_write(memcg->stat->targets[target], next);
 }
 
 /*
@@ -721,6 +722,7 @@ static void __mem_cgroup_target_update(struct mem_cgroup *memcg, int target)
  */
 static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
 {
+       preempt_disable();
        /* threshold event is triggered in finer grain than soft limit */
        if (unlikely(__memcg_event_check(memcg, MEM_CGROUP_TARGET_THRESH))) {
                mem_cgroup_threshold(memcg);
@@ -740,6 +742,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
                }
 #endif
        }
+       preempt_enable();
 }
 
 static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
@@ -993,6 +996,16 @@ void mem_cgroup_add_lru_list(struct page *page, enum lru_list lru)
                return;
        pc = lookup_page_cgroup(page);
        VM_BUG_ON(PageCgroupAcctLRU(pc));
+       /*
+        * putback:                             charge:
+        * SetPageLRU                           SetPageCgroupUsed
+        * smp_mb                               smp_mb
+        * PageCgroupUsed && add to memcg LRU   PageLRU && add to memcg LRU
+        *
+        * Ensure that one of the two sides adds the page to the memcg
+        * LRU during a race.
+        */
+       smp_mb();
        if (!PageCgroupUsed(pc))
                return;
        /* Ensure pc->mem_cgroup is visible after reading PCG_USED. */
@@ -1044,7 +1057,16 @@ static void mem_cgroup_lru_add_after_commit(struct page *page)
        unsigned long flags;
        struct zone *zone = page_zone(page);
        struct page_cgroup *pc = lookup_page_cgroup(page);
-
+       /*
+        * putback:                             charge:
+        * SetPageLRU                           SetPageCgroupUsed
+        * smp_mb                               smp_mb
+        * PageCgroupUsed && add to memcg LRU   PageLRU && add to memcg LRU
+        *
+        * Ensure that one of the two sides adds the page to the memcg
+        * LRU during a race.
+        */
+       smp_mb();
        /* taking care of that the page is added to LRU while we commit it */
        if (likely(!PageLRU(page)))
                return;