Re: [PATCH v2 1/3] rust: watchdog: add watchdog device abstraction

[email protected] Thu, 23 Jul 2026 16:30:48 +0000
Newsgroups org.kernel.vger.linux-watchdog
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 5 potential issue(=
s) to consider:
- [High] Safe `Device::set_timeout` and `Device::timeout` cause data races =
(Undefined Behavior).
- [High] Missing `set_pretimeout` method in `Device`.
- [High] Missing commonly required driver fields (`bootstatus` and `min_hw_=
heartbeat_ms`) in `Options`.
- [Low] Missing `#[inline]` annotations on small abstraction methods.
- [Low] Imports do not follow the kernel vertical import style.
--

--- Patch [1]: [PATCH v2 1/3] rust: watchdog: add watchdog device abstracti=
on ---
commit a2fbd8297d0a9de19e082cbcf7ecd7a0e4b836b1
Author: Artem Lytkin <[email protected]>
Subject: rust: watchdog: add watchdog device abstraction

This commit adds Rust abstractions for the Linux watchdog subsystem, enabli=
ng
watchdog drivers to be written in Rust. It introduces wrappers for the
watchdog device, identity info, and options, along with a trait for driver
operations and a registration mechanism.

> diff --git a/rust/kernel/watchdog.rs b/rust/kernel/watchdog.rs
> new file mode 100644
> index 0000000000000..155eecc679238
> --- /dev/null
> +++ b/rust/kernel/watchdog.rs
> @@ -0,0 +1,522 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Watchdog device support.
> +//!
> +//! C headers: [`include/linux/watchdog.h`](srctree/include/linux/watchd=
og.h).
> +
> +use crate::{bindings, device, error::*, prelude::*, types::Opaque};

[Severity: Low]
This isn't a bug, but should the imports here follow the kernel vertical
import style as documented in the general coding guidelines?

> +use core::marker::PhantomData;
> +

[ ... ]

> +impl Device {
> +    /// Creates a new [`Device`] reference from a raw pointer.
> +    ///
> +    /// # Safety
> +    ///
> +    /// - `ptr` must point at a valid `watchdog_device`.
> +    /// - The returned reference must not outlive the callback invocatio=
n.
> +    unsafe fn from_raw<'a>(ptr: *mut bindings::watchdog_device) -> &'a S=
elf {

[Severity: Low]
This isn't a bug, but should small or forwarding functions in abstractions,
such as from_raw(), as_raw(), and the various getter/setter methods below,
be annotated with #[inline] according to the Rust subsystem guidelines?

> +        // CAST: `Self` is a `repr(transparent)` wrapper around
> +        // `bindings::watchdog_device`.
> +        let ptr =3D ptr.cast::<Self>();
> +        // SAFETY: By the function requirements the pointer is valid.
> +        unsafe { &*ptr }
> +    }
> +
> +    /// Returns a raw pointer to the underlying `watchdog_device`.
> +    fn as_raw(&self) -> *mut bindings::watchdog_device {
> +        self.0.get()
> +    }
> +
> +    /// Returns the current timeout in seconds.
> +    pub fn timeout(&self) -> u32 {
> +        // SAFETY: The struct invariant ensures the pointer is valid. The
> +        // read of this `unsigned int` field mirrors how the C core and C
> +        // drivers access it without synchronisation.
> +        unsafe { (*self.as_raw()).timeout }
> +    }
> +
> +    /// Sets the current timeout in seconds.
> +    pub fn set_timeout(&self, timeout: u32) {
> +        // SAFETY: The struct invariant ensures the pointer is valid. The
> +        // field lives in an `Opaque`, so writing through a shared refer=
ence
> +        // is allowed; the C core accesses this field the same way.
> +        unsafe { (*self.as_raw()).timeout =3D timeout };
> +    }

[Severity: High]
Since the commit message notes that callbacks can run concurrently without
holding a lock, does exposing these safe read and write methods cause a data
race when accessed from multiple threads?

In Rust, unsynchronized concurrent access where at least one is a write
constitutes undefined behavior. Should these methods use volatile or atomic
accesses to mirror READ_ONCE/WRITE_ONCE, or require caller synchronization?

> +
> +    /// Returns the current pretimeout in seconds.
> +    pub fn pretimeout(&self) -> u32 {
> +        // SAFETY: See `timeout`.
> +        unsafe { (*self.as_raw()).pretimeout }
> +    }

[Severity: High]
If a driver provides a set_pretimeout callback, the C watchdog core expects
the driver to update the internal wdd->pretimeout field upon success.

Since the Device abstraction only provides a getter for pretimeout, how can=
 a
Rust driver correctly update this core state without a set_pretimeout() met=
hod?

> +
> +    /// Returns the minimum timeout in seconds.
> +    pub fn min_timeout(&self) -> u32 {

[ ... ]

> +pub struct Options {
> +    /// The default timeout in seconds.
> +    pub timeout: u32,
> +    /// The minimum settable timeout in seconds.
> +    pub min_timeout: u32,
> +    /// The maximum settable timeout in seconds.
> +    pub max_timeout: u32,
> +    /// Hardware limit for the maximum timeout, in milliseconds.
> +    /// Zero means no hardware limit.
> +    pub max_hw_heartbeat_ms: u32,
> +    /// If `true`, the watchdog cannot be stopped once started.
> +    pub nowayout: bool,
> +    /// If `true`, the watchdog is stopped on system reboot. Requires a
> +    /// [`WatchdogOps::stop`] implementation.
> +    pub stop_on_reboot: bool,
> +}

[Severity: High]
Are commonly required driver fields like bootstatus and min_hw_heartbeat_ms
missing from this Options struct?

Because missing fields are zero-initialized in Registration::register() and
there are no setters in Device, are drivers unable to configure these stand=
ard
features, such as reporting WDIOF_CARDRESET?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260723161529.2375=
[email protected]?part=3D1