ath10k: rename board_data in struct ath10k
[cascardo/linux.git] / mm / memcontrol.c
index 6b73d86..d12ca6f 100644 (file)
@@ -263,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.
@@ -299,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;
@@ -406,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);
 }
@@ -498,9 +483,6 @@ 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)
 {
@@ -551,15 +533,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();
@@ -573,7 +555,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);
        }
 }
 
@@ -3050,8 +3032,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)
@@ -3242,7 +3232,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);
 }
@@ -3402,16 +3392,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;
@@ -3499,8 +3491,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);
 }
 
@@ -4218,12 +4208,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
@@ -4335,7 +4325,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));
@@ -4366,7 +4356,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();
 }
@@ -4400,11 +4390,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;
@@ -5183,14 +5176,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:
@@ -5223,12 +5208,10 @@ 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);
@@ -5913,23 +5896,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)
@@ -5937,7 +5940,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
@@ -6186,49 +6193,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.
  */
@@ -6288,7 +6252,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);
@@ -6324,12 +6287,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);
@@ -6345,14 +6305,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);
-       }
        return error;
 }
 
@@ -6378,6 +6330,8 @@ static void mem_cgroup_css_offline(struct cgroup *cont)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
+       kmem_cgroup_css_offline(memcg);
+
        mem_cgroup_invalidate_reclaim_iterators(memcg);
        mem_cgroup_reparent_charges(memcg);
        mem_cgroup_destroy_all_caches(memcg);
@@ -6387,9 +6341,8 @@ static void mem_cgroup_css_free(struct cgroup *cont)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
-       kmem_cgroup_destroy(memcg);
-
-       mem_cgroup_put(memcg);
+       memcg_destroy_kmem(memcg);
+       __mem_cgroup_free(memcg);
 }
 
 #ifdef CONFIG_MMU
@@ -6698,6 +6651,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) {
@@ -6718,7 +6672,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)) {
                        /*
@@ -6728,7 +6684,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);