OSDN Git Service

Merge tag 'driver-core-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[uclinux-h8/linux.git] / mm / page_owner.c
index 99e360d..fb3a05f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/migrate.h>
 #include <linux/stackdepot.h>
 #include <linux/seq_file.h>
+#include <linux/memcontrol.h>
 #include <linux/sched/clock.h>
 
 #include "internal.h"
@@ -28,7 +29,9 @@ struct page_owner {
        depot_stack_handle_t free_handle;
        u64 ts_nsec;
        u64 free_ts_nsec;
+       char comm[TASK_COMM_LEN];
        pid_t pid;
+       pid_t tgid;
 };
 
 static bool page_owner_enabled = false;
@@ -163,7 +166,10 @@ static inline void __set_page_owner_handle(struct page_ext *page_ext,
                page_owner->gfp_mask = gfp_mask;
                page_owner->last_migrate_reason = -1;
                page_owner->pid = current->pid;
+               page_owner->tgid = current->tgid;
                page_owner->ts_nsec = local_clock();
+               strlcpy(page_owner->comm, current->comm,
+                       sizeof(page_owner->comm));
                __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
                __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
 
@@ -229,8 +235,10 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old)
                old_page_owner->last_migrate_reason;
        new_page_owner->handle = old_page_owner->handle;
        new_page_owner->pid = old_page_owner->pid;
+       new_page_owner->tgid = old_page_owner->tgid;
        new_page_owner->ts_nsec = old_page_owner->ts_nsec;
        new_page_owner->free_ts_nsec = old_page_owner->ts_nsec;
+       strcpy(new_page_owner->comm, old_page_owner->comm);
 
        /*
         * We don't clear the bit on the old folio as it's going to be freed
@@ -325,6 +333,45 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
        seq_putc(m, '\n');
 }
 
+/*
+ * Looking for memcg information and print it out
+ */
+static inline int print_page_owner_memcg(char *kbuf, size_t count, int ret,
+                                        struct page *page)
+{
+#ifdef CONFIG_MEMCG
+       unsigned long memcg_data;
+       struct mem_cgroup *memcg;
+       bool online;
+       char name[80];
+
+       rcu_read_lock();
+       memcg_data = READ_ONCE(page->memcg_data);
+       if (!memcg_data)
+               goto out_unlock;
+
+       if (memcg_data & MEMCG_DATA_OBJCGS)
+               ret += scnprintf(kbuf + ret, count - ret,
+                               "Slab cache page\n");
+
+       memcg = page_memcg_check(page);
+       if (!memcg)
+               goto out_unlock;
+
+       online = (memcg->css.flags & CSS_ONLINE);
+       cgroup_name(memcg->css.cgroup, name, sizeof(name));
+       ret += scnprintf(kbuf + ret, count - ret,
+                       "Charged %sto %smemcg %s\n",
+                       PageMemcgKmem(page) ? "(via objcg) " : "",
+                       online ? "" : "offline ",
+                       name);
+out_unlock:
+       rcu_read_unlock();
+#endif /* CONFIG_MEMCG */
+
+       return ret;
+}
+
 static ssize_t
 print_page_owner(char __user *buf, size_t count, unsigned long pfn,
                struct page *page, struct page_owner *page_owner,
@@ -338,19 +385,17 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
        if (!kbuf)
                return -ENOMEM;
 
-       ret = snprintf(kbuf, count,
-                       "Page allocated via order %u, mask %#x(%pGg), pid %d, ts %llu ns, free_ts %llu ns\n",
+       ret = scnprintf(kbuf, count,
+                       "Page allocated via order %u, mask %#x(%pGg), pid %d, tgid %d (%s), ts %llu ns, free_ts %llu ns\n",
                        page_owner->order, page_owner->gfp_mask,
                        &page_owner->gfp_mask, page_owner->pid,
+                       page_owner->tgid, page_owner->comm,
                        page_owner->ts_nsec, page_owner->free_ts_nsec);
 
-       if (ret >= count)
-               goto err;
-
        /* Print information relevant to grouping pages by mobility */
        pageblock_mt = get_pageblock_migratetype(page);
        page_mt  = gfp_migratetype(page_owner->gfp_mask);
-       ret += snprintf(kbuf + ret, count - ret,
+       ret += scnprintf(kbuf + ret, count - ret,
                        "PFN %lu type %s Block %lu type %s Flags %pGp\n",
                        pfn,
                        migratetype_names[page_mt],
@@ -358,21 +403,18 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
                        migratetype_names[pageblock_mt],
                        &page->flags);
 
-       if (ret >= count)
-               goto err;
-
        ret += stack_depot_snprint(handle, kbuf + ret, count - ret, 0);
        if (ret >= count)
                goto err;
 
        if (page_owner->last_migrate_reason != -1) {
-               ret += snprintf(kbuf + ret, count - ret,
+               ret += scnprintf(kbuf + ret, count - ret,
                        "Page has been migrated, last migrate reason: %s\n",
                        migrate_reason_names[page_owner->last_migrate_reason]);
-               if (ret >= count)
-                       goto err;
        }
 
+       ret = print_page_owner_memcg(kbuf, count, ret, page);
+
        ret += snprintf(kbuf + ret, count - ret, "\n");
        if (ret >= count)
                goto err;
@@ -415,9 +457,10 @@ void __dump_page_owner(const struct page *page)
        else
                pr_alert("page_owner tracks the page as freed\n");
 
-       pr_alert("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg), pid %d, ts %llu, free_ts %llu\n",
+       pr_alert("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg), pid %d, tgid %d (%s), ts %llu, free_ts %llu\n",
                 page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask,
-                page_owner->pid, page_owner->ts_nsec, page_owner->free_ts_nsec);
+                page_owner->pid, page_owner->tgid, page_owner->comm,
+                page_owner->ts_nsec, page_owner->free_ts_nsec);
 
        handle = READ_ONCE(page_owner->handle);
        if (!handle)