[PATCH 24/28] hazptr: Add runtime sysfs controls for stall detector
From: Kunwu Chan
Date: Wed Nov 04 2026 - 12:08:50 EST
Add writable sysfs attributes that let the administrator adjust
stall-detector behaviour at runtime.
Suggested-by: Paul E. McKenney <paulmck@xxxxxxxxxx>
Signed-off-by: Kunwu Chan <kunwu.chan@xxxxxxxxx>
---
kernel/hazptr.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/kernel/hazptr.c b/kernel/hazptr.c
index 7d4273a44183..66954251c332 100644
--- a/kernel/hazptr.c
+++ b/kernel/hazptr.c
@@ -423,6 +423,10 @@ static struct hazptr_scan_state hazptr_scan;
/* Sysfs counters, cf. RCU's rcu_stall_count. */
static atomic_t hazptr_stall_count = ATOMIC_INIT(0);
+#ifdef CONFIG_HAZPTR_STALL_DETECTOR
+static unsigned long hazptr_stall_timeout_ms = CONFIG_HAZPTR_STALL_TIMEOUT;
+static int hazptr_stall_suppress;
+#endif
static atomic_t hazptr_drain_count = ATOMIC_INIT(0);
#ifdef CONFIG_HAZPTR_DRAIN_ASSIST
@@ -1115,8 +1119,12 @@ static void hazptr_waiter_stall_report(struct hazptr_waiter *w)
static void hazptr_waiter_stall_check(struct hazptr_waiter *w)
{
unsigned long now = jiffies;
- unsigned long timeout = msecs_to_jiffies(CONFIG_HAZPTR_STALL_TIMEOUT);
+ unsigned long timeout_ms = READ_ONCE(hazptr_stall_timeout_ms);
+ unsigned long timeout;
unsigned long deadline;
+ if (READ_ONCE(hazptr_stall_suppress) || !timeout_ms)
+ return;
+ timeout = msecs_to_jiffies(timeout_ms);
w->cycles++;
deadline = w->reports ? w->last_report + 2 * timeout
: w->enqueue_jiffies + timeout;
@@ -1275,6 +1283,46 @@ void __init hazptr_init(void)
}
#ifdef CONFIG_SYSFS
+#ifdef CONFIG_HAZPTR_STALL_DETECTOR
+static ssize_t hazptr_stall_timeout_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *page)
+{
+ return sysfs_emit(page, "%lu\n", READ_ONCE(hazptr_stall_timeout_ms));
+}
+static ssize_t hazptr_stall_timeout_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long val;
+ int ret;
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+ if (val > 3600000)
+ return -EINVAL;
+ WRITE_ONCE(hazptr_stall_timeout_ms, val);
+ return count;
+}
+static ssize_t hazptr_stall_suppress_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *page)
+{
+ return sysfs_emit(page, "%d\n", READ_ONCE(hazptr_stall_suppress));
+}
+static ssize_t hazptr_stall_suppress_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val, ret;
+ ret = kstrtoint(buf, 0, &val);
+ if (ret)
+ return ret;
+ WRITE_ONCE(hazptr_stall_suppress, !!val);
+ return count;
+}
+#endif /* CONFIG_HAZPTR_STALL_DETECTOR */
+
static ssize_t hazptr_stall_count_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *page)
@@ -1291,12 +1339,24 @@ static ssize_t hazptr_drain_count_show(struct kobject *kobj,
static struct kobj_attribute hazptr_drain_count_attr =
__ATTR_RO(hazptr_drain_count);
+#ifdef CONFIG_HAZPTR_STALL_DETECTOR
+static struct kobj_attribute hazptr_stall_timeout_attr =
+ __ATTR(hazptr_stall_timeout_ms, 0644,
+ hazptr_stall_timeout_show, hazptr_stall_timeout_store);
+static struct kobj_attribute hazptr_stall_suppress_attr =
+ __ATTR(hazptr_stall_suppress, 0644,
+ hazptr_stall_suppress_show, hazptr_stall_suppress_store);
+#endif
static struct kobj_attribute hazptr_stall_count_attr =
__ATTR_RO(hazptr_stall_count);
static struct attribute *hazptr_sysfs_attrs[] = {
&hazptr_stall_count_attr.attr,
&hazptr_drain_count_attr.attr,
+#ifdef CONFIG_HAZPTR_STALL_DETECTOR
+ &hazptr_stall_timeout_attr.attr,
+ &hazptr_stall_suppress_attr.attr,
+#endif
NULL,
};
--
2.43.0