watchdog: make nowayout sysfs file writable
authorRasmus Villemoes <linux@rasmusvillemoes.dk>
Tue, 5 Nov 2019 20:51:18 +0000 (21:51 +0100)
committerWim Van Sebroeck <wim@linux-watchdog.org>
Mon, 18 Nov 2019 18:53:43 +0000 (19:53 +0100)
It can be useful to delay setting the nowayout feature for a watchdog
device. Moreover, not every driver (notably gpio_wdt) implements a
nowayout module parameter/otherwise respects CONFIG_WATCHDOG_NOWAYOUT,
and modifying those drivers carries a risk of causing a regression for
someone who has two watchdog devices, sets CONFIG_WATCHDOG_NOWAYOUT
and somehow relies on the gpio_wdt driver being ignorant of
that (i.e., allowing one to gracefully close a gpio_wdt but not the
other watchdog in the system).

So instead, simply make the nowayout sysfs file writable. Obviously,
setting nowayout is a one-way street.

Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20191105205118.11359-1-linux@rasmusvillemoes.dk
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
Documentation/ABI/testing/sysfs-class-watchdog
drivers/watchdog/watchdog_dev.c

index 675f9b5..9860a8b 100644 (file)
@@ -17,8 +17,13 @@ What:                /sys/class/watchdog/watchdogn/nowayout
 Date:          August 2015
 Contact:       Wim Van Sebroeck <wim@iguana.be>
 Description:
-               It is a read only file. While reading, it gives '1' if that
-               device supports nowayout feature else, it gives '0'.
+               It is a read/write file. While reading, it gives '1'
+               if the device has the nowayout feature set, otherwise
+               it gives '0'. Writing a '1' to the file enables the
+               nowayout feature. Once set, the nowayout feature
+               cannot be disabled, so writing a '0' either has no
+               effect (if the feature was already disabled) or
+               results in a permission error.
 
 What:          /sys/class/watchdog/watchdogn/state
 Date:          August 2015
index 62483a9..4feecd1 100644 (file)
@@ -452,7 +452,26 @@ static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr,
 
        return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status));
 }
-static DEVICE_ATTR_RO(nowayout);
+
+static ssize_t nowayout_store(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+       struct watchdog_device *wdd = dev_get_drvdata(dev);
+       unsigned int value;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &value);
+       if (ret)
+               return ret;
+       if (value > 1)
+               return -EINVAL;
+       /* nowayout cannot be disabled once set */
+       if (test_bit(WDOG_NO_WAY_OUT, &wdd->status) && !value)
+               return -EPERM;
+       watchdog_set_nowayout(wdd, value);
+       return len;
+}
+static DEVICE_ATTR_RW(nowayout);
 
 static ssize_t status_show(struct device *dev, struct device_attribute *attr,
                                char *buf)