[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250513100730.12664-43-byungchul@sk.com>
Date: Tue, 13 May 2025 19:07:29 +0900
From: Byungchul Park <byungchul@...com>
To: linux-kernel@...r.kernel.org
Cc: kernel_team@...ynix.com,
torvalds@...ux-foundation.org,
damien.lemoal@...nsource.wdc.com,
linux-ide@...r.kernel.org,
adilger.kernel@...ger.ca,
linux-ext4@...r.kernel.org,
mingo@...hat.com,
peterz@...radead.org,
will@...nel.org,
tglx@...utronix.de,
rostedt@...dmis.org,
joel@...lfernandes.org,
sashal@...nel.org,
daniel.vetter@...ll.ch,
duyuyang@...il.com,
johannes.berg@...el.com,
tj@...nel.org,
tytso@....edu,
willy@...radead.org,
david@...morbit.com,
amir73il@...il.com,
gregkh@...uxfoundation.org,
kernel-team@....com,
linux-mm@...ck.org,
akpm@...ux-foundation.org,
mhocko@...nel.org,
minchan@...nel.org,
hannes@...xchg.org,
vdavydov.dev@...il.com,
sj@...nel.org,
jglisse@...hat.com,
dennis@...nel.org,
cl@...ux.com,
penberg@...nel.org,
rientjes@...gle.com,
vbabka@...e.cz,
ngupta@...are.org,
linux-block@...r.kernel.org,
josef@...icpanda.com,
linux-fsdevel@...r.kernel.org,
jack@...e.cz,
jlayton@...nel.org,
dan.j.williams@...el.com,
hch@...radead.org,
djwong@...nel.org,
dri-devel@...ts.freedesktop.org,
rodrigosiqueiramelo@...il.com,
melissa.srw@...il.com,
hamohammed.sa@...il.com,
harry.yoo@...cle.com,
chris.p.wilson@...el.com,
gwan-gyeong.mun@...el.com,
max.byungchul.park@...il.com,
boqun.feng@...il.com,
longman@...hat.com,
yskelg@...il.com,
yunseong.kim@...csson.com,
yeoreum.yun@....com,
netdev@...r.kernel.org,
matthew.brost@...el.com,
her0gyugyu@...il.com
Subject: [PATCH v15 42/43] dept: implement a basic unit test for dept
Implement CONFIG_DEPT_UNIT_TEST introducing a kernel module that runs
basic unit test for dept.
Signed-off-by: Byungchul Park <byungchul@...com>
---
include/linux/dept_unit_test.h | 67 +++++++++++
kernel/dependency/Makefile | 1 +
kernel/dependency/dept.c | 12 ++
kernel/dependency/dept_unit_test.c | 173 +++++++++++++++++++++++++++++
lib/Kconfig.debug | 12 ++
5 files changed, 265 insertions(+)
create mode 100644 include/linux/dept_unit_test.h
create mode 100644 kernel/dependency/dept_unit_test.c
diff --git a/include/linux/dept_unit_test.h b/include/linux/dept_unit_test.h
new file mode 100644
index 000000000000..51660f534104
--- /dev/null
+++ b/include/linux/dept_unit_test.h
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DEPT unit test
+ *
+ * Copyright (C) SK hynix, 2025
+ *
+ * Authors: Byungchul Park <max.byungchul.park@...il.com>
+ */
+
+#ifndef __LINUX_DEPT_UNIT_TEST_H
+#define __LINUX_DEPT_UNIT_TEST_H
+
+#if defined(CONFIG_DEPT_UNIT_TEST) || defined(CONFIG_DEPT_UNIT_TEST_MODULE)
+struct dept_ut {
+ bool circle_detected;
+ bool recover_circle_detected;
+
+ int ecxt_stack_total_cnt;
+ int wait_stack_total_cnt;
+ int evnt_stack_total_cnt;
+ int ecxt_stack_valid_cnt;
+ int wait_stack_valid_cnt;
+ int evnt_stack_valid_cnt;
+};
+
+extern struct dept_ut dept_ut_results;
+
+static inline void dept_ut_circle_detect(void)
+{
+ dept_ut_results.circle_detected = true;
+}
+static inline void dept_ut_recover_circle_detect(void)
+{
+ dept_ut_results.recover_circle_detected = true;
+}
+static inline void dept_ut_ecxt_stack_account(bool valid)
+{
+ dept_ut_results.ecxt_stack_total_cnt++;
+
+ if (valid)
+ dept_ut_results.ecxt_stack_valid_cnt++;
+}
+static inline void dept_ut_wait_stack_account(bool valid)
+{
+ dept_ut_results.wait_stack_total_cnt++;
+
+ if (valid)
+ dept_ut_results.wait_stack_valid_cnt++;
+}
+static inline void dept_ut_evnt_stack_account(bool valid)
+{
+ dept_ut_results.evnt_stack_total_cnt++;
+
+ if (valid)
+ dept_ut_results.evnt_stack_valid_cnt++;
+}
+#else
+struct dept_ut {};
+
+#define dept_ut_circle_detect() do { } while (0)
+#define dept_ut_recover_circle_detect() do { } while (0)
+#define dept_ut_ecxt_stack_account(v) do { } while (0)
+#define dept_ut_wait_stack_account(v) do { } while (0)
+#define dept_ut_evnt_stack_account(v) do { } while (0)
+
+#endif
+#endif /* __LINUX_DEPT_UNIT_TEST_H */
diff --git a/kernel/dependency/Makefile b/kernel/dependency/Makefile
index 92f165400187..fc584ca87124 100644
--- a/kernel/dependency/Makefile
+++ b/kernel/dependency/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_DEPT) += dept.o
obj-$(CONFIG_DEPT) += dept_proc.o
+obj-$(CONFIG_DEPT_UNIT_TEST) += dept_unit_test.o
diff --git a/kernel/dependency/dept.c b/kernel/dependency/dept.c
index 03d6c057cdc5..50ba3e1c3fd5 100644
--- a/kernel/dependency/dept.c
+++ b/kernel/dependency/dept.c
@@ -77,8 +77,12 @@
#include <linux/workqueue.h>
#include <linux/irq_work.h>
#include <linux/vmalloc.h>
+#include <linux/dept_unit_test.h>
#include "dept_internal.h"
+struct dept_ut dept_ut_results;
+EXPORT_SYMBOL_GPL(dept_ut_results);
+
static int dept_stop;
static int dept_per_cpu_ready;
@@ -826,6 +830,10 @@ static void print_dep(struct dept_dep *d)
pr_warn("(wait to wake up)\n");
print_ip_stack(0, e->ewait_stack);
}
+
+ dept_ut_ecxt_stack_account(valid_stack(e->ecxt_stack));
+ dept_ut_wait_stack_account(valid_stack(w->wait_stack));
+ dept_ut_evnt_stack_account(valid_stack(e->event_stack));
}
}
@@ -926,6 +934,8 @@ static void print_circle(struct dept_class *c)
tc = fc;
fc = fc->bfs_parent;
} while (tc != c);
+
+ dept_ut_circle_detect();
}
/*
@@ -1027,6 +1037,8 @@ static void print_recover_circle(struct dept_event_site *es)
dump_stack();
dept_outworld_exit();
+
+ dept_ut_recover_circle_detect();
}
static void bfs_init_recover(void *node, void *in, void **out)
diff --git a/kernel/dependency/dept_unit_test.c b/kernel/dependency/dept_unit_test.c
new file mode 100644
index 000000000000..489a7870f2c4
--- /dev/null
+++ b/kernel/dependency/dept_unit_test.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DEPT unit test
+ *
+ * Copyright (C) SK hynix, 2025
+ *
+ * Authors: Byungchul Park <max.byungchul.park@...il.com>
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/dept.h>
+#include <linux/dept_unit_test.h>
+
+MODULE_DESCRIPTION("DEPT unit test");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Byungchul Park <max.byungchul.park@...com>");
+
+struct unit {
+ const char *name;
+ bool (*func)(void);
+ bool result;
+};
+
+static DEFINE_SPINLOCK(s1);
+static DEFINE_SPINLOCK(s2);
+static bool test_spin_lock_deadlock(void)
+{
+ dept_ut_results.circle_detected = false;
+
+ spin_lock(&s1);
+ spin_lock(&s2);
+ spin_unlock(&s2);
+ spin_unlock(&s1);
+
+ spin_lock(&s2);
+ spin_lock(&s1);
+ spin_unlock(&s1);
+ spin_unlock(&s2);
+
+ return dept_ut_results.circle_detected;
+}
+
+static DEFINE_MUTEX(m1);
+static DEFINE_MUTEX(m2);
+static bool test_mutex_lock_deadlock(void)
+{
+ dept_ut_results.circle_detected = false;
+
+ mutex_lock(&m1);
+ mutex_lock(&m2);
+ mutex_unlock(&m2);
+ mutex_unlock(&m1);
+
+ mutex_lock(&m2);
+ mutex_lock(&m1);
+ mutex_unlock(&m1);
+ mutex_unlock(&m2);
+
+ return dept_ut_results.circle_detected;
+}
+
+static bool test_wait_event_deadlock(void)
+{
+ struct dept_map dmap1;
+ struct dept_map dmap2;
+
+ sdt_map_init(&dmap1);
+ sdt_map_init(&dmap2);
+
+ dept_ut_results.circle_detected = false;
+
+ sdt_request_event(&dmap1); /* [S] */
+ sdt_wait(&dmap2); /* [W] */
+ sdt_event(&dmap1); /* [E] */
+
+ sdt_request_event(&dmap2); /* [S] */
+ sdt_wait(&dmap1); /* [W] */
+ sdt_event(&dmap2); /* [E] */
+
+ return dept_ut_results.circle_detected;
+}
+
+static void dummy_event(void)
+{
+ /* Do nothing. */
+}
+
+static DEFINE_DEPT_EVENT_SITE(es1);
+static DEFINE_DEPT_EVENT_SITE(es2);
+static bool test_recover_deadlock(void)
+{
+ dept_ut_results.recover_circle_detected = false;
+
+ dept_recover_event(&es1, &es2);
+ dept_recover_event(&es2, &es1);
+
+ event_site(&es1, dummy_event);
+ event_site(&es2, dummy_event);
+
+ return dept_ut_results.recover_circle_detected;
+}
+
+static struct unit units[] = {
+ {
+ .name = "spin lock deadlock test",
+ .func = test_spin_lock_deadlock,
+ },
+ {
+ .name = "mutex lock deadlock test",
+ .func = test_mutex_lock_deadlock,
+ },
+ {
+ .name = "wait event deadlock test",
+ .func = test_wait_event_deadlock,
+ },
+ {
+ .name = "event recover deadlock test",
+ .func = test_recover_deadlock,
+ },
+};
+
+static int __init dept_ut_init(void)
+{
+ int i;
+
+ lockdep_off();
+
+ dept_ut_results.ecxt_stack_valid_cnt = 0;
+ dept_ut_results.ecxt_stack_total_cnt = 0;
+ dept_ut_results.wait_stack_valid_cnt = 0;
+ dept_ut_results.wait_stack_total_cnt = 0;
+ dept_ut_results.evnt_stack_valid_cnt = 0;
+ dept_ut_results.evnt_stack_total_cnt = 0;
+
+ for (i = 0; i < ARRAY_SIZE(units); i++)
+ units[i].result = units[i].func();
+
+ pr_info("\n");
+ pr_info("******************************************\n");
+ pr_info("DEPT unit test results\n");
+ pr_info("******************************************\n");
+ for (i = 0; i < ARRAY_SIZE(units); i++) {
+ pr_info("(%s) %s\n", units[i].result ? "pass" : "fail",
+ units[i].name);
+ }
+ pr_info("ecxt stack valid count = %d/%d\n",
+ dept_ut_results.ecxt_stack_valid_cnt,
+ dept_ut_results.ecxt_stack_total_cnt);
+ pr_info("wait stack valid count = %d/%d\n",
+ dept_ut_results.wait_stack_valid_cnt,
+ dept_ut_results.wait_stack_total_cnt);
+ pr_info("event stack valid count = %d/%d\n",
+ dept_ut_results.evnt_stack_valid_cnt,
+ dept_ut_results.evnt_stack_total_cnt);
+ pr_info("******************************************\n");
+ pr_info("\n");
+
+ lockdep_on();
+
+ return 0;
+}
+
+static void dept_ut_cleanup(void)
+{
+ /*
+ * Do nothing for now.
+ */
+}
+
+module_init(dept_ut_init);
+module_exit(dept_ut_cleanup);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 7c74f92e4cc2..65f867e35be8 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1404,6 +1404,18 @@ config DEPT_AGGRESSIVE_TIMEOUT_WAIT
that timeout is used to avoid a deadlock. Say N if you'd like
to avoid verbose reports.
+config DEPT_UNIT_TEST
+ tristate "unit test for DEPT"
+ depends on DEBUG_KERNEL && DEPT
+ default n
+ help
+ This option provides a kernel module that runs unit test for
+ DEPT.
+
+ Say Y if you want DEPT unit test to be built into the kernel.
+ Say M if you want DEPT unit test to build as a module.
+ Say N if you are unsure.
+
config LOCK_DEBUGGING_SUPPORT
bool
depends on TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
--
2.17.1
Powered by blists - more mailing lists