]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - mm/memcontrol.c
memcg: fix error path of mem_cgroup_move_parent
[linux-2.6-omap-h63xx.git] / mm / memcontrol.c
index b6651277116737e3012b3ecca84aa6382b1a1be9..7be9b35d7ffb293ac6296354ea1e3493d5ef09d6 100644 (file)
@@ -994,14 +994,15 @@ static int mem_cgroup_move_account(struct page_cgroup *pc,
        if (pc->mem_cgroup != from)
                goto out;
 
-       css_put(&from->css);
        res_counter_uncharge(&from->res, PAGE_SIZE);
        mem_cgroup_charge_statistics(from, pc, false);
        if (do_swap_account)
                res_counter_uncharge(&from->memsw, PAGE_SIZE);
+       css_put(&from->css);
+
+       css_get(&to->css);
        pc->mem_cgroup = to;
        mem_cgroup_charge_statistics(to, pc, true);
-       css_get(&to->css);
        ret = 0;
 out:
        unlock_page_cgroup(pc);
@@ -1034,8 +1035,10 @@ static int mem_cgroup_move_parent(struct page_cgroup *pc,
        if (ret || !parent)
                return ret;
 
-       if (!get_page_unless_zero(page))
-               return -EBUSY;
+       if (!get_page_unless_zero(page)) {
+               ret = -EBUSY;
+               goto uncharge;
+       }
 
        ret = isolate_lru_page(page);
 
@@ -1044,19 +1047,23 @@ static int mem_cgroup_move_parent(struct page_cgroup *pc,
 
        ret = mem_cgroup_move_account(pc, child, parent);
 
-       /* drop extra refcnt by try_charge() (move_account increment one) */
-       css_put(&parent->css);
        putback_lru_page(page);
        if (!ret) {
                put_page(page);
+               /* drop extra refcnt by try_charge() */
+               css_put(&parent->css);
                return 0;
        }
-       /* uncharge if move fails */
+
 cancel:
+       put_page(page);
+uncharge:
+       /* drop extra refcnt by try_charge() */
+       css_put(&parent->css);
+       /* uncharge if move fails */
        res_counter_uncharge(&parent->res, PAGE_SIZE);
        if (do_swap_account)
                res_counter_uncharge(&parent->memsw, PAGE_SIZE);
-       put_page(page);
        return ret;
 }