cgroup: make hierarchy iterators deal with cgroup_subsys_state instead of cgroup
[deliverable/linux.git] / mm / memcontrol.c
index 2e851f453814529d0a3e032e9e5e1dd009a4b34a..2285319e23a997d0831e8795430fa3b70bff5b40 100644 (file)
@@ -187,10 +187,6 @@ struct mem_cgroup_per_node {
        struct mem_cgroup_per_zone zoneinfo[MAX_NR_ZONES];
 };
 
-struct mem_cgroup_lru_info {
-       struct mem_cgroup_per_node *nodeinfo[0];
-};
-
 /*
  * Cgroups above their limits are maintained in a RB-Tree, independent of
  * their hierarchy representation
@@ -267,28 +263,10 @@ struct mem_cgroup {
        /* vmpressure notifications */
        struct vmpressure vmpressure;
 
-       union {
-               /*
-                * the counter to account for mem+swap usage.
-                */
-               struct res_counter memsw;
-
-               /*
-                * rcu_freeing is used only when freeing struct mem_cgroup,
-                * so put it into a union to avoid wasting more memory.
-                * It must be disjoint from the css field.  It could be
-                * in a union with the res field, but res plays a much
-                * larger part in mem_cgroup life than memsw, and might
-                * be of interest, even at time of free, when debugging.
-                * So share rcu_head with the less interesting memsw.
-                */
-               struct rcu_head rcu_freeing;
-               /*
-                * We also need some space for a worker in deferred freeing.
-                * By the time we call it, rcu_freeing is no longer in use.
-                */
-               struct work_struct work_freeing;
-       };
+       /*
+        * the counter to account for mem+swap usage.
+        */
+       struct res_counter memsw;
 
        /*
         * the counter to account for kernel memory usage.
@@ -303,8 +281,6 @@ struct mem_cgroup {
        bool            oom_lock;
        atomic_t        under_oom;
 
-       atomic_t        refcnt;
-
        int     swappiness;
        /* OOM-Killer disable */
        int             oom_kill_disable;
@@ -366,14 +342,8 @@ struct mem_cgroup {
        atomic_t        numainfo_updating;
 #endif
 
-       /*
-        * Per cgroup active and inactive list, similar to the
-        * per zone LRU lists.
-        *
-        * WARNING: This has to be the last element of the struct. Don't
-        * add new fields after this point.
-        */
-       struct mem_cgroup_lru_info info;
+       struct mem_cgroup_per_node *nodeinfo[0];
+       /* WARNING: nodeinfo must be the last member here */
 };
 
 static size_t memcg_size(void)
@@ -416,6 +386,11 @@ static void memcg_kmem_clear_activated(struct mem_cgroup *memcg)
 
 static void memcg_kmem_mark_dead(struct mem_cgroup *memcg)
 {
+       /*
+        * Our caller must use css_get() first, because memcg_uncharge_kmem()
+        * will call css_put() if it sees the memcg is dead.
+        */
+       smp_wmb();
        if (test_bit(KMEM_ACCOUNTED_ACTIVE, &memcg->kmem_account_flags))
                set_bit(KMEM_ACCOUNTED_DEAD, &memcg->kmem_account_flags);
 }
@@ -508,13 +483,9 @@ enum res_type {
  */
 static DEFINE_MUTEX(memcg_create_mutex);
 
-static void mem_cgroup_get(struct mem_cgroup *memcg);
-static void mem_cgroup_put(struct mem_cgroup *memcg);
-
-static inline
 struct mem_cgroup *mem_cgroup_from_css(struct cgroup_subsys_state *s)
 {
-       return container_of(s, struct mem_cgroup, css);
+       return s ? container_of(s, struct mem_cgroup, css) : NULL;
 }
 
 /* Some nice accessors for the vmpressure. */
@@ -561,15 +532,15 @@ void sock_update_memcg(struct sock *sk)
                 */
                if (sk->sk_cgrp) {
                        BUG_ON(mem_cgroup_is_root(sk->sk_cgrp->memcg));
-                       mem_cgroup_get(sk->sk_cgrp->memcg);
+                       css_get(&sk->sk_cgrp->memcg->css);
                        return;
                }
 
                rcu_read_lock();
                memcg = mem_cgroup_from_task(current);
                cg_proto = sk->sk_prot->proto_cgroup(memcg);
-               if (!mem_cgroup_is_root(memcg) && memcg_proto_active(cg_proto)) {
-                       mem_cgroup_get(memcg);
+               if (!mem_cgroup_is_root(memcg) &&
+                   memcg_proto_active(cg_proto) && css_tryget(&memcg->css)) {
                        sk->sk_cgrp = cg_proto;
                }
                rcu_read_unlock();
@@ -583,7 +554,7 @@ void sock_release_memcg(struct sock *sk)
                struct mem_cgroup *memcg;
                WARN_ON(!sk->sk_cgrp->memcg);
                memcg = sk->sk_cgrp->memcg;
-               mem_cgroup_put(memcg);
+               css_put(&sk->sk_cgrp->memcg->css);
        }
 }
 
@@ -683,7 +654,7 @@ static struct mem_cgroup_per_zone *
 mem_cgroup_zoneinfo(struct mem_cgroup *memcg, int nid, int zid)
 {
        VM_BUG_ON((unsigned)nid >= nr_node_ids);
-       return &memcg->info.nodeinfo[nid]->zoneinfo[zid];
+       return &memcg->nodeinfo[nid]->zoneinfo[zid];
 }
 
 struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *memcg)
@@ -1063,10 +1034,9 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
                preempt_enable();
 }
 
-struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
+static inline struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
 {
-       return mem_cgroup_from_css(
-               cgroup_subsys_state(cont, mem_cgroup_subsys_id));
+       return mem_cgroup_from_css(cgroup_css(cont, mem_cgroup_subsys_id));
 }
 
 struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
@@ -1079,7 +1049,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
        if (unlikely(!p))
                return NULL;
 
-       return mem_cgroup_from_css(task_subsys_state(p, mem_cgroup_subsys_id));
+       return mem_cgroup_from_css(task_css(p, mem_cgroup_subsys_id));
 }
 
 struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
@@ -1112,7 +1082,7 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
                struct mem_cgroup *last_visited)
 {
-       struct cgroup *prev_cgroup, *next_cgroup;
+       struct cgroup_subsys_state *prev_css, *next_css;
 
        /*
         * Root is not visited by cgroup iterators so it needs an
@@ -1121,11 +1091,9 @@ static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
        if (!last_visited)
                return root;
 
-       prev_cgroup = (last_visited == root) ? NULL
-               : last_visited->css.cgroup;
+       prev_css = (last_visited == root) ? NULL : &last_visited->css;
 skip_node:
-       next_cgroup = cgroup_next_descendant_pre(
-                       prev_cgroup, root->css.cgroup);
+       next_css = css_next_descendant_pre(prev_css, &root->css);
 
        /*
         * Even if we found a group we have to make sure it is
@@ -1134,13 +1102,13 @@ skip_node:
         * last_visited css is safe to use because it is
         * protected by css_get and the tree walk is rcu safe.
         */
-       if (next_cgroup) {
-               struct mem_cgroup *mem = mem_cgroup_from_cont(
-                               next_cgroup);
+       if (next_css) {
+               struct mem_cgroup *mem = mem_cgroup_from_css(next_css);
+
                if (css_tryget(&mem->css))
                        return mem;
                else {
-                       prev_cgroup = next_cgroup;
+                       prev_css = next_css;
                        goto skip_node;
                }
        }
@@ -1553,10 +1521,8 @@ static unsigned long mem_cgroup_margin(struct mem_cgroup *memcg)
 
 int mem_cgroup_swappiness(struct mem_cgroup *memcg)
 {
-       struct cgroup *cgrp = memcg->css.cgroup;
-
        /* root ? */
-       if (cgrp->parent == NULL)
+       if (!css_parent(&memcg->css))
                return vm_swappiness;
 
        return memcg->swappiness;
@@ -2982,10 +2948,10 @@ static struct kmem_cache *memcg_params_to_cache(struct memcg_cache_params *p)
 }
 
 #ifdef CONFIG_SLABINFO
-static int mem_cgroup_slabinfo_read(struct cgroup *cont, struct cftype *cft,
-                                       struct seq_file *m)
+static int mem_cgroup_slabinfo_read(struct cgroup_subsys_state *css,
+                                   struct cftype *cft, struct seq_file *m)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct memcg_cache_params *params;
 
        if (!memcg_can_account_kmem(memcg))
@@ -3060,8 +3026,16 @@ static void memcg_uncharge_kmem(struct mem_cgroup *memcg, u64 size)
        if (res_counter_uncharge(&memcg->kmem, size))
                return;
 
+       /*
+        * Releases a reference taken in kmem_cgroup_css_offline in case
+        * this last uncharge is racing with the offlining code or it is
+        * outliving the memcg existence.
+        *
+        * The memory barrier imposed by test&clear is paired with the
+        * explicit one in memcg_kmem_mark_dead().
+        */
        if (memcg_kmem_test_and_clear_dead(memcg))
-               mem_cgroup_put(memcg);
+               css_put(&memcg->css);
 }
 
 void memcg_cache_list_add(struct mem_cgroup *memcg, struct kmem_cache *cachep)
@@ -3252,7 +3226,7 @@ void memcg_release_cache(struct kmem_cache *s)
        list_del(&s->memcg_params->list);
        mutex_unlock(&memcg->slab_caches_mutex);
 
-       mem_cgroup_put(memcg);
+       css_put(&memcg->css);
 out:
        kfree(s->memcg_params);
 }
@@ -3412,16 +3386,18 @@ static struct kmem_cache *memcg_create_kmem_cache(struct mem_cgroup *memcg,
 
        mutex_lock(&memcg_cache_mutex);
        new_cachep = cachep->memcg_params->memcg_caches[idx];
-       if (new_cachep)
+       if (new_cachep) {
+               css_put(&memcg->css);
                goto out;
+       }
 
        new_cachep = kmem_cache_dup(memcg, cachep);
        if (new_cachep == NULL) {
                new_cachep = cachep;
+               css_put(&memcg->css);
                goto out;
        }
 
-       mem_cgroup_get(memcg);
        atomic_set(&new_cachep->memcg_params->nr_pages , 0);
 
        cachep->memcg_params->memcg_caches[idx] = new_cachep;
@@ -3509,8 +3485,6 @@ static void memcg_create_cache_work_func(struct work_struct *w)
 
        cw = container_of(w, struct create_work, work);
        memcg_create_kmem_cache(cw->memcg, cw->cachep);
-       /* Drop the reference gotten when we enqueued. */
-       css_put(&cw->memcg->css);
        kfree(cw);
 }
 
@@ -3647,6 +3621,34 @@ __memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **_memcg, int order)
        int ret;
 
        *_memcg = NULL;
+
+       /*
+        * Disabling accounting is only relevant for some specific memcg
+        * internal allocations. Therefore we would initially not have such
+        * check here, since direct calls to the page allocator that are marked
+        * with GFP_KMEMCG only happen outside memcg core. We are mostly
+        * concerned with cache allocations, and by having this test at
+        * memcg_kmem_get_cache, we are already able to relay the allocation to
+        * the root cache and bypass the memcg cache altogether.
+        *
+        * There is one exception, though: the SLUB allocator does not create
+        * large order caches, but rather service large kmallocs directly from
+        * the page allocator. Therefore, the following sequence when backed by
+        * the SLUB allocator:
+        *
+        *      memcg_stop_kmem_account();
+        *      kmalloc(<large_number>)
+        *      memcg_resume_kmem_account();
+        *
+        * would effectively ignore the fact that we should skip accounting,
+        * since it will drive us directly to this function without passing
+        * through the cache selector memcg_kmem_get_cache. Such large
+        * allocations are extremely rare but can happen, for instance, for the
+        * cache arrays. We bring this test here.
+        */
+       if (!current->mm || current->memcg_kmem_skip_account)
+               return true;
+
        memcg = try_get_mem_cgroup_from_mm(current->mm);
 
        /*
@@ -4200,12 +4202,12 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
        unlock_page_cgroup(pc);
        /*
         * even after unlock, we have memcg->res.usage here and this memcg
-        * will never be freed.
+        * will never be freed, so it's safe to call css_get().
         */
        memcg_check_events(memcg, page);
        if (do_swap_account && ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT) {
                mem_cgroup_swap_statistics(memcg, true);
-               mem_cgroup_get(memcg);
+               css_get(&memcg->css);
        }
        /*
         * Migration does not charge the res_counter for the
@@ -4317,7 +4319,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
 
        /*
         * record memcg information,  if swapout && memcg != NULL,
-        * mem_cgroup_get() was called in uncharge().
+        * css_get() was called in uncharge().
         */
        if (do_swap_account && swapout && memcg)
                swap_cgroup_record(ent, css_id(&memcg->css));
@@ -4348,7 +4350,7 @@ void mem_cgroup_uncharge_swap(swp_entry_t ent)
                if (!mem_cgroup_is_root(memcg))
                        res_counter_uncharge(&memcg->memsw, PAGE_SIZE);
                mem_cgroup_swap_statistics(memcg, false);
-               mem_cgroup_put(memcg);
+               css_put(&memcg->css);
        }
        rcu_read_unlock();
 }
@@ -4382,11 +4384,14 @@ static int mem_cgroup_move_swap_account(swp_entry_t entry,
                 * This function is only called from task migration context now.
                 * It postpones res_counter and refcount handling till the end
                 * of task migration(mem_cgroup_clear_mc()) for performance
-                * improvement. But we cannot postpone mem_cgroup_get(to)
-                * because if the process that has been moved to @to does
-                * swap-in, the refcount of @to might be decreased to 0.
+                * improvement. But we cannot postpone css_get(to)  because if
+                * the process that has been moved to @to does swap-in, the
+                * refcount of @to might be decreased to 0.
+                *
+                * We are in attach() phase, so the cgroup is guaranteed to be
+                * alive, so we can just call css_get().
                 */
-               mem_cgroup_get(to);
+               css_get(&to->css);
                return 0;
        }
        return -EINVAL;
@@ -4932,10 +4937,10 @@ static void mem_cgroup_reparent_charges(struct mem_cgroup *memcg)
  */
 static inline bool __memcg_has_children(struct mem_cgroup *memcg)
 {
-       struct cgroup *pos;
+       struct cgroup_subsys_state *pos;
 
        /* bounce at first found */
-       cgroup_for_each_child(pos, memcg->css.cgroup)
+       css_for_each_child(pos, &memcg->css)
                return true;
        return false;
 }
@@ -4991,9 +4996,10 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
        return 0;
 }
 
-static int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
+static int mem_cgroup_force_empty_write(struct cgroup_subsys_state *css,
+                                       unsigned int event)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        int ret;
 
        if (mem_cgroup_is_root(memcg))
@@ -5006,21 +5012,18 @@ static int mem_cgroup_force_empty_write(struct cgroup *cont, unsigned int event)
 }
 
 
-static u64 mem_cgroup_hierarchy_read(struct cgroup *cont, struct cftype *cft)
+static u64 mem_cgroup_hierarchy_read(struct cgroup_subsys_state *css,
+                                    struct cftype *cft)
 {
-       return mem_cgroup_from_cont(cont)->use_hierarchy;
+       return mem_cgroup_from_css(css)->use_hierarchy;
 }
 
-static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft,
-                                       u64 val)
+static int mem_cgroup_hierarchy_write(struct cgroup_subsys_state *css,
+                                     struct cftype *cft, u64 val)
 {
        int retval = 0;
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-       struct cgroup *parent = cont->parent;
-       struct mem_cgroup *parent_memcg = NULL;
-
-       if (parent)
-               parent_memcg = mem_cgroup_from_cont(parent);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *parent_memcg = mem_cgroup_from_css(css_parent(&memcg->css));
 
        mutex_lock(&memcg_create_mutex);
 
@@ -5090,11 +5093,11 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
        return val << PAGE_SHIFT;
 }
 
-static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
-                              struct file *file, char __user *buf,
-                              size_t nbytes, loff_t *ppos)
+static ssize_t mem_cgroup_read(struct cgroup_subsys_state *css,
+                              struct cftype *cft, struct file *file,
+                              char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        char str[64];
        u64 val;
        int name, len;
@@ -5127,11 +5130,11 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
        return simple_read_from_buffer(buf, nbytes, ppos, str, len);
 }
 
-static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
+static int memcg_update_kmem_limit(struct cgroup_subsys_state *css, u64 val)
 {
        int ret = -EINVAL;
 #ifdef CONFIG_MEMCG_KMEM
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        /*
         * For simplicity, we won't allow this to be disabled.  It also can't
         * be changed if the cgroup has children already, or if tasks had
@@ -5147,7 +5150,7 @@ static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
        mutex_lock(&memcg_create_mutex);
        mutex_lock(&set_limit_mutex);
        if (!memcg->kmem_account_flags && val != RESOURCE_MAX) {
-               if (cgroup_task_count(cont) || memcg_has_children(memcg)) {
+               if (cgroup_task_count(css->cgroup) || memcg_has_children(memcg)) {
                        ret = -EBUSY;
                        goto out;
                }
@@ -5165,14 +5168,6 @@ static int memcg_update_kmem_limit(struct cgroup *cont, u64 val)
                 * starts accounting before all call sites are patched
                 */
                memcg_kmem_set_active(memcg);
-
-               /*
-                * kmem charges can outlive the cgroup. In the case of slab
-                * pages, for instance, a page contain objects from various
-                * processes, so it is unfeasible to migrate them away. We
-                * need to reference count the memcg because of that.
-                */
-               mem_cgroup_get(memcg);
        } else
                ret = res_counter_set_limit(&memcg->kmem, val);
 out:
@@ -5205,16 +5200,16 @@ static int memcg_propagate_kmem(struct mem_cgroup *memcg)
                goto out;
 
        /*
-        * destroy(), called if we fail, will issue static_key_slow_inc() and
-        * mem_cgroup_put() if kmem is enabled. We have to either call them
-        * unconditionally, or clear the KMEM_ACTIVE flag. I personally find
-        * this more consistent, since it always leads to the same destroy path
+        * __mem_cgroup_free() will issue static_key_slow_dec() because this
+        * memcg is active already. If the later initialization fails then the
+        * cgroup core triggers the cleanup so we do not have to do it here.
         */
-       mem_cgroup_get(memcg);
        static_key_slow_inc(&memcg_kmem_enabled_key);
 
        mutex_lock(&set_limit_mutex);
+       memcg_stop_kmem_account();
        ret = memcg_update_cache_sizes(memcg);
+       memcg_resume_kmem_account();
        mutex_unlock(&set_limit_mutex);
 out:
        return ret;
@@ -5225,10 +5220,10 @@ out:
  * The user of this function is...
  * RES_LIMIT.
  */
-static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
+static int mem_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft,
                            const char *buffer)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        enum res_type type;
        int name;
        unsigned long long val;
@@ -5252,7 +5247,7 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
                else if (type == _MEMSWAP)
                        ret = mem_cgroup_resize_memsw_limit(memcg, val);
                else if (type == _KMEM)
-                       ret = memcg_update_kmem_limit(cont, val);
+                       ret = memcg_update_kmem_limit(css, val);
                else
                        return -EINVAL;
                break;
@@ -5280,18 +5275,15 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
 static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg,
                unsigned long long *mem_limit, unsigned long long *memsw_limit)
 {
-       struct cgroup *cgroup;
        unsigned long long min_limit, min_memsw_limit, tmp;
 
        min_limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
        min_memsw_limit = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
-       cgroup = memcg->css.cgroup;
        if (!memcg->use_hierarchy)
                goto out;
 
-       while (cgroup->parent) {
-               cgroup = cgroup->parent;
-               memcg = mem_cgroup_from_cont(cgroup);
+       while (css_parent(&memcg->css)) {
+               memcg = mem_cgroup_from_css(css_parent(&memcg->css));
                if (!memcg->use_hierarchy)
                        break;
                tmp = res_counter_read_u64(&memcg->res, RES_LIMIT);
@@ -5304,9 +5296,9 @@ out:
        *memsw_limit = min_memsw_limit;
 }
 
-static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
+static int mem_cgroup_reset(struct cgroup_subsys_state *css, unsigned int event)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        int name;
        enum res_type type;
 
@@ -5339,17 +5331,17 @@ static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
        return 0;
 }
 
-static u64 mem_cgroup_move_charge_read(struct cgroup *cgrp,
+static u64 mem_cgroup_move_charge_read(struct cgroup_subsys_state *css,
                                        struct cftype *cft)
 {
-       return mem_cgroup_from_cont(cgrp)->move_charge_at_immigrate;
+       return mem_cgroup_from_css(css)->move_charge_at_immigrate;
 }
 
 #ifdef CONFIG_MMU
-static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
+static int mem_cgroup_move_charge_write(struct cgroup_subsys_state *css,
                                        struct cftype *cft, u64 val)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
        if (val >= (1 << NR_MOVE_TYPE))
                return -EINVAL;
@@ -5364,7 +5356,7 @@ static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
        return 0;
 }
 #else
-static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
+static int mem_cgroup_move_charge_write(struct cgroup_subsys_state *css,
                                        struct cftype *cft, u64 val)
 {
        return -ENOSYS;
@@ -5372,13 +5364,13 @@ static int mem_cgroup_move_charge_write(struct cgroup *cgrp,
 #endif
 
 #ifdef CONFIG_NUMA
-static int memcg_numa_stat_show(struct cgroup *cont, struct cftype *cft,
-                                     struct seq_file *m)
+static int memcg_numa_stat_show(struct cgroup_subsys_state *css,
+                               struct cftype *cft, struct seq_file *m)
 {
        int nid;
        unsigned long total_nr, file_nr, anon_nr, unevictable_nr;
        unsigned long node_nr;
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
        total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
        seq_printf(m, "total=%lu", total_nr);
@@ -5423,10 +5415,10 @@ static inline void mem_cgroup_lru_names_not_uptodate(void)
        BUILD_BUG_ON(ARRAY_SIZE(mem_cgroup_lru_names) != NR_LRU_LISTS);
 }
 
-static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,
+static int memcg_stat_show(struct cgroup_subsys_state *css, struct cftype *cft,
                                 struct seq_file *m)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        struct mem_cgroup *mi;
        unsigned int i;
 
@@ -5510,27 +5502,23 @@ static int memcg_stat_show(struct cgroup *cont, struct cftype *cft,
        return 0;
 }
 
-static u64 mem_cgroup_swappiness_read(struct cgroup *cgrp, struct cftype *cft)
+static u64 mem_cgroup_swappiness_read(struct cgroup_subsys_state *css,
+                                     struct cftype *cft)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
        return mem_cgroup_swappiness(memcg);
 }
 
-static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft,
-                                      u64 val)
+static int mem_cgroup_swappiness_write(struct cgroup_subsys_state *css,
+                                      struct cftype *cft, u64 val)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
-       struct mem_cgroup *parent;
-
-       if (val > 100)
-               return -EINVAL;
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(&memcg->css));
 
-       if (cgrp->parent == NULL)
+       if (val > 100 || !parent)
                return -EINVAL;
 
-       parent = mem_cgroup_from_cont(cgrp->parent);
-
        mutex_lock(&memcg_create_mutex);
 
        /* If under hierarchy, only empty-root can set this value */
@@ -5841,10 +5829,10 @@ static void mem_cgroup_oom_unregister_event(struct cgroup *cgrp,
        spin_unlock(&memcg_oom_lock);
 }
 
-static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
+static int mem_cgroup_oom_control_read(struct cgroup_subsys_state *css,
        struct cftype *cft,  struct cgroup_map_cb *cb)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
        cb->fill(cb, "oom_kill_disable", memcg->oom_kill_disable);
 
@@ -5855,18 +5843,16 @@ static int mem_cgroup_oom_control_read(struct cgroup *cgrp,
        return 0;
 }
 
-static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
+static int mem_cgroup_oom_control_write(struct cgroup_subsys_state *css,
        struct cftype *cft, u64 val)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
-       struct mem_cgroup *parent;
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(&memcg->css));
 
        /* cannot set to root cgroup and only 0 and 1 are allowed */
-       if (!cgrp->parent || !((val == 0) || (val == 1)))
+       if (!parent || !((val == 0) || (val == 1)))
                return -EINVAL;
 
-       parent = mem_cgroup_from_cont(cgrp->parent);
-
        mutex_lock(&memcg_create_mutex);
        /* oom-kill-disable is a flag for subhierarchy. */
        if ((parent->use_hierarchy) || memcg_has_children(memcg)) {
@@ -5893,23 +5879,43 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
        return mem_cgroup_sockets_init(memcg, ss);
 }
 
-static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
+static void memcg_destroy_kmem(struct mem_cgroup *memcg)
 {
        mem_cgroup_sockets_destroy(memcg);
+}
+
+static void kmem_cgroup_css_offline(struct mem_cgroup *memcg)
+{
+       if (!memcg_kmem_is_active(memcg))
+               return;
+
+       /*
+        * kmem charges can outlive the cgroup. In the case of slab
+        * pages, for instance, a page contain objects from various
+        * processes. As we prevent from taking a reference for every
+        * such allocation we have to be careful when doing uncharge
+        * (see memcg_uncharge_kmem) and here during offlining.
+        *
+        * The idea is that that only the _last_ uncharge which sees
+        * the dead memcg will drop the last reference. An additional
+        * reference is taken here before the group is marked dead
+        * which is then paired with css_put during uncharge resp. here.
+        *
+        * Although this might sound strange as this path is called from
+        * css_offline() when the referencemight have dropped down to 0
+        * and shouldn't be incremented anymore (css_tryget would fail)
+        * we do not have other options because of the kmem allocations
+        * lifetime.
+        */
+       css_get(&memcg->css);
 
        memcg_kmem_mark_dead(memcg);
 
        if (res_counter_read_u64(&memcg->kmem, RES_USAGE) != 0)
                return;
 
-       /*
-        * Charges already down to 0, undo mem_cgroup_get() done in the charge
-        * path here, being careful not to race with memcg_uncharge_kmem: it is
-        * possible that the charges went down to 0 between mark_dead and the
-        * res_counter read, so in that case, we don't need the put
-        */
        if (memcg_kmem_test_and_clear_dead(memcg))
-               mem_cgroup_put(memcg);
+               css_put(&memcg->css);
 }
 #else
 static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
@@ -5917,7 +5923,11 @@ static int memcg_init_kmem(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
        return 0;
 }
 
-static void kmem_cgroup_destroy(struct mem_cgroup *memcg)
+static void memcg_destroy_kmem(struct mem_cgroup *memcg)
+{
+}
+
+static void kmem_cgroup_css_offline(struct mem_cgroup *memcg)
 {
 }
 #endif
@@ -6087,13 +6097,13 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
                mz->on_tree = false;
                mz->memcg = memcg;
        }
-       memcg->info.nodeinfo[node] = pn;
+       memcg->nodeinfo[node] = pn;
        return 0;
 }
 
 static void free_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 {
-       kfree(memcg->info.nodeinfo[node]);
+       kfree(memcg->nodeinfo[node]);
 }
 
 static struct mem_cgroup *mem_cgroup_alloc(void)
@@ -6166,49 +6176,6 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
                vfree(memcg);
 }
 
-
-/*
- * Helpers for freeing a kmalloc()ed/vzalloc()ed mem_cgroup by RCU,
- * but in process context.  The work_freeing structure is overlaid
- * on the rcu_freeing structure, which itself is overlaid on memsw.
- */
-static void free_work(struct work_struct *work)
-{
-       struct mem_cgroup *memcg;
-
-       memcg = container_of(work, struct mem_cgroup, work_freeing);
-       __mem_cgroup_free(memcg);
-}
-
-static void free_rcu(struct rcu_head *rcu_head)
-{
-       struct mem_cgroup *memcg;
-
-       memcg = container_of(rcu_head, struct mem_cgroup, rcu_freeing);
-       INIT_WORK(&memcg->work_freeing, free_work);
-       schedule_work(&memcg->work_freeing);
-}
-
-static void mem_cgroup_get(struct mem_cgroup *memcg)
-{
-       atomic_inc(&memcg->refcnt);
-}
-
-static void __mem_cgroup_put(struct mem_cgroup *memcg, int count)
-{
-       if (atomic_sub_and_test(count, &memcg->refcnt)) {
-               struct mem_cgroup *parent = parent_mem_cgroup(memcg);
-               call_rcu(&memcg->rcu_freeing, free_rcu);
-               if (parent)
-                       mem_cgroup_put(parent);
-       }
-}
-
-static void mem_cgroup_put(struct mem_cgroup *memcg)
-{
-       __mem_cgroup_put(memcg, 1);
-}
-
 /*
  * Returns the parent mem_cgroup in memcgroup hierarchy with hierarchy enabled.
  */
@@ -6244,7 +6211,7 @@ static void __init mem_cgroup_soft_limit_tree_init(void)
 }
 
 static struct cgroup_subsys_state * __ref
-mem_cgroup_css_alloc(struct cgroup *cont)
+mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
 {
        struct mem_cgroup *memcg;
        long error = -ENOMEM;
@@ -6259,7 +6226,7 @@ mem_cgroup_css_alloc(struct cgroup *cont)
                        goto free_out;
 
        /* root ? */
-       if (cont->parent == NULL) {
+       if (parent_css == NULL) {
                root_mem_cgroup = memcg;
                res_counter_init(&memcg->res, NULL);
                res_counter_init(&memcg->memsw, NULL);
@@ -6268,7 +6235,6 @@ mem_cgroup_css_alloc(struct cgroup *cont)
 
        memcg->last_scanned_node = MAX_NUMNODES;
        INIT_LIST_HEAD(&memcg->oom_notify);
-       atomic_set(&memcg->refcnt, 1);
        memcg->move_charge_at_immigrate = 0;
        mutex_init(&memcg->thresholds_lock);
        spin_lock_init(&memcg->move_lock);
@@ -6282,17 +6248,16 @@ free_out:
 }
 
 static int
-mem_cgroup_css_online(struct cgroup *cont)
+mem_cgroup_css_online(struct cgroup_subsys_state *css)
 {
-       struct mem_cgroup *memcg, *parent;
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css));
        int error = 0;
 
-       if (!cont->parent)
+       if (!parent)
                return 0;
 
        mutex_lock(&memcg_create_mutex);
-       memcg = mem_cgroup_from_cont(cont);
-       parent = mem_cgroup_from_cont(cont->parent);
 
        memcg->use_hierarchy = parent->use_hierarchy;
        memcg->oom_kill_disable = parent->oom_kill_disable;
@@ -6304,12 +6269,9 @@ mem_cgroup_css_online(struct cgroup *cont)
                res_counter_init(&memcg->kmem, &parent->kmem);
 
                /*
-                * We increment refcnt of the parent to ensure that we can
-                * safely access it on res_counter_charge/uncharge.
-                * This refcnt will be decremented when freeing this
-                * mem_cgroup(see mem_cgroup_put).
+                * No need to take a reference to the parent because cgroup
+                * core guarantees its existence.
                 */
-               mem_cgroup_get(parent);
        } else {
                res_counter_init(&memcg->res, NULL);
                res_counter_init(&memcg->memsw, NULL);
@@ -6325,16 +6287,6 @@ mem_cgroup_css_online(struct cgroup *cont)
 
        error = memcg_init_kmem(memcg, &mem_cgroup_subsys);
        mutex_unlock(&memcg_create_mutex);
-       if (error) {
-               /*
-                * We call put now because our (and parent's) refcnts
-                * are already in place. mem_cgroup_put() will internally
-                * call __mem_cgroup_free, so return directly
-                */
-               mem_cgroup_put(memcg);
-               if (parent->use_hierarchy)
-                       mem_cgroup_put(parent);
-       }
        return error;
 }
 
@@ -6356,22 +6308,23 @@ static void mem_cgroup_invalidate_reclaim_iterators(struct mem_cgroup *memcg)
                mem_cgroup_iter_invalidate(root_mem_cgroup);
 }
 
-static void mem_cgroup_css_offline(struct cgroup *cont)
+static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+
+       kmem_cgroup_css_offline(memcg);
 
        mem_cgroup_invalidate_reclaim_iterators(memcg);
        mem_cgroup_reparent_charges(memcg);
        mem_cgroup_destroy_all_caches(memcg);
 }
 
-static void mem_cgroup_css_free(struct cgroup *cont)
+static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
-
-       kmem_cgroup_destroy(memcg);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
 
-       mem_cgroup_put(memcg);
+       memcg_destroy_kmem(memcg);
+       __mem_cgroup_free(memcg);
 }
 
 #ifdef CONFIG_MMU
@@ -6680,6 +6633,7 @@ static void __mem_cgroup_clear_mc(void)
 {
        struct mem_cgroup *from = mc.from;
        struct mem_cgroup *to = mc.to;
+       int i;
 
        /* we must uncharge all the leftover precharges from mc.to */
        if (mc.precharge) {
@@ -6700,7 +6654,9 @@ static void __mem_cgroup_clear_mc(void)
                if (!mem_cgroup_is_root(mc.from))
                        res_counter_uncharge(&mc.from->memsw,
                                                PAGE_SIZE * mc.moved_swap);
-               __mem_cgroup_put(mc.from, mc.moved_swap);
+
+               for (i = 0; i < mc.moved_swap; i++)
+                       css_put(&mc.from->css);
 
                if (!mem_cgroup_is_root(mc.to)) {
                        /*
@@ -6710,7 +6666,7 @@ static void __mem_cgroup_clear_mc(void)
                        res_counter_uncharge(&mc.to->res,
                                                PAGE_SIZE * mc.moved_swap);
                }
-               /* we've already done mem_cgroup_get(mc.to) */
+               /* we've already done css_get(mc.to) */
                mc.moved_swap = 0;
        }
        memcg_oom_recover(from);
@@ -6735,12 +6691,12 @@ static void mem_cgroup_clear_mc(void)
        mem_cgroup_end_move(from);
 }
 
-static int mem_cgroup_can_attach(struct cgroup *cgroup,
+static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
                                 struct cgroup_taskset *tset)
 {
        struct task_struct *p = cgroup_taskset_first(tset);
        int ret = 0;
-       struct mem_cgroup *memcg = mem_cgroup_from_cont(cgroup);
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
        unsigned long move_charge_at_immigrate;
 
        /*
@@ -6782,7 +6738,7 @@ static int mem_cgroup_can_attach(struct cgroup *cgroup,
        return ret;
 }
 
-static void mem_cgroup_cancel_attach(struct cgroup *cgroup,
+static void mem_cgroup_cancel_attach(struct cgroup_subsys_state *css,
                                     struct cgroup_taskset *tset)
 {
        mem_cgroup_clear_mc();
@@ -6930,7 +6886,7 @@ retry:
        up_read(&mm->mmap_sem);
 }
 
-static void mem_cgroup_move_task(struct cgroup *cont,
+static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
                                 struct cgroup_taskset *tset)
 {
        struct task_struct *p = cgroup_taskset_first(tset);
@@ -6945,16 +6901,16 @@ static void mem_cgroup_move_task(struct cgroup *cont,
                mem_cgroup_clear_mc();
 }
 #else  /* !CONFIG_MMU */
-static int mem_cgroup_can_attach(struct cgroup *cgroup,
+static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
                                 struct cgroup_taskset *tset)
 {
        return 0;
 }
-static void mem_cgroup_cancel_attach(struct cgroup *cgroup,
+static void mem_cgroup_cancel_attach(struct cgroup_subsys_state *css,
                                     struct cgroup_taskset *tset)
 {
 }
-static void mem_cgroup_move_task(struct cgroup *cont,
+static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
                                 struct cgroup_taskset *tset)
 {
 }
@@ -6964,15 +6920,15 @@ static void mem_cgroup_move_task(struct cgroup *cont,
  * Cgroup retains root cgroups across [un]mount cycles making it necessary
  * to verify sane_behavior flag on each mount attempt.
  */
-static void mem_cgroup_bind(struct cgroup *root)
+static void mem_cgroup_bind(struct cgroup_subsys_state *root_css)
 {
        /*
         * use_hierarchy is forced with sane_behavior.  cgroup core
         * guarantees that @root doesn't have any children, so turning it
         * on for the root memcg is enough.
         */
-       if (cgroup_sane_behavior(root))
-               mem_cgroup_from_cont(root)->use_hierarchy = true;
+       if (cgroup_sane_behavior(root_css->cgroup))
+               mem_cgroup_from_css(root_css)->use_hierarchy = true;
 }
 
 struct cgroup_subsys mem_cgroup_subsys = {
This page took 0.040837 seconds and 5 git commands to generate.