]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
wdctl: add --setpretimeout
authorKarel Zak <kzak@redhat.com>
Tue, 19 Oct 2021 07:47:44 +0000 (09:47 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 19 Oct 2021 07:47:44 +0000 (09:47 +0200)
Addresses: https://github.com/karelzak/util-linux/issues/1475
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/wdctl.8.adoc
sys-utils/wdctl.c

index 08a1eb82e572c02fbc5fd5c0d6932fcfc98e9ba9..a376e62595faacd66bf42071227ce8495b4959ab 100644 (file)
@@ -42,10 +42,17 @@ Define the output columns to use in table of watchdog flags. If no output arrang
 *-O*, *--oneline*::
 Print all wanted information on one line in key="value" output format.
 
+*-p*, *--setpretimeout* _seconds_::
+Set the watchdog pre-timeout in seconds. A watchdog pre-timeout is a
+notification generated by the watchdog before the watchdog reset might occur in
+the event the watchdog has not been serviced. This notification is handled by
+the kernel and can be configured to take an action using sysfs (e.g.
+/sys/class/watchdog/watchdog0/pretimeout_governor).
+
 *-r*, *--raw*::
 Use the raw output format.
 
-*-s*, *-settimeout* _seconds_::
+*-s*, *--settimeout* _seconds_::
 Set the watchdog timeout in seconds.
 
 *-T*, *--notimeouts*::
index 6b9affa0aa76da031d205461b15d25fd5a41de85..d9abea8addcfbecad3ea0241d231e5a5c866c322 100644 (file)
@@ -216,6 +216,7 @@ static void __attribute__((__noreturn__)) usage(void)
                " -n, --noheadings       don't print headings for flags table\n"
                " -O, --oneline          print all information on one line\n"
                " -o, --output <list>    output columns of the flags\n"
+               " -p, --setpretimeout <sec> set watchdog pre-timeout\n"
                " -r, --raw              use raw output format for flags table\n"
                " -T, --notimeouts       don't print watchdog timeouts\n"
                " -s, --settimeout <sec> set watchdog timeout\n"
@@ -334,19 +335,27 @@ done:
        scols_unref_table(table);
        return rc;
 }
+
+enum {
+       WDCTL_SET_TIMEOUT = (1 << 1),
+       WDCTL_SET_PRETIMEOUT = (1 << 2)
+};
+
 /*
  * Warning: successfully opened watchdog has to be properly closed with magic
  * close character otherwise the machine will be rebooted!
  *
  * Don't use err() or exit() here!
  */
-static int set_watchdog(struct wd_device *wd, int timeout)
+static int set_watchdog(struct wd_device *wd, int timeout, int pretimeout,
+                       unsigned int flags)
 {
        int fd;
        sigset_t sigs, oldsigs;
        int rc = 0;
 
        assert(wd->devpath);
+       assert(flags);
 
        sigemptyset(&oldsigs);
        sigfillset(&sigs);
@@ -377,11 +386,18 @@ static int set_watchdog(struct wd_device *wd, int timeout)
                 * the machine might end up rebooting. */
        }
 
-       if (ioctl(fd, WDIOC_SETTIMEOUT, &timeout) != 0) {
-               rc = errno;
+       if ((flags & WDCTL_SET_TIMEOUT) &&
+           ioctl(fd, WDIOC_SETTIMEOUT, &timeout) != 0) {
+               rc += errno;
                warn(_("cannot set timeout for %s"), wd->devpath);
        }
 
+       if ((flags & WDCTL_SET_PRETIMEOUT) &&
+           ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout) != 0) {
+               rc += errno;
+               warn(_("cannot set pretimeout for %s"), wd->devpath);
+       }
+
        if (close(fd))
                warn(_("write failed"));
        sigprocmask(SIG_SETMASK, &oldsigs, NULL);
@@ -599,8 +615,9 @@ int main(int argc, char *argv[])
        struct wd_device wd;
        struct wd_control ctl = { .hide_headings = 0 };
        int c, res = EXIT_SUCCESS, count = 0;
+       unsigned int wantset = 0;
        uint32_t wanted = 0;
-       int timeout = 0;
+       int timeout = 0, pretimeout = 0;
        const char *dflt_device = NULL;
 
        static const struct option long_opts[] = {
@@ -612,6 +629,7 @@ int main(int argc, char *argv[])
                { "noident",    no_argument,       NULL, 'I' },
                { "notimeouts", no_argument,       NULL, 'T' },
                { "settimeout", required_argument, NULL, 's' },
+               { "setpretimeout", required_argument, NULL, 'p' },
                { "output",     required_argument, NULL, 'o' },
                { "oneline",    no_argument,       NULL, 'O' },
                { "raw",        no_argument,       NULL, 'r' },
@@ -631,7 +649,7 @@ int main(int argc, char *argv[])
        close_stdout_atexit();
 
        while ((c = getopt_long(argc, argv,
-                               "d:f:hFnITo:s:OrVx", long_opts, NULL)) != -1) {
+                               "d:f:hFnITp:o:s:OrVx", long_opts, NULL)) != -1) {
 
                err_exclusive_options(c, long_opts, excl, excl_st);
 
@@ -645,6 +663,11 @@ int main(int argc, char *argv[])
                        break;
                case 's':
                        timeout = strtos32_or_err(optarg, _("invalid timeout argument"));
+                       wantset |= WDCTL_SET_TIMEOUT;
+                       break;
+               case 'p':
+                       pretimeout = strtos32_or_err(optarg, _("invalid pretimeout argument"));
+                       wantset |= WDCTL_SET_PRETIMEOUT;
                        break;
                case 'f':
                        if (string_to_bitmask(optarg, (unsigned long *) &wanted, name2bit) != 0)
@@ -707,8 +730,8 @@ int main(int argc, char *argv[])
                        fputc('\n', stdout);
                count++;
 
-               if (timeout) {
-                       rc = set_watchdog(&wd, timeout);
+               if (wantset) {
+                       rc = set_watchdog(&wd, timeout, pretimeout, wantset);
                        if (rc) {
                                res = EXIT_FAILURE;
                        }