[PATCH v2 1/1] kernel/watchdog: always restore watchdog_softlockup(,hardlockup)_user_enabled after proc show

From: Tio Zhang
Date: Fri Sep 06 2024 - 05:48:12 EST


Otherwise when watchdog_enabled becomes 0,
watchdog_softlockup(,hardlockup)_user_enabled will changes to 0 after
proc show.

Steps to reproduce:

step 1:
# cat /proc/sys/kernel/*watchdog
1
1
1

| name | value
|----------------------------------|--------------------------
| watchdog_enabled | 1
|----------------------------------|--------------------------
| watchdog_hardlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_softlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_user_enabled | 1
|----------------------------------|--------------------------

step 2:
# echo 0 > /proc/sys/kernel/watchdog

| name | value
|----------------------------------|--------------------------
| watchdog_enabled | 0
|----------------------------------|--------------------------
| watchdog_hardlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_softlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_user_enabled | 0
|----------------------------------|--------------------------

step 3:
# cat /proc/sys/kernel/*watchdog
0
0
0

| name | value
|----------------------------------|--------------------------
| watchdog_enabled | 0
|----------------------------------|--------------------------
| watchdog_hardlockup_user_enabled | 0
|----------------------------------|--------------------------
| watchdog_softlockup_user_enabled | 0
|----------------------------------|--------------------------
| watchdog_user_enabled | 0
|----------------------------------|--------------------------

step 4:
# echo 1 > /proc/sys/kernel/watchdog

| name | value
|----------------------------------|--------------------------
| watchdog_enabled | 0
|----------------------------------|--------------------------
| watchdog_hardlockup_user_enabled | 0
|----------------------------------|--------------------------
| watchdog_softlockup_user_enabled | 0
|----------------------------------|--------------------------
| watchdog_user_enabled | 0
|----------------------------------|--------------------------

step 5:
# cat /proc/sys/kernel/*watchdog
0
0
0

If we dont do "step 3", do "step 4" right after "step 2", it will be

| name | value
|----------------------------------|--------------------------
| watchdog_enabled | 1
|----------------------------------|--------------------------
| watchdog_hardlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_softlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_user_enabled | 1
|----------------------------------|--------------------------

then everything works correctly.

So this patch fix "step 3"'s value into

| name | value
|----------------------------------|--------------------------
| watchdog_enabled | 0
|----------------------------------|--------------------------
| watchdog_hardlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_softlockup_user_enabled | 1
|----------------------------------|--------------------------
| watchdog_user_enabled | 0
|----------------------------------|--------------------------

And still print 0 as before.

Signed-off-by: Tio Zhang <tiozhang@xxxxxxxxxxxxxx>
---
kernel/watchdog.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 51915b44ac73..ade69b2319f6 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -990,6 +990,7 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,

mutex_lock(&watchdog_mutex);

+ old = *param;
if (!write) {
/*
* On read synchronize the userspace interface. This is a
@@ -997,8 +998,8 @@ static int proc_watchdog_common(int which, struct ctl_table *table, int write,
*/
*param = (watchdog_enabled & which) != 0;
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ *param = old;
} else {
- old = READ_ONCE(*param);
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (!err && old != READ_ONCE(*param))
proc_watchdog_update();
--
2.17.1