It'd be useful to show dept internal stats and dependency graph on
runtime via proc for better information.  Introduce the knobs.

Signed-off-by: Byungchul Park <[email protected]>
---
 kernel/dependency/Makefile        |  1 +
 kernel/dependency/dept.c          | 11 +---
 kernel/dependency/dept_internal.h | 10 ++++
 kernel/dependency/dept_proc.c     | 96 +++++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 9 deletions(-)
 create mode 100644 kernel/dependency/dept_proc.c

diff --git a/kernel/dependency/Makefile b/kernel/dependency/Makefile
index b5cfb8a03c0c..92f165400187 100644
--- a/kernel/dependency/Makefile
+++ b/kernel/dependency/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_DEPT) += dept.o
+obj-$(CONFIG_DEPT) += dept_proc.o
diff --git a/kernel/dependency/dept.c b/kernel/dependency/dept.c
index 18b238931699..dfe9dfdb6991 100644
--- a/kernel/dependency/dept.c
+++ b/kernel/dependency/dept.c
@@ -266,20 +266,13 @@ static bool valid_key(struct dept_key *k)
  *       have been freed will be placed.
  */
 
-enum object_t {
-#define OBJECT(id, nr) OBJECT_##id,
-       #include "dept_object.h"
-#undef OBJECT
-       OBJECT_NR,
-};
-
 #define OBJECT(id, nr)                                                 \
 static struct dept_##id spool_##id[nr];                                        
\
 static DEFINE_PER_CPU(struct llist_head, lpool_##id);
        #include "dept_object.h"
 #undef OBJECT
 
-static struct dept_pool dept_pool[OBJECT_NR] = {
+struct dept_pool dept_pool[OBJECT_NR] = {
 #define OBJECT(id, nr) {                                               \
        .name = #id,                                                    \
        .obj_sz = sizeof(struct dept_##id),                             \
@@ -2083,7 +2076,7 @@ void dept_map_copy(struct dept_map *to, struct dept_map 
*from)
        clean_classes_cache(&to->map_key);
 }
 
-static LIST_HEAD(dept_classes);
+LIST_HEAD(dept_classes);
 
 static bool within(const void *addr, void *start, unsigned long size)
 {
diff --git a/kernel/dependency/dept_internal.h 
b/kernel/dependency/dept_internal.h
index 9b28398fecfd..a1eb1ed647a7 100644
--- a/kernel/dependency/dept_internal.h
+++ b/kernel/dependency/dept_internal.h
@@ -279,5 +279,15 @@ struct dept_hash {
        int                             bits;
 };
 
+enum object_t {
+#define OBJECT(id, nr) OBJECT_##id,
+       #include "dept_object.h"
+#undef OBJECT
+       OBJECT_NR,
+};
+
+extern struct list_head dept_classes;
+extern struct dept_pool dept_pool[];
+
 #endif
 #endif /* __DEPT_INTERNAL_H */
diff --git a/kernel/dependency/dept_proc.c b/kernel/dependency/dept_proc.c
new file mode 100644
index 000000000000..97beaf397715
--- /dev/null
+++ b/kernel/dependency/dept_proc.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Procfs knobs for Dept(DEPendency Tracker)
+ *
+ * Started by Byungchul Park <[email protected]>:
+ *
+ *  Copyright (C) 2021 LG Electronics, Inc. , Byungchul Park
+ *  Copyright (C) 2024 SK hynix, Inc. , Byungchul Park
+ */
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/dept.h>
+#include "dept_internal.h"
+
+static void *l_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       /*
+        * XXX: Serialize list traversal if needed. The following might
+        * give a wrong information on contention.
+        */
+       return seq_list_next(v, &dept_classes, pos);
+}
+
+static void *l_start(struct seq_file *m, loff_t *pos)
+{
+       /*
+        * XXX: Serialize list traversal if needed. The following might
+        * give a wrong information on contention.
+        */
+       return seq_list_start_head(&dept_classes, *pos);
+}
+
+static void l_stop(struct seq_file *m, void *v)
+{
+}
+
+static int l_show(struct seq_file *m, void *v)
+{
+       struct dept_class *fc = list_entry(v, struct dept_class, all_node);
+       struct dept_dep *d;
+       const char *prefix;
+
+       if (v == &dept_classes) {
+               seq_puts(m, "All classes:\n\n");
+               return 0;
+       }
+
+       prefix = fc->sched_map ? "<sched> " : "";
+       seq_printf(m, "[%p] %s%s\n", (void *)fc->key, prefix, fc->name);
+
+       /*
+        * XXX: Serialize list traversal if needed. The following might
+        * give a wrong information on contention.
+        */
+       list_for_each_entry(d, &fc->dep_head, dep_node) {
+               struct dept_class *tc = d->wait->class;
+
+               prefix = tc->sched_map ? "<sched> " : "";
+               seq_printf(m, " -> [%p] %s%s\n", (void *)tc->key, prefix, 
tc->name);
+       }
+       seq_puts(m, "\n");
+
+       return 0;
+}
+
+static const struct seq_operations dept_deps_ops = {
+       .start  = l_start,
+       .next   = l_next,
+       .stop   = l_stop,
+       .show   = l_show,
+};
+
+static int dept_stats_show(struct seq_file *m, void *v)
+{
+       int r;
+
+       seq_puts(m, "Availability in the static pools:\n\n");
+#define OBJECT(id, nr)                                                 \
+       r = atomic_read(&dept_pool[OBJECT_##id].obj_nr);                \
+       if (r < 0)                                                      \
+               r = 0;                                                  \
+       seq_printf(m, "%s\t%d/%d(%d%%)\n", #id, r, nr, (r * 100) / (nr));
+       #include "dept_object.h"
+#undef  OBJECT
+
+       return 0;
+}
+
+static int __init dept_proc_init(void)
+{
+       proc_create_seq("dept_deps", S_IRUSR, NULL, &dept_deps_ops);
+       proc_create_single("dept_stats", S_IRUSR, NULL, dept_stats_show);
+       return 0;
+}
+
+__initcall(dept_proc_init);
-- 
2.17.1


Reply via email to