Merge branch 'akpm' (patches from Andrew)
[linux-2.6-block.git] / mm / memcontrol.c
index e79cb59552d9b0076a2c9cbfec3af9ebfa5c06e2..54920cbc46bfdcb87b0a4ae3e6b4538596b6bd58 100644 (file)
@@ -1669,6 +1669,8 @@ static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int
        if (order > PAGE_ALLOC_COSTLY_ORDER)
                return OOM_SKIPPED;
 
+       memcg_memory_event(memcg, MEMCG_OOM);
+
        /*
         * We are in the middle of the charge context here, so we
         * don't want to block when potentially sitting on a callstack
@@ -2250,8 +2252,6 @@ retry:
        if (fatal_signal_pending(current))
                goto force;
 
-       memcg_memory_event(mem_over_limit, MEMCG_OOM);
-
        /*
         * keep retrying as long as the memcg oom killer is able to make
         * a forward progress or bypass the charge if the oom killer
@@ -2460,7 +2460,7 @@ static void memcg_kmem_cache_create_func(struct work_struct *w)
 /*
  * Enqueue the creation of a per-memcg kmem_cache.
  */
-static void __memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
+static void memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
                                               struct kmem_cache *cachep)
 {
        struct memcg_kmem_cache_create_work *cw;
@@ -2478,25 +2478,6 @@ static void __memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
        queue_work(memcg_kmem_cache_wq, &cw->work);
 }
 
-static void memcg_schedule_kmem_cache_create(struct mem_cgroup *memcg,
-                                            struct kmem_cache *cachep)
-{
-       /*
-        * We need to stop accounting when we kmalloc, because if the
-        * corresponding kmalloc cache is not yet created, the first allocation
-        * in __memcg_schedule_kmem_cache_create will recurse.
-        *
-        * However, it is better to enclose the whole function. Depending on
-        * the debugging options enabled, INIT_WORK(), for instance, can
-        * trigger an allocation. This too, will make us recurse. Because at
-        * this point we can't allow ourselves back into memcg_kmem_get_cache,
-        * the safest choice is to do it like this, wrapping the whole function.
-        */
-       current->memcg_kmem_skip_account = 1;
-       __memcg_schedule_kmem_cache_create(memcg, cachep);
-       current->memcg_kmem_skip_account = 0;
-}
-
 static inline bool memcg_kmem_bypass(void)
 {
        if (in_interrupt() || !current->mm || (current->flags & PF_KTHREAD))
@@ -2531,9 +2512,6 @@ struct kmem_cache *memcg_kmem_get_cache(struct kmem_cache *cachep)
        if (memcg_kmem_bypass())
                return cachep;
 
-       if (current->memcg_kmem_skip_account)
-               return cachep;
-
        memcg = get_mem_cgroup_from_current();
        kmemcg_id = READ_ONCE(memcg->kmemcg_id);
        if (kmemcg_id < 0)
@@ -4321,14 +4299,12 @@ static void mem_cgroup_id_remove(struct mem_cgroup *memcg)
 
 static void mem_cgroup_id_get_many(struct mem_cgroup *memcg, unsigned int n)
 {
-       VM_BUG_ON(atomic_read(&memcg->id.ref) <= 0);
-       atomic_add(n, &memcg->id.ref);
+       refcount_add(n, &memcg->id.ref);
 }
 
 static void mem_cgroup_id_put_many(struct mem_cgroup *memcg, unsigned int n)
 {
-       VM_BUG_ON(atomic_read(&memcg->id.ref) < n);
-       if (atomic_sub_and_test(n, &memcg->id.ref)) {
+       if (refcount_sub_and_test(n, &memcg->id.ref)) {
                mem_cgroup_id_remove(memcg);
 
                /* Memcg ID pins CSS */
@@ -4545,7 +4521,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
        }
 
        /* Online state pins memcg ID, memcg ID pins CSS */
-       atomic_set(&memcg->id.ref, 1);
+       refcount_set(&memcg->id.ref, 1);
        css_get(css);
        return 0;
 }
@@ -4573,6 +4549,8 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
        memcg_offline_kmem(memcg);
        wb_memcg_offline(memcg);
 
+       drain_all_stock(memcg);
+
        mem_cgroup_id_put(memcg);
 }
 
@@ -4750,7 +4728,7 @@ static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
        /* shmem/tmpfs may report page out on swap: account for that too. */
        if (shmem_mapping(mapping)) {
                page = find_get_entry(mapping, pgoff);
-               if (radix_tree_exceptional_entry(page)) {
+               if (xa_is_value(page)) {
                        swp_entry_t swp = radix_to_swp_entry(page);
                        if (do_memsw_account())
                                *entry = swp;
@@ -5595,6 +5573,13 @@ static int memory_stat_show(struct seq_file *m, void *v)
        seq_printf(m, "pgfault %lu\n", acc.events[PGFAULT]);
        seq_printf(m, "pgmajfault %lu\n", acc.events[PGMAJFAULT]);
 
+       seq_printf(m, "workingset_refault %lu\n",
+                  acc.stat[WORKINGSET_REFAULT]);
+       seq_printf(m, "workingset_activate %lu\n",
+                  acc.stat[WORKINGSET_ACTIVATE]);
+       seq_printf(m, "workingset_nodereclaim %lu\n",
+                  acc.stat[WORKINGSET_NODERECLAIM]);
+
        seq_printf(m, "pgrefill %lu\n", acc.events[PGREFILL]);
        seq_printf(m, "pgscan %lu\n", acc.events[PGSCAN_KSWAPD] +
                   acc.events[PGSCAN_DIRECT]);
@@ -5605,13 +5590,6 @@ static int memory_stat_show(struct seq_file *m, void *v)
        seq_printf(m, "pglazyfree %lu\n", acc.events[PGLAZYFREE]);
        seq_printf(m, "pglazyfreed %lu\n", acc.events[PGLAZYFREED]);
 
-       seq_printf(m, "workingset_refault %lu\n",
-                  acc.stat[WORKINGSET_REFAULT]);
-       seq_printf(m, "workingset_activate %lu\n",
-                  acc.stat[WORKINGSET_ACTIVATE]);
-       seq_printf(m, "workingset_nodereclaim %lu\n",
-                  acc.stat[WORKINGSET_NODERECLAIM]);
-
        return 0;
 }
 
@@ -6377,7 +6355,7 @@ subsys_initcall(mem_cgroup_init);
 #ifdef CONFIG_MEMCG_SWAP
 static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg)
 {
-       while (!atomic_inc_not_zero(&memcg->id.ref)) {
+       while (!refcount_inc_not_zero(&memcg->id.ref)) {
                /*
                 * The root cgroup cannot be destroyed, so it's refcount must
                 * always be >= 1.