Oliver Neukum 8d1d68
From 317f29c14d0cca09952f1022491454b23455ebcb Mon Sep 17 00:00:00 2001
Oliver Neukum 8d1d68
From: Stephen Boyd <swboyd@chromium.org>
Oliver Neukum 8d1d68
Date: Wed, 11 May 2022 13:19:51 -0700
Oliver Neukum 8d1d68
Subject: [PATCH] timers: Provide a better debugobjects hint for delayed works
Oliver Neukum 8d1d68
Git-commit: 317f29c14d0cca09952f1022491454b23455ebcb
Oliver Neukum 8d1d68
References: bsc#1207210
Oliver Neukum 8d1d68
Patch-mainline: v5.19-rc1
Oliver Neukum 8d1d68
Oliver Neukum 8d1d68
With debugobjects enabled the timer hint for freeing of active timers
Oliver Neukum 8d1d68
embedded inside delayed works is always the same, i.e. the hint is
Oliver Neukum 8d1d68
delayed_work_timer_fn, even though the function the delayed work is going
Oliver Neukum 8d1d68
to run can be wildly different depending on what work was queued.  Enabling
Oliver Neukum 8d1d68
workqueue debugobjects doesn't help either because the delayed work isn't
Oliver Neukum 8d1d68
considered active until it is actually queued to run on a workqueue. If the
Oliver Neukum 8d1d68
work is freed while the timer is pending the work isn't considered active
Oliver Neukum 8d1d68
so there is no information from workqueue debugobjects.
Oliver Neukum 8d1d68
Oliver Neukum 8d1d68
Special case delayed works in the timer debugobjects hint logic so that the
Oliver Neukum 8d1d68
delayed work function is returned instead of the delayed_work_timer_fn.
Oliver Neukum 8d1d68
This will help to understand which delayed work was pending that got
Oliver Neukum 8d1d68
freed.
Oliver Neukum 8d1d68
Oliver Neukum 8d1d68
Apply the same treatment for kthread_delayed_work because it follows the
Oliver Neukum 8d1d68
same pattern.
Oliver Neukum 8d1d68
Oliver Neukum 8d1d68
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Oliver Neukum 8d1d68
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Oliver Neukum 8d1d68
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Oliver Neukum 8d1d68
Link: https://lore.kernel.org/r/20220511201951.42408-1-swboyd@chromium.org
Oliver Neukum 8d1d68
Signed-off-by: Oliver Neukum <oneukum@suse.com>
Oliver Neukum 8d1d68
---
Oliver Neukum 8d1d68
 kernel/time/timer.c | 32 +++++++++++++++++++++++++++++++-
Oliver Neukum 8d1d68
 1 file changed, 31 insertions(+), 1 deletion(-)
Oliver Neukum 8d1d68
Oliver Neukum 8d1d68
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
Oliver Neukum 8d1d68
index ef082d43c307..a0666d948147 100644
Oliver Neukum 8d1d68
--- a/kernel/time/timer.c
Oliver Neukum 8d1d68
+++ b/kernel/time/timer.c
Oliver Neukum 8d1d68
@@ -638,9 +638,39 @@ static void internal_add_timer(struct timer_base *base, struct timer_list *timer
Oliver Neukum 8d1d68
 
Oliver Neukum 8d1d68
 static const struct debug_obj_descr timer_debug_descr;
Oliver Neukum 8d1d68
 
Oliver Neukum 8d1d68
+struct timer_hint {
Oliver Neukum 8d1d68
+	void	(*function)(struct timer_list *t);
Oliver Neukum 8d1d68
+	long	offset;
Oliver Neukum 8d1d68
+};
Oliver Neukum 8d1d68
+
Oliver Neukum 8d1d68
+#define TIMER_HINT(fn, container, timr, hintfn)			\
Oliver Neukum 8d1d68
+	{							\
Oliver Neukum 8d1d68
+		.function = fn,					\
Oliver Neukum 8d1d68
+		.offset	  = offsetof(container, hintfn) -	\
Oliver Neukum 8d1d68
+			    offsetof(container, timr)		\
Oliver Neukum 8d1d68
+	}
Oliver Neukum 8d1d68
+
Oliver Neukum 8d1d68
+static const struct timer_hint timer_hints[] = {
Oliver Neukum 8d1d68
+	TIMER_HINT(delayed_work_timer_fn,
Oliver Neukum 8d1d68
+		   struct delayed_work, timer, work.func),
Oliver Neukum 8d1d68
+	TIMER_HINT(kthread_delayed_work_timer_fn,
Oliver Neukum 8d1d68
+		   struct kthread_delayed_work, timer, work.func),
Oliver Neukum 8d1d68
+};
Oliver Neukum 8d1d68
+
Oliver Neukum 8d1d68
 static void *timer_debug_hint(void *addr)
Oliver Neukum 8d1d68
 {
Oliver Neukum 8d1d68
-	return ((struct timer_list *) addr)->function;
Oliver Neukum 8d1d68
+	struct timer_list *timer = addr;
Oliver Neukum 8d1d68
+	int i;
Oliver Neukum 8d1d68
+
Oliver Neukum 8d1d68
+	for (i = 0; i < ARRAY_SIZE(timer_hints); i++) {
Oliver Neukum 8d1d68
+		if (timer_hints[i].function == timer->function) {
Oliver Neukum 8d1d68
+			void (**fn)(void) = addr + timer_hints[i].offset;
Oliver Neukum 8d1d68
+
Oliver Neukum 8d1d68
+			return *fn;
Oliver Neukum 8d1d68
+		}
Oliver Neukum 8d1d68
+	}
Oliver Neukum 8d1d68
+
Oliver Neukum 8d1d68
+	return timer->function;
Oliver Neukum 8d1d68
 }
Oliver Neukum 8d1d68
 
Oliver Neukum 8d1d68
 static bool timer_is_static_object(void *addr)
Oliver Neukum 8d1d68
-- 
Oliver Neukum 8d1d68
2.39.0
Oliver Neukum 8d1d68