Re: [RFC PATCH v2 1/3] meminfo_extra: introduce meminfo extra
From: Dave Young <hidden>
Date: 2020-03-23 12:01:07
Also in:
linux-mm, lkml
Hi Jaewon, On 03/23/20 at 05:05pm, Jaewon Kim wrote:
quoted hunk ↗ jump to hunk
Provide APIs to drivers so that they can show its memory usage on /proc/meminfo_extra. int register_meminfo_extra(atomic_long_t *val, int shift, const char *name); int unregister_meminfo_extra(atomic_long_t *val); Signed-off-by: Jaewon Kim <redacted> --- v2: move to /proc/meminfo_extra as a new file, meminfo_extra.c use rcu to reduce lock overhead v1: print info at /proc/meminfo --- fs/proc/Makefile | 1 + fs/proc/meminfo_extra.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/mm.h | 4 ++ mm/page_alloc.c | 1 + 4 files changed, 129 insertions(+) create mode 100644 fs/proc/meminfo_extra.cdiff --git a/fs/proc/Makefile b/fs/proc/Makefile index bd08616ed8ba..83d2f55591c6 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile@@ -19,6 +19,7 @@ proc-y += devices.o proc-y += interrupts.o proc-y += loadavg.o proc-y += meminfo.o +proc-y += meminfo_extra.o proc-y += stat.o proc-y += uptime.o proc-y += util.odiff --git a/fs/proc/meminfo_extra.c b/fs/proc/meminfo_extra.c new file mode 100644 index 000000000000..bd3f0d2b7fb7 --- /dev/null +++ b/fs/proc/meminfo_extra.c@@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/mm.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/slab.h> + +static void show_val_kb(struct seq_file *m, const char *s, unsigned long num) +{ + seq_put_decimal_ull_width(m, s, num << (PAGE_SHIFT - 10), 8); + seq_write(m, " kB\n", 4); +} + +static LIST_HEAD(meminfo_head); +static DEFINE_SPINLOCK(meminfo_lock); + +#define NAME_SIZE 15 +#define NAME_BUF_SIZE (NAME_SIZE + 2) /* ':' and '\0' */ + +struct meminfo_extra { + struct list_head list; + atomic_long_t *val; + int shift_for_page;
Can this be simplified to use a bytes value without an extra shift?
+ char name[NAME_BUF_SIZE]; + char name_pad[NAME_BUF_SIZE]; +}; +
There should be document about below function here.
+int register_meminfo_extra(atomic_long_t *val, int shift, const char *name)
+{
+ struct meminfo_extra *meminfo, *memtemp;
+ int len;
+ int error = 0;
+
+ meminfo = kzalloc(sizeof(*meminfo), GFP_KERNEL);
+ if (!meminfo) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ meminfo->val = val;
+ meminfo->shift_for_page = shift;
+ strncpy(meminfo->name, name, NAME_SIZE);
+ len = strlen(meminfo->name);
+ meminfo->name[len] = ':';
+ strncpy(meminfo->name_pad, meminfo->name, NAME_BUF_SIZE);
+ while (++len < NAME_BUF_SIZE - 1)
+ meminfo->name_pad[len] = ' ';
+
+ spin_lock(&meminfo_lock);
+ list_for_each_entry_rcu(memtemp, &meminfo_head, list) {
+ if (memtemp->val == val) {
+ error = -EINVAL;
+ break;
+ }
+ }
+ if (!error)
+ list_add_tail_rcu(&meminfo->list, &meminfo_head);
+ spin_unlock(&meminfo_lock);
+ if (error)
+ kfree(meminfo);
+out:
+
+ return error;
+}
+EXPORT_SYMBOL(register_meminfo_extra);
+
+int unregister_meminfo_extra(atomic_long_t *val)
+{
+ struct meminfo_extra *memtemp;
+ int error = -EINVAL;
+
+ spin_lock(&meminfo_lock);
+ list_for_each_entry_rcu(memtemp, &meminfo_head, list) {
+ if (memtemp->val == val) {
+ list_del_rcu(&memtemp->list);
+ error = 0;
+ break;
+ }
+ }
+ spin_unlock(&meminfo_lock);
+ if (!error) {
+ synchronize_rcu();
+ kfree(memtemp);
+ }
+
+ return error;
+}
+EXPORT_SYMBOL(unregister_meminfo_extra);
+
+static void __meminfo_extra(struct seq_file *m)
+{
+ struct meminfo_extra *memtemp;
+ unsigned long nr_page;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(memtemp, &meminfo_head, list) {
+ nr_page = (unsigned long)atomic_long_read(memtemp->val);
+ nr_page = nr_page >> memtemp->shift_for_page;
+ if (m)
+ show_val_kb(m, memtemp->name_pad, nr_page);
+ else
+ pr_cont("%s%lukB ", memtemp->name, nr_page);nr_page != nr_kb?
quoted hunk ↗ jump to hunk
+ } + rcu_read_unlock(); +} + +void show_meminfo_extra(void) +{ + __meminfo_extra(NULL); +} + +static int meminfo_extra_proc_show(struct seq_file *m, void *v) +{ + __meminfo_extra(m); + + return 0; +} + +static int __init proc_meminfo_extra_init(void) +{ + proc_create_single("meminfo_extra", 0, NULL, meminfo_extra_proc_show); + return 0; +} +fs_initcall(proc_meminfo_extra_init);diff --git a/include/linux/mm.h b/include/linux/mm.h index 52269e56c514..55317161ab57 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h@@ -2898,6 +2898,10 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif +void show_meminfo_extra(void); +int register_meminfo_extra(atomic_long_t *val, int shift, const char *name); +int unregister_meminfo_extra(atomic_long_t *val); + extern int memcmp_pages(struct page *page1, struct page *page2); static inline int pages_identical(struct page *page1, struct page *page2)diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3c4eb750a199..db1be9a39783 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c@@ -5229,6 +5229,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask) struct zone *zone; pg_data_t *pgdat; + show_meminfo_extra(); for_each_populated_zone(zone) { if (show_mem_node_skip(filter, zone_to_nid(zone), nodemask)) continue;-- 2.13.7 _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec
Thanks Dave