Thread (18 messages) 18 messages, 4 authors, 2021-03-02

Re: [PATCH 2/5] mm: memcontrol: make page_memcg{_rcu} only applicable for non-kmem page

From: Shakeel Butt <hidden>
Date: 2021-03-01 18:15:30
Also in: bpf, linux-fsdevel, linux-mm, lkml, netdev

On Sun, Feb 28, 2021 at 10:25 PM Muchun Song [off-list ref] wrote:
We want to reuse the obj_cgroup APIs to reparent the kmem pages when
the memcg offlined. If we do this, we should store an object cgroup
pointer to page->memcg_data for the kmem pages.

Finally, page->memcg_data can have 3 different meanings.

  1) For the slab pages, page->memcg_data points to an object cgroups
     vector.

  2) For the kmem pages (exclude the slab pages), page->memcg_data
     points to an object cgroup.

  3) For the user pages (e.g. the LRU pages), page->memcg_data points
     to a memory cgroup.

Currently we always get the memcg associated with a page via page_memcg
or page_memcg_rcu. page_memcg_check is special, it has to be used in
cases when it's not known if a page has an associated memory cgroup
pointer or an object cgroups vector. Because the page->memcg_data of
the kmem page is not pointing to a memory cgroup in the later patch,
the page_memcg and page_memcg_rcu cannot be applicable for the kmem
pages. In this patch, we introduce page_memcg_kmem to get the memcg
associated with the kmem pages. And make page_memcg and page_memcg_rcu
no longer apply to the kmem pages.

In the end, there are 4 helpers to get the memcg associated with a
page. The usage is as follows.

  1) Get the memory cgroup associated with a non-kmem page (e.g. the LRU
     pages).

     - page_memcg()
     - page_memcg_rcu()
Can you rename these to page_memcg_lru[_rcu] to make them explicitly
for LRU pages?
  2) Get the memory cgroup associated with a kmem page (exclude the slab
     pages).

     - page_memcg_kmem()

  3) Get the memory cgroup associated with a page. It has to be used in
     cases when it's not known if a page has an associated memory cgroup
     pointer or an object cgroups vector. Returns NULL for slab pages or
     uncharged pages, otherwise, returns memory cgroup for charged pages
     (e.g. kmem pages, LRU pages).

     - page_memcg_check()

In some place, we use page_memcg to check whether the page is charged.
Now we introduce page_memcg_charged helper to do this.

This is a preparation for reparenting the kmem pages. To support reparent
kmem pages, we just need to adjust page_memcg_kmem and page_memcg_check in
the later patch.

Signed-off-by: Muchun Song <redacted>
---
[snip]
quoted hunk ↗ jump to hunk
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -855,10 +855,11 @@ void __mod_lruvec_page_state(struct page *page, enum node_stat_item idx,
                             int val)
 {
        struct page *head = compound_head(page); /* rmap on tail pages */
-       struct mem_cgroup *memcg = page_memcg(head);
+       struct mem_cgroup *memcg;
        pg_data_t *pgdat = page_pgdat(page);
        struct lruvec *lruvec;

+       memcg = PageMemcgKmem(head) ? page_memcg_kmem(head) : page_memcg(head);
Should page_memcg_check() be used here?
quoted hunk ↗ jump to hunk
        /* Untracked pages have no memcg, no lruvec. Update only the node */
        if (!memcg) {
                __mod_node_page_state(pgdat, idx, val);
@@ -3170,12 +3171,13 @@ int __memcg_kmem_charge_page(struct page *page, gfp_t gfp, int order)
  */
 void __memcg_kmem_uncharge_page(struct page *page, int order)
 {
-       struct mem_cgroup *memcg = page_memcg(page);
+       struct mem_cgroup *memcg;
        unsigned int nr_pages = 1 << order;

-       if (!memcg)
+       if (!page_memcg_charged(page))
                return;

+       memcg = page_memcg_kmem(page);
        VM_BUG_ON_PAGE(mem_cgroup_is_root(memcg), page);
        __memcg_kmem_uncharge(memcg, nr_pages);
        page->memcg_data = 0;
@@ -6831,24 +6833,25 @@ static void uncharge_batch(const struct uncharge_gather *ug)
 static void uncharge_page(struct page *page, struct uncharge_gather *ug)
 {
        unsigned long nr_pages;
+       struct mem_cgroup *memcg;

        VM_BUG_ON_PAGE(PageLRU(page), page);

-       if (!page_memcg(page))
+       if (!page_memcg_charged(page))
                return;

        /*
         * Nobody should be changing or seriously looking at
-        * page_memcg(page) at this point, we have fully
-        * exclusive access to the page.
+        * page memcg at this point, we have fully exclusive
+        * access to the page.
         */
-
-       if (ug->memcg != page_memcg(page)) {
+       memcg = PageMemcgKmem(page) ? page_memcg_kmem(page) : page_memcg(page);
Same, should page_memcg_check() be used here?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help