Merge tag 'staging-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[linux-2.6-microblaze.git] / mm / memcontrol.c
index 7a4bd8b..7ddf91c 100644 (file)
@@ -777,6 +777,17 @@ void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
        rcu_read_unlock();
 }
 
+void mod_memcg_obj_state(void *p, int idx, int val)
+{
+       struct mem_cgroup *memcg;
+
+       rcu_read_lock();
+       memcg = mem_cgroup_from_obj(p);
+       if (memcg)
+               mod_memcg_state(memcg, idx, val);
+       rcu_read_unlock();
+}
+
 /**
  * __count_memcg_events - account VM events in a cgroup
  * @memcg: the memory cgroup
@@ -2661,6 +2672,33 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg,
 }
 
 #ifdef CONFIG_MEMCG_KMEM
+/*
+ * Returns a pointer to the memory cgroup to which the kernel object is charged.
+ *
+ * The caller must ensure the memcg lifetime, e.g. by taking rcu_read_lock(),
+ * cgroup_mutex, etc.
+ */
+struct mem_cgroup *mem_cgroup_from_obj(void *p)
+{
+       struct page *page;
+
+       if (mem_cgroup_disabled())
+               return NULL;
+
+       page = virt_to_head_page(p);
+
+       /*
+        * Slab pages don't have page->mem_cgroup set because corresponding
+        * kmem caches can be reparented during the lifetime. That's why
+        * memcg_from_slab_page() should be used instead.
+        */
+       if (PageSlab(page))
+               return memcg_from_slab_page(page);
+
+       /* All other pages use page->mem_cgroup */
+       return page->mem_cgroup;
+}
+
 static int memcg_alloc_cache_id(void)
 {
        int id, size;