Merge branch 'akpm' (patches from Andrew Morton)
[cascardo/linux.git] / mm / memcontrol.c
index 3d4bb07..f20a57b 100644 (file)
@@ -500,6 +500,29 @@ static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
        return (memcg == root_mem_cgroup);
 }
 
+/*
+ * We restrict the id in the range of [1, 65535], so it can fit into
+ * an unsigned short.
+ */
+#define MEM_CGROUP_ID_MAX      USHRT_MAX
+
+static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
+{
+       /*
+        * The ID of the root cgroup is 0, but memcg treat 0 as an
+        * invalid ID, so we return (cgroup_id + 1).
+        */
+       return memcg->css.cgroup->id + 1;
+}
+
+static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
+{
+       struct cgroup_subsys_state *css;
+
+       css = css_from_id(id - 1, &mem_cgroup_subsys);
+       return mem_cgroup_from_css(css);
+}
+
 /* Writing them here to avoid exposing memcg's inner layout */
 #if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
 
@@ -571,16 +594,11 @@ static void disarm_sock_keys(struct mem_cgroup *memcg)
 #ifdef CONFIG_MEMCG_KMEM
 /*
  * This will be the memcg's index in each cache's ->memcg_params->memcg_caches.
- * There are two main reasons for not using the css_id for this:
- *  1) this works better in sparse environments, where we have a lot of memcgs,
- *     but only a few kmem-limited. Or also, if we have, for instance, 200
- *     memcgs, and none but the 200th is kmem-limited, we'd have to have a
- *     200 entry array for that.
- *
- *  2) In order not to violate the cgroup API, we would like to do all memory
- *     allocation in ->create(). At that point, we haven't yet allocated the
- *     css_id. Having a separate index prevents us from messing with the cgroup
- *     core for this
+ * The main reason for not using cgroup id for this:
+ *  this works better in sparse environments, where we have a lot of memcgs,
+ *  but only a few kmem-limited. Or also, if we have, for instance, 200
+ *  memcgs, and none but the 200th is kmem-limited, we'd have to have a
+ *  200 entry array for that.
  *
  * The current size of the caches array is stored in
  * memcg_limited_groups_array_size.  It will double each time we have to
@@ -595,14 +613,14 @@ int memcg_limited_groups_array_size;
  * cgroups is a reasonable guess. In the future, it could be a parameter or
  * tunable, but that is strictly not necessary.
  *
- * MAX_SIZE should be as large as the number of css_ids. Ideally, we could get
+ * MAX_SIZE should be as large as the number of cgrp_ids. Ideally, we could get
  * this constant directly from cgroup, but it is understandable that this is
  * better kept as an internal representation in cgroup.c. In any case, the
- * css_id space is not getting any smaller, and we don't have to necessarily
+ * cgrp_id space is not getting any smaller, and we don't have to necessarily
  * increase ours as well if it increases.
  */
 #define MEMCG_CACHES_MIN_SIZE 4
-#define MEMCG_CACHES_MAX_SIZE 65535
+#define MEMCG_CACHES_MAX_SIZE MEM_CGROUP_ID_MAX
 
 /*
  * A lot of the calls to the cache allocation functions are expected to be
@@ -1409,7 +1427,7 @@ bool __mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
                return true;
        if (!root_memcg->use_hierarchy || !memcg)
                return false;
-       return css_is_ancestor(&memcg->css, &root_memcg->css);
+       return cgroup_is_descendant(memcg->css.cgroup, root_memcg->css.cgroup);
 }
 
 static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
@@ -2827,15 +2845,10 @@ static void __mem_cgroup_cancel_local_charge(struct mem_cgroup *memcg,
  */
 static struct mem_cgroup *mem_cgroup_lookup(unsigned short id)
 {
-       struct cgroup_subsys_state *css;
-
        /* ID 0 is unused ID */
        if (!id)
                return NULL;
-       css = css_lookup(&mem_cgroup_subsys, id);
-       if (!css)
-               return NULL;
-       return mem_cgroup_from_css(css);
+       return mem_cgroup_from_id(id);
 }
 
 struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
@@ -4344,7 +4357,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout)
         * css_get() was called in uncharge().
         */
        if (do_swap_account && swapout && memcg)
-               swap_cgroup_record(ent, css_id(&memcg->css));
+               swap_cgroup_record(ent, mem_cgroup_id(memcg));
 }
 #endif
 
@@ -4396,8 +4409,8 @@ static int mem_cgroup_move_swap_account(swp_entry_t entry,
 {
        unsigned short old_id, new_id;
 
-       old_id = css_id(&from->css);
-       new_id = css_id(&to->css);
+       old_id = mem_cgroup_id(from);
+       new_id = mem_cgroup_id(to);
 
        if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) {
                mem_cgroup_swap_statistics(from, false);
@@ -6165,7 +6178,6 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
        size_t size = memcg_size();
 
        mem_cgroup_remove_from_trees(memcg);
-       free_css_id(&mem_cgroup_subsys, &memcg->css);
 
        for_each_node(node)
                free_mem_cgroup_per_zone_info(memcg, node);
@@ -6268,6 +6280,9 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
        struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css));
        int error = 0;
 
+       if (css->cgroup->id > MEM_CGROUP_ID_MAX)
+               return -ENOSPC;
+
        if (!parent)
                return 0;
 
@@ -6539,7 +6554,7 @@ static enum mc_target_type get_mctgt_type(struct vm_area_struct *vma,
        }
        /* There is a swap entry and a page doesn't exist or isn't charged */
        if (ent.val && !ret &&
-                       css_id(&mc.from->css) == lookup_swap_cgroup_id(ent)) {
+           mem_cgroup_id(mc.from) == lookup_swap_cgroup_id(ent)) {
                ret = MC_TARGET_SWAP;
                if (target)
                        target->ent = ent;
@@ -6959,7 +6974,6 @@ struct cgroup_subsys mem_cgroup_subsys = {
        .bind = mem_cgroup_bind,
        .base_cftypes = mem_cgroup_files,
        .early_init = 0,
-       .use_id = 1,
 };
 
 #ifdef CONFIG_MEMCG_SWAP