Commit Graph
79 Commits
Author SHA1 Message Date
Daan De Meyer d9ccf6b349 path-util: Reduce transitive includes 2025-05-07 22:04:46 +09:00
Daan De Meyer 1cf40697e3 tree-wide: Sort includes
This was done by running a locally built clang-format with
https://github.com/llvm/llvm-project/pull/137617 and
https://github.com/llvm/llvm-project/pull/137840 applied on all .c
and .h files.
2025-04-30 09:30:51 +02:00
Daan De Meyer 40d60725ec basic: Move ratelimit logging functions to ratelimit.h
The ratelimit logging functions are only useful in a few scenarios
so let's move them to ratelimit.h instead of keeping them in the
generic log.h
2025-04-18 10:11:40 +02:00
Yu Watanabe 072ebe3ece watchdog: fix typo
Follow-up for ab596e4cde.
2025-03-31 21:27:00 +09:00
Zbigniew Jędrzejewski-Szmek ab596e4cde shared/watchdog: give up after a few failed pings
Closes https://github.com/systemd/systemd/issues/35405. Apparently some
watchdog devices can be opened, but then the pings start failing after some
time. Since the timestamp of the last successful ping is not updated, we try to
ping again immediately, causing a busy loop and excessive logging.

After trying a few different approaches to fit this into the existing framework
without changing the logic too much, I settled on an approach with a second
timestamp. In particular, the timestamp of the last successful ping is public,
exposed as WatchdogLastPingTimestamp over dbus. It'd be wrong to redefine this
to mean the last ping *attempt*. So we need a second timestamp in some form.

Also, if we give up on pinging, we probably should attempt to disarm the
watchdog. It's possible that the pinging fails, but the watchdog would still
fire. I don't think we want that, since it seems that our internal loop is
working, it's just the watchdog that is broken.

Structured message with SD_MESSAGE_WATCHDOG_PING_FAILED is logged if we fail
to ping.

I tested this by attaching gdb to pid 1 and calling close(watchdog_fd).
We get a bunch of warning messages and then an attempt to close the watchdog:
Mar 21 15:46:17 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:20 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:23 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:26 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:29 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:32 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:35 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:37 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:40 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:43 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:46 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:49 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:52 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:55 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0: Bad file descriptor
Mar 21 15:46:58 fedora systemd[1]: Failed to ping hardware watchdog /dev/watchdog0, closing watchdog after 15 attempts: Bad file descriptor
Mar 21 15:46:58 fedora systemd[1]: Failed to disable hardware watchdog, ignoring: Bad file descriptor
Mar 21 15:46:58 fedora systemd[1]: Failed to disarm watchdog timer, ignoring: Bad file descriptor
2025-03-24 10:45:49 +01:00
Zbigniew Jędrzejewski-Szmek 236ac39b65 shared/watchdog: add MESSAGE_IDs to logs about watchdog opening
One ID for the success case, with WATCHDOG_DEVICE= showing the device,
and one ID for the failure case, with WATCHDOG_DEVICE= if configured,
and ERRNO= set automatically.
2025-03-21 15:55:50 +01:00
Zbigniew Jędrzejewski-Szmek b27c9279f6 shared/watchdog: ratelimit the number of attempts to open watchdog
We need to retry the open attempts for the watchdog, because the device becomes
available asynchronously.

The watchdog is opened in two places:

- in pid1 in the main loop. The loop has a ratelimit, but during a boot we
  iterate in it fairly quickly. On my test VM with 'iTCO_wdt', version 2:

    $ journalctl -b --grep 'Failed to open any watchdog' | wc -l
    3398

  After the device has been processed by udev, it is initialized successfully.

- in shutdown. In that case, we most likely don't need to try more than once,
  because we mostly care about the case where the watchdog device was present
  and configured previously. But in principle it is possible that we might
  attempt shutdown while the machine was initializing, so we don't want to
  disable retries. Nevertheless, watchdog_ping() is called from a loop that
  might be fairly tight, so we could end up trying to reopen the device fairly
  often. This probably doesn't matter *too* much, but it's still ugly to try to
  open the device without any ratelimit.

Usually the watchdog timeout would be set to something like 30 s or a few
minutes. OTOH, on my VM, the device becomes avaiable at 4.35 s after boot. So
let's use 5 s or half the watchdog timeout, whatever is smaller, as the
interval.
2025-03-21 15:55:50 +01:00
Zbigniew Jędrzejewski-Szmek 2c6397d1c2 pid1: log if we failed to find a watchdog device
I think we need to log at some point if the user configured a watchdog device,
but no devices were found. We can't log ENOENT immediately, because the device
may likely appear during boot. So wait until the end of the initial transaction
and log then.
2025-03-21 11:38:43 +01:00
Zbigniew Jędrzejewski-Szmek 0b291130e8 shared/watchdog: raise log levels for watchdog errors
If we failed to open the watchdog device for any reason, we'd only log at debug
level. This seems iffy: if the user configured a timeout for the watchdog, we
should report when we can't set it up. ENOENT is still logged at debug level
only, since it's somewhat expected to have a watchdog timeout set up, even for
systems which don't have a watchdog, or the device might appear later.

If the device doesn't support WDIOC_GETSUPPORT, still log that we opened a
device.

No change in behaviour, except for the log level threshold. As a side effect,
the reason why we failed to open the device is now stored in watchdog_fd
(previously it was -1 always), but this isn't used for anything.
2025-03-21 11:30:26 +01:00
Zbigniew Jędrzejewski-Szmek ab37e9cdb2 core/watchdog: initialize variables only if they'll be used
This is not a hot path, but let's move the variables to the
minimal scope in which they are needed.

Also, all functions which call watchdog_open() check for fd < 0 first,
so change the conditional return into an assert.
2025-03-21 11:30:26 +01:00
Zbigniew Jędrzejewski-Szmek bfd5a0687f various: move const ptr indicator to return value 2024-06-19 16:28:28 +02:00
Lennart Poettering bbd3832e6b watchdog: reset last ping timestamp when opening watchdog
When we open a watchdog fresh we have never pinged it, hence reset the
ping timestamp explicitly, so that it is not only reset the first time
we open the device, but all times.
2024-05-29 17:42:02 +02:00
Lennart Poettering e7f0053787 watchdog: normalize how we name watchdog related calls
Let's put the "watchdog" always as prefix in the name, and not as suffix
or the middle. Just for reasons of naming hygiene
2024-05-29 17:42:02 +02:00
Yu Watanabe 4e494e6aac tree-wise: several cleanups for logging
- drop unnecessary SYNTHETIC_ERRNO() when the logger does not propagate
  error code,
- drop unnecessary '%m' in error message when the error code is
  specified with SYNTHETIC_ERRNO(),
- add missing full stop at the end of log message,
- use RET_GATHER(),
- add missing ", ignoring.",
- upeercase the first letter, etc., etc...
2024-05-01 04:41:06 +09:00
Lennart Poettering 99a1ef8c9c watchdog: clarify that we set the *watchdog* timeout
This makes sure we mention the word "watchdog" in every log message
related to the watchdog.

Also, this uses the expression "hardware timeout" when referring to the
primary timeout of the watchdog, as opposed to the "pretimeout".

(Not ideal wording I know, but it's preexisting to some point, I just
continued it. I think it's OK though, in particular to underline the
difference to the software watchdog logic we implement via WATCHDOG= in
sd_notify().)

Fixes: #31662
2024-04-04 17:53:38 +02:00
Holger Assmann f681046ede watchdog: ensure configured timeout is used instead of USEC_INFINITY
In some rare cases, a watchdog driver might neither be able to change
the watchdog timeout value, nor read it from the hardware at runtime.

With an otherwise functional watchdog setup, this constellation worked
until systemd v249. Since then, systemd ends up ignoring the timeout
defined by the system.conf and rather uses USEC_INFINITY. Consequently,
the watchdog is not pinged anymore and eventually resets the system.

We therefore want to ensure that the system keeps running with the
originally configured timeout.
2024-01-10 19:14:38 +00:00
Lennart Poettering f81048f8f5 watchdog: always disarm watchdog properly before closing it
If we change the watchdog device we should disarm the old one first.

Similar, if we open the watchdog, but then fail setting it up, disarm it
before closing it again.
2023-05-15 21:55:19 +08:00
Zbigniew Jędrzejewski-Szmek 254d1313ae tree-wide: use -EBADF for fd initialization
-1 was used everywhere, but -EBADF or -EBADFD started being used in various
places. Let's make things consistent in the new style.

Note that there are two candidates:
EBADF 9 Bad file descriptor
EBADFD 77 File descriptor in bad state

Since we're initializating the fd, we're just assigning a value that means
"no fd yet", so it's just a bad file descriptor, and the first errno fits
better. If instead we had a valid file descriptor that became invalid because
of some operation or state change, the other errno would fit better.

In some places, initialization is dropped if unnecessary.
2022-12-19 15:00:57 +01:00
Yu Watanabe ab8e6464b5 Merge pull request #24664 from yuwata/watchdog
watchdog: open /dev/watchdog0 only if it exists
2022-09-17 00:18:53 +09:00
Yu Watanabe a6b7ebaafa watchdog: use /dev/watchdog0 only if it exists
Fixes #24661.
2022-09-16 22:34:37 +09:00
Yu Watanabe 3e911a0d0e pid1: drop redundant DBus properties
Follow-up for 10f3f4ed01.

We already have RuntimeWatchdogUSec or friends. Let's not introduce
redundant properties.

Also, drop the const qualifier for WatchdogLastPingTimestamp, as they
are actually not constant.
2022-09-16 21:53:28 +09:00
Yu Watanabe 9341f41801 watchdog: explicitly initialize global variable
No functional change, as they were implicitly initialized with zero.
2022-09-16 21:48:39 +09:00
Yu Watanabe 10f3f4ed01 pid1: introduce dbus properties WatchdogDevice and friends
Closes #24665.
2022-09-14 13:13:59 +01:00
Jan Janssen 3a4e4fface tree-wide: Use devnum helpers in a few more places 2022-09-01 00:55:37 +09:00
Jan Janssen c0f86d66f3 tree-wide: Use correct format specifiers
gcc will complain about all these with -Wformat-signedness.
2022-08-30 12:03:28 +02:00
Lennart Poettering ba4e0427e9 time-util: assume CLOCK_BOOTTIME always exists
Let's raise our supported baseline a bit: CLOCK_BOOTTIME started to work
with timerfd in kernel 3.15 (i.e. back in 2014), let's require support
for it now.

This will raise our baseline only modestly from 3.13 → 3.15.
2022-03-28 16:55:41 +02:00
Yu Watanabe a17e54783a tree-wide: fix typo 2022-03-07 15:32:22 +09:00
Luca Boccassi aff3a9e1fa watchdog: add setting to configure pretimeout governor 2022-02-22 17:19:54 +00:00
Curtis Klein 56b96db700 watchdog: check pretimeout governor
Check and log the default pretimeout governor configured in the kernel.
The pretimeout will not work unless at least one governor is available
and configured. This requires loading a kernel module manually.
2022-02-22 17:19:54 +00:00
Curtis Klein 5717062e93 watchdog: Add watchdog pretimeout support
Add support for managing and configuring watchdog pretimeout values if
the watchdog hardware supports it. The ping interval is adjusted to
account for a pretimeout so that it will still ping at half the timeout
interval before a pretimeout event would be triggered. By default the
pretimeout defaults to 0s or disabled.

The RuntimeWatchdogPreSec config option is added to allow the pretimeout
to be specified (similar to RuntimeWatchdogSec). The
RuntimeWatchdogPreUSec dbus property is added to override the pretimeout
value at runtime (similar to RuntimeWatchdogUSec). Setting the
pretimeout to 0s will disable the pretimeout.
2022-02-22 17:19:54 +00:00
Curtis Klein d6463a399d watchdog: saturate to kernel's max watchdog timeout
Since version 4.5, the max possible timeout is UINT_MAX / 1000 since it
does calculations in milliseconds. A small helper function is added to
make this conversion and saturation and will be used more in the next
commit.

Also document the usage of signed integers by the kernel userspace API.
2022-02-08 14:43:12 +01:00
Lennart Poettering 8eb0c7917d watchdog: work around Coverity confusion
Coverity (and I, initially) get really confused about "fn"'s validity
here. it doesn't grok that free_and_strdup() is actually a NOP in case
the string isn't changed, and assumes it always invalidates the
specified buffer, which it doesn't do though.

Follow-up for: f4b1a6b641
2022-02-07 20:48:36 +00:00
Michael Olbrich f4b1a6b641 watchdog: fix watchdog_set_device() when the default watchdog device is used
If watchdog_set_device() is not called before open_watchdog() then
'watchdog_device' remains 'NULL' while the device is open.

As a result, the "same device" check in watchdog_set_device() does not work
correctly: If no device is specified (e.g. from watchdog_free_device())
then the current fd is not closed.

Fix this by setting 'watchdog_device' to the correct device during
open_watchdog()
2022-02-04 12:26:58 +01:00
Yu Watanabe b144177240 watchdog: rebreak comments 2022-01-07 09:31:57 +01:00
Franck Bui 8ce08c8e97 watchdog: shorten watchdog_set_device() 2022-01-07 09:28:55 +01:00
Yu Watanabe 769020c092 watchdog: adjust comment 2022-01-05 20:13:59 +09:00
Lennart Poettering d9752ca196 watchdog: fix fd validity check 2021-10-18 11:27:39 +02:00
Lennart Poettering ef52fa5bd1 watchdog: drop unnecessary variable 2021-10-18 11:27:39 +02:00
Lennart Poettering 59bcac0b1a watchdog: always prefer /dev/watchdog0 over /dev/watchdog 2021-10-18 11:27:39 +02:00
Lennart Poettering a73b7b1b0e watchdog: fix error code handling 2021-10-18 11:27:39 +02:00
Franck Bui 0ffdfe7d68 watchdog: handle timeout programming errors more safely
If an error happened while the timeout value was being programmed, the error
was ignored and the watchdog module used the new timeout value whereas the
watchdog device was left with the previous one.

Now in cases of error, the device is now disabled and closed if it wasn't
opened already otherwise the previous timeout value is kept so the device is
still pinged at correct intervals.
2021-10-13 08:58:36 +02:00
Franck Bui f16890f8d2 watchdog: passing 0 to watchdog_setup now closes the watchdog
Passing 0 meant "disable the watchdog although still kept it opened". However
this case didn't seem to be useful especially since PID1 closes the device if
it is passed the nul timeout.

Hence let's change the meaning of watchdog_setup(0) to match PID1's behavior
which allows to simplify the code a bit.

Hence this patch also drops enable_watchdog().
2021-10-13 08:58:30 +02:00
Franck Bui c1a08a76ab watchdog: pass USEC_INFINITY to watchdog_setup() to reuse the programmed timeout value
This patch changes the meaning of USEC_INFINITY value for the watchdog
module.

Previously passing this value was a NOP. It now has a special meaning: it
requests the watchdog module to read the programmed timeout value and reuse it
for pinging the device.

This is mostly useful when the watchdog is started by the firmware and there's
no way to reconfigure the timeout with a different value
afterwards. "RuntimeWatchdogSec=infinity" in system.conf can now be used rather
than putting an arbitrary value that PID1 will fail to set (even if it still
felt back to the programmed timeout).

Please note that "infinity" is not supposed to restore the default value of the
firmware. If the value is changed after booting then "infinity" would simply
reuse the current programmed value. IOW it's a NOP unless the watchdog was
previously closed and in that case it will be reopened and the last programmed
value reused.
2021-10-13 08:51:15 +02:00
Franck Bui ef1d5f3c5c watchdog: configuring a timeout value might not be supported by the HW
In that case we should hanlde this case more gracefully by reusing the
programmed value.

Fixes: #20683
2021-10-13 08:51:13 +02:00
Franck Bui fcbf2c64f5 watchdog: minor optimization in watchdog_setup() 2021-10-13 08:50:08 +02:00
Franck Bui 85e5613cf3 watchdog: cleanup: create an helper for each ioctl
No functional changes.
2021-10-13 08:50:04 +02:00
Lennart Poettering 84b5e291e2 watchdog: add ", ignoring" to log messages about errors we ignore
As per coding style. Also downgrade relevant log messages to
LOG_WARNING.
2021-09-15 16:01:02 +02:00
Lennart Poettering a4588af942 watchdog: pass right error code to log function so that %m works 2021-09-15 16:00:20 +02:00
Franck Bui 10fd2b1180 watchdog: use MIN() in update_timeout()
Also the previous expression was probably wrong as "(int) t >= INT_MAX" is
likely to always evaluate to false.
2021-09-15 12:14:53 +02:00
Franck Bui bcc3a1830e watchdog: constify watchdog_set_device() parameter 2021-09-15 12:14:53 +02:00