From 6de3def84cf48b68b79d0cc4b5e1d2696e0484d1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 13 Oct 2023 16:44:51 +0200 Subject: [PATCH] wdctl: use only sysfs if sufficient MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Also avoid opening device if nowayout is set. Opening the device node starts the watchdog. With 'nowayout' enabled unstoppably. Also the device node can only be opened once at the same time which can be problematic. Prefer to retrieve the information via sysfs which does not have such problems. Fixes #2543 Signed-off-by: Thomas Weißschuh --- sys-utils/wdctl.c | 50 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/sys-utils/wdctl.c b/sys-utils/wdctl.c index a5fdeaeb22..767f061fea 100644 --- a/sys-utils/wdctl.c +++ b/sys-utils/wdctl.c @@ -125,7 +125,12 @@ struct wd_device { struct watchdog_info ident; - unsigned int has_timeout : 1, + unsigned int has_identity : 1, + has_fw_version : 1, + has_options : 1, + has_status : 1, + has_bootstatus : 1, + has_timeout : 1, has_timeleft : 1, has_pretimeout : 1, has_nowayout : 1, @@ -549,13 +554,16 @@ static int read_watchdog_from_sysfs(struct wd_device *wd) if (!sys) return 1; - ul_path_read_buffer(sys, (char *) wd->ident.identity, sizeof(wd->ident.identity), "identity"); - ul_path_read_u32(sys, &wd->ident.firmware_version, "fw_version"); - ul_path_scanf(sys, "options", "%x", &wd->ident.options); - - ul_path_scanf(sys, "status", "%x", &wd->status); - ul_path_read_u32(sys, &wd->bstatus, "bootstatus"); - + if (ul_path_read_buffer(sys, (char *) wd->ident.identity, sizeof(wd->ident.identity), "identity") >= 0) + wd->has_identity = 1; + if (ul_path_read_u32(sys, &wd->ident.firmware_version, "fw_version") == 0) + wd->has_fw_version = 1; + if (ul_path_scanf(sys, "options", "%x", &wd->ident.options) == 1) + wd->has_options = 1; + if (ul_path_scanf(sys, "status", "%x", &wd->status) == 1) + wd->has_status = 1; + if (ul_path_read_u32(sys, &wd->bstatus, "bootstatus") == 0) + wd->has_bootstatus = 1; if (ul_path_read_s32(sys, &wd->nowayout, "nowayout") == 0) wd->has_nowayout = 1; if (ul_path_read_s32(sys, &wd->timeout, "timeout") == 0) @@ -598,12 +606,32 @@ static int read_governors(struct wd_device *wd) return 0; } +static bool should_read_from_device(struct wd_device *wd) +{ + if (!wd->has_nowayout) + return false; + + if (wd->nowayout) + return false; + + return !wd->has_identity || + !wd->has_fw_version || + !wd->has_options || + !wd->has_status || + !wd->has_bootstatus || + !wd->has_timeout || + !wd->has_timeleft; + // pretimeout attribute may be hidden in sysfs +} + static int read_watchdog(struct wd_device *wd) { - int rc = read_watchdog_from_device(wd); + int rc; + + rc = read_watchdog_from_sysfs(wd); - if (rc == -EBUSY || rc == -EACCES || rc == -EPERM) - rc = read_watchdog_from_sysfs(wd); + if (rc && should_read_from_device(wd)) + rc = read_watchdog_from_device(wd); if (rc) { warn(_("cannot read information about %s"), wd->devpath); -- 2.47.2