Merge branch 'akpm' (patches from Andrew)
[linux-2.6-microblaze.git] / mm / memcontrol.c
index c9ddd02..09d342c 100644 (file)
@@ -2823,31 +2823,31 @@ static inline void mod_objcg_mlstate(struct obj_cgroup *objcg,
        rcu_read_unlock();
 }
 
-int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s,
-                                gfp_t gfp, bool new_page)
+int memcg_alloc_slab_cgroups(struct slab *slab, struct kmem_cache *s,
+                                gfp_t gfp, bool new_slab)
 {
-       unsigned int objects = objs_per_slab_page(s, page);
+       unsigned int objects = objs_per_slab(s, slab);
        unsigned long memcg_data;
        void *vec;
 
        gfp &= ~OBJCGS_CLEAR_MASK;
        vec = kcalloc_node(objects, sizeof(struct obj_cgroup *), gfp,
-                          page_to_nid(page));
+                          slab_nid(slab));
        if (!vec)
                return -ENOMEM;
 
        memcg_data = (unsigned long) vec | MEMCG_DATA_OBJCGS;
-       if (new_page) {
+       if (new_slab) {
                /*
-                * If the slab page is brand new and nobody can yet access
-                * it's memcg_data, no synchronization is required and
-                * memcg_data can be simply assigned.
+                * If the slab is brand new and nobody can yet access its
+                * memcg_data, no synchronization is required and memcg_data can
+                * be simply assigned.
                 */
-               page->memcg_data = memcg_data;
-       } else if (cmpxchg(&page->memcg_data, 0, memcg_data)) {
+               slab->memcg_data = memcg_data;
+       } else if (cmpxchg(&slab->memcg_data, 0, memcg_data)) {
                /*
-                * If the slab page is already in use, somebody can allocate
-                * and assign obj_cgroups in parallel. In this case the existing
+                * If the slab is already in use, somebody can allocate and
+                * assign obj_cgroups in parallel. In this case the existing
                 * objcg vector should be reused.
                 */
                kfree(vec);
@@ -2872,38 +2872,43 @@ int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s,
  */
 struct mem_cgroup *mem_cgroup_from_obj(void *p)
 {
-       struct page *page;
+       struct folio *folio;
 
        if (mem_cgroup_disabled())
                return NULL;
 
-       page = virt_to_head_page(p);
+       folio = virt_to_folio(p);
 
        /*
         * Slab objects are accounted individually, not per-page.
         * Memcg membership data for each individual object is saved in
-        * the page->obj_cgroups.
+        * slab->memcg_data.
         */
-       if (page_objcgs_check(page)) {
-               struct obj_cgroup *objcg;
+       if (folio_test_slab(folio)) {
+               struct obj_cgroup **objcgs;
+               struct slab *slab;
                unsigned int off;
 
-               off = obj_to_index(page->slab_cache, page, p);
-               objcg = page_objcgs(page)[off];
-               if (objcg)
-                       return obj_cgroup_memcg(objcg);
+               slab = folio_slab(folio);
+               objcgs = slab_objcgs(slab);
+               if (!objcgs)
+                       return NULL;
+
+               off = obj_to_index(slab->slab_cache, slab, p);
+               if (objcgs[off])
+                       return obj_cgroup_memcg(objcgs[off]);
 
                return NULL;
        }
 
        /*
-        * page_memcg_check() is used here, because page_has_obj_cgroups()
-        * check above could fail because the object cgroups vector wasn't set
-        * at that moment, but it can be set concurrently.
+        * page_memcg_check() is used here, because in theory we can encounter
+        * a folio where the slab flag has been cleared already, but
+        * slab->memcg_data has not been freed yet
         * page_memcg_check(page) will guarantee that a proper memory
         * cgroup pointer or NULL will be returned.
         */
-       return page_memcg_check(page);
+       return page_memcg_check(folio_page(folio, 0));
 }
 
 __always_inline struct obj_cgroup *get_obj_cgroup_from_current(void)