Merge tag 'nfsd-5.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
[linux-2.6-microblaze.git] / mm / memcontrol.c
index b323588..c100265 100644 (file)
@@ -255,10 +255,8 @@ struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr)
 #ifdef CONFIG_MEMCG_KMEM
 extern spinlock_t css_set_lock;
 
-static int __memcg_kmem_charge(struct mem_cgroup *memcg, gfp_t gfp,
-                              unsigned int nr_pages);
-static void __memcg_kmem_uncharge(struct mem_cgroup *memcg,
-                                 unsigned int nr_pages);
+static void obj_cgroup_uncharge_pages(struct obj_cgroup *objcg,
+                                     unsigned int nr_pages);
 
 static void obj_cgroup_release(struct percpu_ref *ref)
 {
@@ -295,7 +293,7 @@ static void obj_cgroup_release(struct percpu_ref *ref)
        spin_lock_irqsave(&css_set_lock, flags);
        memcg = obj_cgroup_memcg(objcg);
        if (nr_pages)
-               __memcg_kmem_uncharge(memcg, nr_pages);
+               obj_cgroup_uncharge_pages(objcg, nr_pages);
        list_del(&objcg->list);
        mem_cgroup_put(memcg);
        spin_unlock_irqrestore(&css_set_lock, flags);
@@ -865,18 +863,22 @@ void __mod_lruvec_page_state(struct page *page, enum node_stat_item idx,
                             int val)
 {
        struct page *head = compound_head(page); /* rmap on tail pages */
-       struct mem_cgroup *memcg = page_memcg(head);
+       struct mem_cgroup *memcg;
        pg_data_t *pgdat = page_pgdat(page);
        struct lruvec *lruvec;
 
+       rcu_read_lock();
+       memcg = page_memcg(head);
        /* Untracked pages have no memcg, no lruvec. Update only the node */
        if (!memcg) {
+               rcu_read_unlock();
                __mod_node_page_state(pgdat, idx, val);
                return;
        }
 
        lruvec = mem_cgroup_lruvec(memcg, pgdat);
        __mod_lruvec_state(lruvec, idx, val);
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL(__mod_lruvec_page_state);
 
@@ -1051,20 +1053,6 @@ static __always_inline struct mem_cgroup *active_memcg(void)
                return current->active_memcg;
 }
 
-static __always_inline struct mem_cgroup *get_active_memcg(void)
-{
-       struct mem_cgroup *memcg;
-
-       rcu_read_lock();
-       memcg = active_memcg();
-       /* remote memcg must hold a ref. */
-       if (memcg && WARN_ON_ONCE(!css_tryget(&memcg->css)))
-               memcg = root_mem_cgroup;
-       rcu_read_unlock();
-
-       return memcg;
-}
-
 static __always_inline bool memcg_kmem_bypass(void)
 {
        /* Allow remote memcg charging from any context. */
@@ -1078,20 +1066,6 @@ static __always_inline bool memcg_kmem_bypass(void)
        return false;
 }
 
-/**
- * If active memcg is set, do not fallback to current->mm->memcg.
- */
-static __always_inline struct mem_cgroup *get_mem_cgroup_from_current(void)
-{
-       if (memcg_kmem_bypass())
-               return NULL;
-
-       if (unlikely(active_memcg()))
-               return get_active_memcg();
-
-       return get_mem_cgroup_from_mm(current->mm);
-}
-
 /**
  * mem_cgroup_iter - iterate over memory cgroup hierarchy
  * @root: hierarchy root
@@ -2364,39 +2338,39 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
        mutex_unlock(&percpu_charge_mutex);
 }
 
-static int memcg_hotplug_cpu_dead(unsigned int cpu)
+static void memcg_flush_lruvec_page_state(struct mem_cgroup *memcg, int cpu)
 {
-       struct memcg_stock_pcp *stock;
-       struct mem_cgroup *memcg;
-
-       stock = &per_cpu(memcg_stock, cpu);
-       drain_stock(stock);
+       int nid;
 
-       for_each_mem_cgroup(memcg) {
+       for_each_node(nid) {
+               struct mem_cgroup_per_node *pn = memcg->nodeinfo[nid];
+               unsigned long stat[NR_VM_NODE_STAT_ITEMS];
+               struct batched_lruvec_stat *lstatc;
                int i;
 
+               lstatc = per_cpu_ptr(pn->lruvec_stat_cpu, cpu);
                for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++) {
-                       int nid;
+                       stat[i] = lstatc->count[i];
+                       lstatc->count[i] = 0;
+               }
 
-                       for_each_node(nid) {
-                               struct batched_lruvec_stat *lstatc;
-                               struct mem_cgroup_per_node *pn;
-                               long x;
+               do {
+                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+                               atomic_long_add(stat[i], &pn->lruvec_stat[i]);
+               } while ((pn = parent_nodeinfo(pn, nid)));
+       }
+}
 
-                               pn = memcg->nodeinfo[nid];
-                               lstatc = per_cpu_ptr(pn->lruvec_stat_cpu, cpu);
+static int memcg_hotplug_cpu_dead(unsigned int cpu)
+{
+       struct memcg_stock_pcp *stock;
+       struct mem_cgroup *memcg;
 
-                               x = lstatc->count[i];
-                               lstatc->count[i] = 0;
+       stock = &per_cpu(memcg_stock, cpu);
+       drain_stock(stock);
 
-                               if (x) {
-                                       do {
-                                               atomic_long_add(x, &pn->lruvec_stat[i]);
-                                       } while ((pn = parent_nodeinfo(pn, nid)));
-                               }
-                       }
-               }
-       }
+       for_each_mem_cgroup(memcg)
+               memcg_flush_lruvec_page_state(memcg, cpu);
 
        return 0;
 }
@@ -2874,6 +2848,20 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg)
        page->memcg_data = (unsigned long)memcg;
 }
 
+static struct mem_cgroup *get_mem_cgroup_from_objcg(struct obj_cgroup *objcg)
+{
+       struct mem_cgroup *memcg;
+
+       rcu_read_lock();
+retry:
+       memcg = obj_cgroup_memcg(objcg);
+       if (unlikely(!css_tryget(&memcg->css)))
+               goto retry;
+       rcu_read_unlock();
+
+       return memcg;
+}
+
 #ifdef CONFIG_MEMCG_KMEM
 int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s,
                                 gfp_t gfp, bool new_page)
@@ -3025,23 +3013,45 @@ static void memcg_free_cache_id(int id)
        ida_simple_remove(&memcg_cache_ida, id);
 }
 
-/**
- * __memcg_kmem_charge: charge a number of kernel pages to a memcg
- * @memcg: memory cgroup to charge
+/*
+ * obj_cgroup_uncharge_pages: uncharge a number of kernel pages from a objcg
+ * @objcg: object cgroup to uncharge
+ * @nr_pages: number of pages to uncharge
+ */
+static void obj_cgroup_uncharge_pages(struct obj_cgroup *objcg,
+                                     unsigned int nr_pages)
+{
+       struct mem_cgroup *memcg;
+
+       memcg = get_mem_cgroup_from_objcg(objcg);
+
+       if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
+               page_counter_uncharge(&memcg->kmem, nr_pages);
+       refill_stock(memcg, nr_pages);
+
+       css_put(&memcg->css);
+}
+
+/*
+ * obj_cgroup_charge_pages: charge a number of kernel pages to a objcg
+ * @objcg: object cgroup to charge
  * @gfp: reclaim mode
  * @nr_pages: number of pages to charge
  *
  * Returns 0 on success, an error code on failure.
  */
-static int __memcg_kmem_charge(struct mem_cgroup *memcg, gfp_t gfp,
-                              unsigned int nr_pages)
+static int obj_cgroup_charge_pages(struct obj_cgroup *objcg, gfp_t gfp,
+                                  unsigned int nr_pages)
 {
        struct page_counter *counter;
+       struct mem_cgroup *memcg;
        int ret;
 
+       memcg = get_mem_cgroup_from_objcg(objcg);
+
        ret = try_charge(memcg, gfp, nr_pages);
        if (ret)
-               return ret;
+               goto out;
 
        if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) &&
            !page_counter_try_charge(&memcg->kmem, nr_pages, &counter)) {
@@ -3053,25 +3063,15 @@ static int __memcg_kmem_charge(struct mem_cgroup *memcg, gfp_t gfp,
                 */
                if (gfp & __GFP_NOFAIL) {
                        page_counter_charge(&memcg->kmem, nr_pages);
-                       return 0;
+                       goto out;
                }
                cancel_charge(memcg, nr_pages);
-               return -ENOMEM;
+               ret = -ENOMEM;
        }
-       return 0;
-}
-
-/**
- * __memcg_kmem_uncharge: uncharge a number of kernel pages from a memcg
- * @memcg: memcg to uncharge
- * @nr_pages: number of pages to uncharge
- */
-static void __memcg_kmem_uncharge(struct mem_cgroup *memcg, unsigned int nr_pages)
-{
-       if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
-               page_counter_uncharge(&memcg->kmem, nr_pages);
+out:
+       css_put(&memcg->css);
 
-       refill_stock(memcg, nr_pages);
+       return ret;
 }
 
 /**
@@ -3084,18 +3084,18 @@ static void __memcg_kmem_uncharge(struct mem_cgroup *memcg, unsigned int nr_page
  */
 int __memcg_kmem_charge_page(struct page *page, gfp_t gfp, int order)
 {
-       struct mem_cgroup *memcg;
+       struct obj_cgroup *objcg;
        int ret = 0;
 
-       memcg = get_mem_cgroup_from_current();
-       if (memcg && !mem_cgroup_is_root(memcg)) {
-               ret = __memcg_kmem_charge(memcg, gfp, 1 << order);
+       objcg = get_obj_cgroup_from_current();
+       if (objcg) {
+               ret = obj_cgroup_charge_pages(objcg, gfp, 1 << order);
                if (!ret) {
-                       page->memcg_data = (unsigned long)memcg |
+                       page->memcg_data = (unsigned long)objcg |
                                MEMCG_DATA_KMEM;
                        return 0;
                }
-               css_put(&memcg->css);
+               obj_cgroup_put(objcg);
        }
        return ret;
 }
@@ -3107,16 +3107,16 @@ int __memcg_kmem_charge_page(struct page *page, gfp_t gfp, int order)
  */
 void __memcg_kmem_uncharge_page(struct page *page, int order)
 {
-       struct mem_cgroup *memcg = page_memcg(page);
+       struct obj_cgroup *objcg;
        unsigned int nr_pages = 1 << order;
 
-       if (!memcg)
+       if (!PageMemcgKmem(page))
                return;
 
-       VM_BUG_ON_PAGE(mem_cgroup_is_root(memcg), page);
-       __memcg_kmem_uncharge(memcg, nr_pages);
+       objcg = __page_objcg(page);
+       obj_cgroup_uncharge_pages(objcg, nr_pages);
        page->memcg_data = 0;
-       css_put(&memcg->css);
+       obj_cgroup_put(objcg);
 }
 
 static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
@@ -3149,11 +3149,8 @@ static void drain_obj_stock(struct memcg_stock_pcp *stock)
                unsigned int nr_pages = stock->nr_bytes >> PAGE_SHIFT;
                unsigned int nr_bytes = stock->nr_bytes & (PAGE_SIZE - 1);
 
-               if (nr_pages) {
-                       rcu_read_lock();
-                       __memcg_kmem_uncharge(obj_cgroup_memcg(old), nr_pages);
-                       rcu_read_unlock();
-               }
+               if (nr_pages)
+                       obj_cgroup_uncharge_pages(old, nr_pages);
 
                /*
                 * The leftover is flushed to the centralized per-memcg value.
@@ -3211,7 +3208,6 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
 
 int obj_cgroup_charge(struct obj_cgroup *objcg, gfp_t gfp, size_t size)
 {
-       struct mem_cgroup *memcg;
        unsigned int nr_pages, nr_bytes;
        int ret;
 
@@ -3228,24 +3224,16 @@ int obj_cgroup_charge(struct obj_cgroup *objcg, gfp_t gfp, size_t size)
         * refill_obj_stock(), called from this function or
         * independently later.
         */
-       rcu_read_lock();
-retry:
-       memcg = obj_cgroup_memcg(objcg);
-       if (unlikely(!css_tryget(&memcg->css)))
-               goto retry;
-       rcu_read_unlock();
-
        nr_pages = size >> PAGE_SHIFT;
        nr_bytes = size & (PAGE_SIZE - 1);
 
        if (nr_bytes)
                nr_pages += 1;
 
-       ret = __memcg_kmem_charge(memcg, gfp, nr_pages);
+       ret = obj_cgroup_charge_pages(objcg, gfp, nr_pages);
        if (!ret && nr_bytes)
                refill_obj_stock(objcg, PAGE_SIZE - nr_bytes);
 
-       css_put(&memcg->css);
        return ret;
 }
 
@@ -3269,7 +3257,11 @@ void split_page_memcg(struct page *head, unsigned int nr)
 
        for (i = 1; i < nr; i++)
                head[i].memcg_data = head->memcg_data;
-       css_get_many(&memcg->css, nr - 1);
+
+       if (PageMemcgKmem(head))
+               obj_cgroup_get_many(__page_objcg(head), nr - 1);
+       else
+               css_get_many(&memcg->css, nr - 1);
 }
 
 #ifdef CONFIG_MEMCG_SWAP
@@ -3583,27 +3575,6 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
        }
 }
 
-static void memcg_flush_lruvec_page_state(struct mem_cgroup *memcg)
-{
-       int node;
-
-       for_each_node(node) {
-               struct mem_cgroup_per_node *pn = memcg->nodeinfo[node];
-               unsigned long stat[NR_VM_NODE_STAT_ITEMS] = { 0 };
-               struct mem_cgroup_per_node *pi;
-               int cpu, i;
-
-               for_each_online_cpu(cpu)
-                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
-                               stat[i] += per_cpu(
-                                       pn->lruvec_stat_cpu->count[i], cpu);
-
-               for (pi = pn; pi; pi = parent_nodeinfo(pi, node))
-                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
-                               atomic_long_add(stat[i], &pi->lruvec_stat[i]);
-       }
-}
-
 #ifdef CONFIG_MEMCG_KMEM
 static int memcg_online_kmem(struct mem_cgroup *memcg)
 {
@@ -5139,12 +5110,15 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
 
 static void mem_cgroup_free(struct mem_cgroup *memcg)
 {
+       int cpu;
+
        memcg_wb_domain_exit(memcg);
        /*
         * Flush percpu lruvec stats to guarantee the value
         * correctness on parent's and all ancestor levels.
         */
-       memcg_flush_lruvec_page_state(memcg);
+       for_each_online_cpu(cpu)
+               memcg_flush_lruvec_page_state(memcg, cpu);
        __mem_cgroup_free(memcg);
 }
 
@@ -6662,6 +6636,27 @@ void mem_cgroup_calculate_protection(struct mem_cgroup *root,
                        atomic_long_read(&parent->memory.children_low_usage)));
 }
 
+static int __mem_cgroup_charge(struct page *page, struct mem_cgroup *memcg,
+                              gfp_t gfp)
+{
+       unsigned int nr_pages = thp_nr_pages(page);
+       int ret;
+
+       ret = try_charge(memcg, gfp, nr_pages);
+       if (ret)
+               goto out;
+
+       css_get(&memcg->css);
+       commit_charge(page, memcg);
+
+       local_irq_disable();
+       mem_cgroup_charge_statistics(memcg, page, nr_pages);
+       memcg_check_events(memcg, page);
+       local_irq_enable();
+out:
+       return ret;
+}
+
 /**
  * mem_cgroup_charge - charge a newly allocated page to a cgroup
  * @page: page to charge
@@ -6671,55 +6666,71 @@ void mem_cgroup_calculate_protection(struct mem_cgroup *root,
  * Try to charge @page to the memcg that @mm belongs to, reclaiming
  * pages according to @gfp_mask if necessary.
  *
+ * Do not use this for pages allocated for swapin.
+ *
  * Returns 0 on success. Otherwise, an error code is returned.
  */
 int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
 {
-       unsigned int nr_pages = thp_nr_pages(page);
-       struct mem_cgroup *memcg = NULL;
-       int ret = 0;
+       struct mem_cgroup *memcg;
+       int ret;
 
        if (mem_cgroup_disabled())
-               goto out;
+               return 0;
 
-       if (PageSwapCache(page)) {
-               swp_entry_t ent = { .val = page_private(page), };
-               unsigned short id;
+       memcg = get_mem_cgroup_from_mm(mm);
+       ret = __mem_cgroup_charge(page, memcg, gfp_mask);
+       css_put(&memcg->css);
 
-               /*
-                * Every swap fault against a single page tries to charge the
-                * page, bail as early as possible.  shmem_unuse() encounters
-                * already charged pages, too.  page and memcg binding is
-                * protected by the page lock, which serializes swap cache
-                * removal, which in turn serializes uncharging.
-                */
-               VM_BUG_ON_PAGE(!PageLocked(page), page);
-               if (page_memcg(compound_head(page)))
-                       goto out;
+       return ret;
+}
 
-               id = lookup_swap_cgroup_id(ent);
-               rcu_read_lock();
-               memcg = mem_cgroup_from_id(id);
-               if (memcg && !css_tryget_online(&memcg->css))
-                       memcg = NULL;
-               rcu_read_unlock();
-       }
+/**
+ * mem_cgroup_swapin_charge_page - charge a newly allocated page for swapin
+ * @page: page to charge
+ * @mm: mm context of the victim
+ * @gfp: reclaim mode
+ * @entry: swap entry for which the page is allocated
+ *
+ * This function charges a page allocated for swapin. Please call this before
+ * adding the page to the swapcache.
+ *
+ * Returns 0 on success. Otherwise, an error code is returned.
+ */
+int mem_cgroup_swapin_charge_page(struct page *page, struct mm_struct *mm,
+                                 gfp_t gfp, swp_entry_t entry)
+{
+       struct mem_cgroup *memcg;
+       unsigned short id;
+       int ret;
 
-       if (!memcg)
-               memcg = get_mem_cgroup_from_mm(mm);
+       if (mem_cgroup_disabled())
+               return 0;
 
-       ret = try_charge(memcg, gfp_mask, nr_pages);
-       if (ret)
-               goto out_put;
+       id = lookup_swap_cgroup_id(entry);
+       rcu_read_lock();
+       memcg = mem_cgroup_from_id(id);
+       if (!memcg || !css_tryget_online(&memcg->css))
+               memcg = get_mem_cgroup_from_mm(mm);
+       rcu_read_unlock();
 
-       css_get(&memcg->css);
-       commit_charge(page, memcg);
+       ret = __mem_cgroup_charge(page, memcg, gfp);
 
-       local_irq_disable();
-       mem_cgroup_charge_statistics(memcg, page, nr_pages);
-       memcg_check_events(memcg, page);
-       local_irq_enable();
+       css_put(&memcg->css);
+       return ret;
+}
 
+/*
+ * mem_cgroup_swapin_uncharge_swap - uncharge swap slot
+ * @entry: swap entry for which the page is charged
+ *
+ * Call this function after successfully adding the charged page to swapcache.
+ *
+ * Note: This function assumes the page for which swap slot is being uncharged
+ * is order 0 page.
+ */
+void mem_cgroup_swapin_uncharge_swap(swp_entry_t entry)
+{
        /*
         * Cgroup1's unified memory+swap counter has been charged with the
         * new swapcache page, finish the transfer by uncharging the swap
@@ -6732,25 +6743,19 @@ int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
         * correspond 1:1 to page and swap slot lifetimes: we charge the
         * page to memory here, and uncharge swap when the slot is freed.
         */
-       if (do_memsw_account() && PageSwapCache(page)) {
-               swp_entry_t entry = { .val = page_private(page) };
+       if (!mem_cgroup_disabled() && do_memsw_account()) {
                /*
                 * The swap entry might not get freed for a long time,
                 * let's not wait for it.  The page already received a
                 * memory+swap charge, drop the swap entry duplicate.
                 */
-               mem_cgroup_uncharge_swap(entry, nr_pages);
+               mem_cgroup_uncharge_swap(entry, 1);
        }
-
-out_put:
-       css_put(&memcg->css);
-out:
-       return ret;
 }
 
 struct uncharge_gather {
        struct mem_cgroup *memcg;
-       unsigned long nr_pages;
+       unsigned long nr_memory;
        unsigned long pgpgout;
        unsigned long nr_kmem;
        struct page *dummy_page;
@@ -6765,10 +6770,10 @@ static void uncharge_batch(const struct uncharge_gather *ug)
 {
        unsigned long flags;
 
-       if (!mem_cgroup_is_root(ug->memcg)) {
-               page_counter_uncharge(&ug->memcg->memory, ug->nr_pages);
+       if (ug->nr_memory) {
+               page_counter_uncharge(&ug->memcg->memory, ug->nr_memory);
                if (do_memsw_account())
-                       page_counter_uncharge(&ug->memcg->memsw, ug->nr_pages);
+                       page_counter_uncharge(&ug->memcg->memsw, ug->nr_memory);
                if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) && ug->nr_kmem)
                        page_counter_uncharge(&ug->memcg->kmem, ug->nr_kmem);
                memcg_oom_recover(ug->memcg);
@@ -6776,7 +6781,7 @@ static void uncharge_batch(const struct uncharge_gather *ug)
 
        local_irq_save(flags);
        __count_memcg_events(ug->memcg, PGPGOUT, ug->pgpgout);
-       __this_cpu_add(ug->memcg->vmstats_percpu->nr_page_events, ug->nr_pages);
+       __this_cpu_add(ug->memcg->vmstats_percpu->nr_page_events, ug->nr_memory);
        memcg_check_events(ug->memcg, ug->dummy_page);
        local_irq_restore(flags);
 
@@ -6787,40 +6792,60 @@ static void uncharge_batch(const struct uncharge_gather *ug)
 static void uncharge_page(struct page *page, struct uncharge_gather *ug)
 {
        unsigned long nr_pages;
+       struct mem_cgroup *memcg;
+       struct obj_cgroup *objcg;
 
        VM_BUG_ON_PAGE(PageLRU(page), page);
 
-       if (!page_memcg(page))
-               return;
-
        /*
         * Nobody should be changing or seriously looking at
-        * page_memcg(page) at this point, we have fully
+        * page memcg or objcg at this point, we have fully
         * exclusive access to the page.
         */
+       if (PageMemcgKmem(page)) {
+               objcg = __page_objcg(page);
+               /*
+                * This get matches the put at the end of the function and
+                * kmem pages do not hold memcg references anymore.
+                */
+               memcg = get_mem_cgroup_from_objcg(objcg);
+       } else {
+               memcg = __page_memcg(page);
+       }
 
-       if (ug->memcg != page_memcg(page)) {
+       if (!memcg)
+               return;
+
+       if (ug->memcg != memcg) {
                if (ug->memcg) {
                        uncharge_batch(ug);
                        uncharge_gather_clear(ug);
                }
-               ug->memcg = page_memcg(page);
+               ug->memcg = memcg;
+               ug->dummy_page = page;
 
                /* pairs with css_put in uncharge_batch */
-               css_get(&ug->memcg->css);
+               css_get(&memcg->css);
        }
 
        nr_pages = compound_nr(page);
-       ug->nr_pages += nr_pages;
 
-       if (PageMemcgKmem(page))
+       if (PageMemcgKmem(page)) {
+               ug->nr_memory += nr_pages;
                ug->nr_kmem += nr_pages;
-       else
+
+               page->memcg_data = 0;
+               obj_cgroup_put(objcg);
+       } else {
+               /* LRU pages aren't accounted at the root level */
+               if (!mem_cgroup_is_root(memcg))
+                       ug->nr_memory += nr_pages;
                ug->pgpgout++;
 
-       ug->dummy_page = page;
-       page->memcg_data = 0;
-       css_put(&ug->memcg->css);
+               page->memcg_data = 0;
+       }
+
+       css_put(&memcg->css);
 }
 
 /**