[PATCH] rust: debugfs: add primitive type bindings

Matthias Kaehlcke posted 1 patch 1 day, 19 hours ago
rust/kernel/debugfs.rs       | 52 +++++++++++++++++++++
samples/rust/rust_debugfs.rs | 91 ++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+)
[PATCH] rust: debugfs: add primitive type bindings
Posted by Matthias Kaehlcke 1 day, 19 hours ago
Introduce `impl_debugfs_primitive!` to implement debugfs attribute
creation for native Rust primitive types by wrapping C debugfs creation
helpers.

Signed-off-by: Matthias Kaehlcke <matthias@kaehlcke.net>
---
 rust/kernel/debugfs.rs       | 52 +++++++++++++++++++++
 samples/rust/rust_debugfs.rs | 91 ++++++++++++++++++++++++++++++++++++
 2 files changed, 143 insertions(+)

diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs
index d7b8014a6474..bec600c67a06 100644
--- a/rust/kernel/debugfs.rs
+++ b/rust/kernel/debugfs.rs
@@ -400,6 +400,58 @@ pub fn scope<'a, T: 'a, E: 'a, F>(
     }
 }
 
+/// Implements `debugfs` interface operations for a single primitive type.
+///
+/// This macro generates the necessary FFI wrappers and glue code to expose
+/// a specific primitive type (e.g., `u32`, `bool`) to the `debugfs` filesystem.
+///
+/// # Type Support
+///
+/// Accepts standard integer primitives (`u8` through `u64`, `x8` through `x64`),
+/// `bool`, and `usize`.
+///
+/// # Examples
+///
+/// ```rust,ignore
+/// impl_debugfs_primitive!(u32, create_u32, debugfs_create_u32);
+/// ```
+macro_rules! impl_debugfs_primitive {
+    ($type:ty, $fn_name:ident,$c_func:ident) => {
+        impl Dir {
+            /// Creates a debugfs entry for a primitive `$type` value inside this directory.
+            ///
+            /// # Safety
+            ///
+            /// `value` must point to a valid memory location that outlives this directory `Dir`
+            /// (e.g., inside a pinned driver state structure or a `static` location).
+            pub unsafe fn $fn_name(&self, name: &CStr, mode: u16, value: *mut $type) {
+                let parent_ptr = match self.0.as_deref() {
+                    Some(entry) => entry.as_ptr(),
+                    None => core::ptr::null_mut(),
+                };
+
+                // SAFETY: `name` is a valid CStr. `parent_ptr` points to a valid parent
+                // dentry or NULL. The caller guarantees that `value` outlives the debugfs node.
+                unsafe {
+                    bindings::$c_func(name.as_char_ptr(), mode, parent_ptr, value);
+                }
+            }
+        }
+    };
+}
+
+// Bind native Rust primitive types to their corresponding C debugfs helpers.
+impl_debugfs_primitive!(u8, create_u8, debugfs_create_u8);
+impl_debugfs_primitive!(u16, create_u16, debugfs_create_u16);
+impl_debugfs_primitive!(u32, create_u32, debugfs_create_u32);
+impl_debugfs_primitive!(u64, create_u64, debugfs_create_u64);
+impl_debugfs_primitive!(u8, create_x8, debugfs_create_x8);
+impl_debugfs_primitive!(u16, create_x16, debugfs_create_x16);
+impl_debugfs_primitive!(u32, create_x32, debugfs_create_x32);
+impl_debugfs_primitive!(u64, create_x64, debugfs_create_x64);
+impl_debugfs_primitive!(bool, create_bool, debugfs_create_bool);
+impl_debugfs_primitive!(usize, create_size_t, debugfs_create_size_t);
+
 #[pin_data]
 /// Handle to a DebugFS scope, which ensures that attached `data` will outlive the DebugFS entry
 /// without moving.
diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs
index 77c19a437695..b2ef8c71f7ee 100644
--- a/samples/rust/rust_debugfs.rs
+++ b/samples/rust/rust_debugfs.rs
@@ -34,6 +34,7 @@
 use core::str::FromStr;
 use kernel::{
     acpi,
+    c_str,
     debugfs::{
         Dir,
         File, //
@@ -79,6 +80,8 @@ struct RustDebugFs {
     array_blob: File<Mutex<[u8; 4]>>,
     #[pin]
     vector_blob: File<Mutex<KVec<u8>>>,
+    #[pin]
+    primitive_values: PrimitiveValues,
 }
 
 #[derive(Debug)]
@@ -87,6 +90,36 @@ struct Inner {
     y: u32,
 }
 
+struct PrimitiveValues {
+    u8: u8,
+    u16: u16,
+    u32: u32,
+    u64: u64,
+    x8: u8,
+    x16: u16,
+    x32: u32,
+    x64: u64,
+    size_t: usize,
+    bool: bool,
+}
+
+impl PrimitiveValues {
+    fn new() -> Self {
+        Self {
+            u8: 8,
+            u16: 16,
+            u32: 32,
+            u64: 64,
+            x8: 0x88,
+            x16: 0x1616,
+            x32: 0x32323232,
+            x64: 0x6464646464646464,
+            size_t: 12345678,
+            bool: true,
+        }
+    }
+}
+
 impl FromStr for Inner {
     type Err = Error;
     fn from_str(s: &str) -> Result<Self> {
@@ -171,9 +204,67 @@ fn new<'a, 'b>(
                     c"vector_blob",
                     new_mutex!(kernel::kvec!(0x42; SZ_4K)?),
                 ),
+                primitive_values <- PrimitiveValues::new(),
                 _debugfs: debugfs,
                 pdev: pdev.into(),
             }
         }
+        .pin_chain(|this| {
+            // SAFETY: primitive values live until the module is dropped
+            unsafe {
+                this._debugfs.create_u8(
+                    c_str!("u8"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.u8) as *mut _,
+                );
+                this._debugfs.create_u16(
+                    c_str!("u16"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.u16) as *mut _,
+                );
+                this._debugfs.create_u32(
+                    c_str!("u32"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.u32) as *mut _,
+                );
+                this._debugfs.create_u64(
+                    c_str!("u64"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.u64) as *mut _,
+                );
+                this._debugfs.create_x8(
+                    c_str!("x8"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.x8) as *mut _,
+                );
+                this._debugfs.create_x16(
+                    c_str!("x16"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.x16) as *mut _,
+                );
+                this._debugfs.create_x32(
+                    c_str!("x32"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.x32) as *mut _,
+                );
+                this._debugfs.create_x64(
+                    c_str!("x64"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.x64) as *mut _,
+                );
+                this._debugfs.create_bool(
+                    c_str!("bool"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.bool) as *mut _,
+                );
+                this._debugfs.create_size_t(
+                    c_str!("usize"),
+                    0644,
+                    core::ptr::addr_of!(this.primitive_values.size_t) as *mut _,
+                );
+            }
+
+            Ok(())
+        })
     }
 }
-- 
2.47.3
Re: [PATCH] rust: debugfs: add primitive type bindings
Posted by Matthias Kaehlcke 1 day, 18 hours ago
sashiko-bot@kernel.org pointed out a few issues that seem valid,
I'll try to address these first before human reviewer time is
needed.

El Tue, Sep 22, 2026 at 09:18:58PM +0200 Matthias Kaehlcke ha dit:

> Introduce `impl_debugfs_primitive!` to implement debugfs attribute
> creation for native Rust primitive types by wrapping C debugfs creation
> helpers.
> 
> Signed-off-by: Matthias Kaehlcke <matthias@kaehlcke.net>
> ---
>  rust/kernel/debugfs.rs       | 52 +++++++++++++++++++++
>  samples/rust/rust_debugfs.rs | 91 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 143 insertions(+)
> 
> diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs
> index d7b8014a6474..bec600c67a06 100644
> --- a/rust/kernel/debugfs.rs
> +++ b/rust/kernel/debugfs.rs
> @@ -400,6 +400,58 @@ pub fn scope<'a, T: 'a, E: 'a, F>(
>      }
>  }
>  
> +/// Implements `debugfs` interface operations for a single primitive type.
> +///
> +/// This macro generates the necessary FFI wrappers and glue code to expose
> +/// a specific primitive type (e.g., `u32`, `bool`) to the `debugfs` filesystem.
> +///
> +/// # Type Support
> +///
> +/// Accepts standard integer primitives (`u8` through `u64`, `x8` through `x64`),
> +/// `bool`, and `usize`.
> +///
> +/// # Examples
> +///
> +/// ```rust,ignore
> +/// impl_debugfs_primitive!(u32, create_u32, debugfs_create_u32);
> +/// ```
> +macro_rules! impl_debugfs_primitive {
> +    ($type:ty, $fn_name:ident,$c_func:ident) => {
> +        impl Dir {
> +            /// Creates a debugfs entry for a primitive `$type` value inside this directory.
> +            ///
> +            /// # Safety
> +            ///
> +            /// `value` must point to a valid memory location that outlives this directory `Dir`
> +            /// (e.g., inside a pinned driver state structure or a `static` location).
> +            pub unsafe fn $fn_name(&self, name: &CStr, mode: u16, value: *mut $type) {
> +                let parent_ptr = match self.0.as_deref() {
> +                    Some(entry) => entry.as_ptr(),
> +                    None => core::ptr::null_mut(),
> +                };
> +
> +                // SAFETY: `name` is a valid CStr. `parent_ptr` points to a valid parent
> +                // dentry or NULL. The caller guarantees that `value` outlives the debugfs node.
> +                unsafe {
> +                    bindings::$c_func(name.as_char_ptr(), mode, parent_ptr, value);
> +                }
> +            }
> +        }
> +    };
> +}
> +
> +// Bind native Rust primitive types to their corresponding C debugfs helpers.
> +impl_debugfs_primitive!(u8, create_u8, debugfs_create_u8);
> +impl_debugfs_primitive!(u16, create_u16, debugfs_create_u16);
> +impl_debugfs_primitive!(u32, create_u32, debugfs_create_u32);
> +impl_debugfs_primitive!(u64, create_u64, debugfs_create_u64);
> +impl_debugfs_primitive!(u8, create_x8, debugfs_create_x8);
> +impl_debugfs_primitive!(u16, create_x16, debugfs_create_x16);
> +impl_debugfs_primitive!(u32, create_x32, debugfs_create_x32);
> +impl_debugfs_primitive!(u64, create_x64, debugfs_create_x64);
> +impl_debugfs_primitive!(bool, create_bool, debugfs_create_bool);
> +impl_debugfs_primitive!(usize, create_size_t, debugfs_create_size_t);
> +
>  #[pin_data]
>  /// Handle to a DebugFS scope, which ensures that attached `data` will outlive the DebugFS entry
>  /// without moving.
> diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs
> index 77c19a437695..b2ef8c71f7ee 100644
> --- a/samples/rust/rust_debugfs.rs
> +++ b/samples/rust/rust_debugfs.rs
> @@ -34,6 +34,7 @@
>  use core::str::FromStr;
>  use kernel::{
>      acpi,
> +    c_str,
>      debugfs::{
>          Dir,
>          File, //
> @@ -79,6 +80,8 @@ struct RustDebugFs {
>      array_blob: File<Mutex<[u8; 4]>>,
>      #[pin]
>      vector_blob: File<Mutex<KVec<u8>>>,
> +    #[pin]
> +    primitive_values: PrimitiveValues,
>  }
>  
>  #[derive(Debug)]
> @@ -87,6 +90,36 @@ struct Inner {
>      y: u32,
>  }
>  
> +struct PrimitiveValues {
> +    u8: u8,
> +    u16: u16,
> +    u32: u32,
> +    u64: u64,
> +    x8: u8,
> +    x16: u16,
> +    x32: u32,
> +    x64: u64,
> +    size_t: usize,
> +    bool: bool,
> +}
> +
> +impl PrimitiveValues {
> +    fn new() -> Self {
> +        Self {
> +            u8: 8,
> +            u16: 16,
> +            u32: 32,
> +            u64: 64,
> +            x8: 0x88,
> +            x16: 0x1616,
> +            x32: 0x32323232,
> +            x64: 0x6464646464646464,
> +            size_t: 12345678,
> +            bool: true,
> +        }
> +    }
> +}
> +
>  impl FromStr for Inner {
>      type Err = Error;
>      fn from_str(s: &str) -> Result<Self> {
> @@ -171,9 +204,67 @@ fn new<'a, 'b>(
>                      c"vector_blob",
>                      new_mutex!(kernel::kvec!(0x42; SZ_4K)?),
>                  ),
> +                primitive_values <- PrimitiveValues::new(),
>                  _debugfs: debugfs,
>                  pdev: pdev.into(),
>              }
>          }
> +        .pin_chain(|this| {
> +            // SAFETY: primitive values live until the module is dropped
> +            unsafe {
> +                this._debugfs.create_u8(
> +                    c_str!("u8"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.u8) as *mut _,
> +                );
> +                this._debugfs.create_u16(
> +                    c_str!("u16"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.u16) as *mut _,
> +                );
> +                this._debugfs.create_u32(
> +                    c_str!("u32"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.u32) as *mut _,
> +                );
> +                this._debugfs.create_u64(
> +                    c_str!("u64"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.u64) as *mut _,
> +                );
> +                this._debugfs.create_x8(
> +                    c_str!("x8"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.x8) as *mut _,
> +                );
> +                this._debugfs.create_x16(
> +                    c_str!("x16"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.x16) as *mut _,
> +                );
> +                this._debugfs.create_x32(
> +                    c_str!("x32"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.x32) as *mut _,
> +                );
> +                this._debugfs.create_x64(
> +                    c_str!("x64"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.x64) as *mut _,
> +                );
> +                this._debugfs.create_bool(
> +                    c_str!("bool"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.bool) as *mut _,
> +                );
> +                this._debugfs.create_size_t(
> +                    c_str!("usize"),
> +                    0644,
> +                    core::ptr::addr_of!(this.primitive_values.size_t) as *mut _,
> +                );
> +            }
> +
> +            Ok(())
> +        })
>      }
>  }
> -- 
> 2.47.3