[PATCH v3 4/4] rust: samples: Add debugfs sample

Matthew Maurer posted 4 patches 9 months, 1 week ago
There is a newer version of this series
[PATCH v3 4/4] rust: samples: Add debugfs sample
Posted by Matthew Maurer 9 months, 1 week ago
Provides an example of using the Rust DebugFS bindings.

Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
 MAINTAINERS                  |  1 +
 samples/rust/Kconfig         | 11 +++++++++
 samples/rust/Makefile        |  1 +
 samples/rust/rust_debugfs.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a3b835e427b083a4ddd690d9e7739851f0af47ae..426bcdac025134e20911de8e2cf5c9efb0591814 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7278,6 +7278,7 @@ F:	rust/kernel/devres.rs
 F:	rust/kernel/driver.rs
 F:	rust/kernel/faux.rs
 F:	rust/kernel/platform.rs
+F:	samples/rust/rust_debugfs.rs
 F:	samples/rust/rust_driver_platform.rs
 F:	samples/rust/rust_driver_faux.rs
 
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index 43cb72d72631bb2d6e06185e1d88778edff6ee13..6c42ed73f842cda26256039e6917bb443738d3f1 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -51,6 +51,17 @@ config SAMPLE_RUST_DMA
 
 	  If unsure, say N.
 
+config SAMPLE_RUST_DEBUGFS
+	tristate "DebugFS Test Driver"
+	depends on DEBUG_FS
+	help
+	  This option builds the Rust DebugFS Test driver sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_debugfs.
+
+	  If unsure, say N.
+
 config SAMPLE_RUST_DRIVER_PCI
 	tristate "PCI Driver"
 	depends on PCI
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index 6a466afd2a21eba84a3b7b2be29f25dce44e9053..b1fc4677ed53fcf7d0f5a3dbf322f65851bc1784 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -4,6 +4,7 @@ ccflags-y += -I$(src)				# needed for trace events
 obj-$(CONFIG_SAMPLE_RUST_MINIMAL)		+= rust_minimal.o
 obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE)		+= rust_misc_device.o
 obj-$(CONFIG_SAMPLE_RUST_PRINT)			+= rust_print.o
+obj-$(CONFIG_SAMPLE_RUST_DEBUGFS)		+= rust_debugfs.o
 obj-$(CONFIG_SAMPLE_RUST_DMA)			+= rust_dma.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI)		+= rust_driver_pci.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM)	+= rust_driver_platform.o
diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b22255667f3bb91b10555ac8b91be850cd5f172e
--- /dev/null
+++ b/samples/rust/rust_debugfs.rs
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Google LLC.
+
+//! Sample DebugFS exporting module
+
+use core::sync::atomic::{AtomicU32, Ordering};
+use kernel::c_str;
+use kernel::debugfs::Dir;
+use kernel::prelude::*;
+
+module! {
+    type: RustDebugFs,
+    name: "rust_debugfs",
+    authors: ["Matthew Maurer"],
+    description: "Rust DebugFS usage sample",
+    license: "GPL",
+}
+
+struct RustDebugFs {
+    // As we only hold this for drop effect (to remove the directory) we have a leading underscore
+    // to indicate to the compiler that we don't expect to use this field directly.
+    _debugfs: Dir,
+}
+
+static EXAMPLE: AtomicU32 = AtomicU32::new(8);
+
+impl kernel::Module for RustDebugFs {
+    fn init(_this: &'static ThisModule) -> Result<Self> {
+        // Create a debugfs directory in the root of the filesystem called "sample_debugfs".
+        let debugfs = Dir::new(c_str!("sample_debugfs"));
+
+        // Create a subdirectory, so "sample_debugfs/subdir" now exists.
+        let sub = debugfs.subdir(c_str!("subdir"));
+
+        // Create a single file in the subdirectory called "example" that will read from the
+        // `EXAMPLE` atomic variable.
+        sub.fmt_file(c_str!("example"), &EXAMPLE, &|example, f| {
+            writeln!(f, "Reading atomic: {}", example.load(Ordering::Relaxed))
+        });
+        // Now, "sample_debugfs/subdir/example" will print "Reading atomic: 8\n" when read.
+
+        // Change the value in the variable displayed by the file. This is intended to demonstrate
+        // that the module can continue to change the value used by the file.
+        EXAMPLE.store(10, Ordering::Relaxed);
+        // Now, "sample_debugfs/subdir/example" will print "Reading atomic: 10\n" when read.
+
+        // Save the root debugfs directory we created to our module object. It will be
+        // automatically cleaned up when our module is unloaded because dropping the module object
+        // will drop the `Dir` handle. The base directory, the subdirectory, and the file will all
+        // continue to exist until the module is unloaded.
+        Ok(Self { _debugfs: debugfs })
+    }
+}

-- 
2.49.0.906.g1f30a19c02-goog
Re: [PATCH v3 4/4] rust: samples: Add debugfs sample
Posted by Danilo Krummrich 9 months, 1 week ago
On Thu, May 01, 2025 at 10:47:44PM +0000, Matthew Maurer wrote:
> +struct RustDebugFs {
> +    // As we only hold this for drop effect (to remove the directory) we have a leading underscore
> +    // to indicate to the compiler that we don't expect to use this field directly.

This feels like an introduction to Rust in the kernel for Rust beginners, which
is a great thing!

However, I wonder if, instead, we may want a dedicated (or even multiple) sample
modules or sample drivers, where we go into such detail and leave those samples
to focus only on the corresponding API?

> +    _debugfs: Dir,
> +}
> +
> +static EXAMPLE: AtomicU32 = AtomicU32::new(8);
> +
> +impl kernel::Module for RustDebugFs {
> +    fn init(_this: &'static ThisModule) -> Result<Self> {
> +        // Create a debugfs directory in the root of the filesystem called "sample_debugfs".
> +        let debugfs = Dir::new(c_str!("sample_debugfs"));
> +
> +        // Create a subdirectory, so "sample_debugfs/subdir" now exists.
> +        let sub = debugfs.subdir(c_str!("subdir"));
> +
> +        // Create a single file in the subdirectory called "example" that will read from the
> +        // `EXAMPLE` atomic variable.
> +        sub.fmt_file(c_str!("example"), &EXAMPLE, &|example, f| {
> +            writeln!(f, "Reading atomic: {}", example.load(Ordering::Relaxed))
> +        });
> +        // Now, "sample_debugfs/subdir/example" will print "Reading atomic: 8\n" when read.
> +
> +        // Change the value in the variable displayed by the file. This is intended to demonstrate
> +        // that the module can continue to change the value used by the file.
> +        EXAMPLE.store(10, Ordering::Relaxed);
> +        // Now, "sample_debugfs/subdir/example" will print "Reading atomic: 10\n" when read.
> +
> +        // Save the root debugfs directory we created to our module object. It will be
> +        // automatically cleaned up when our module is unloaded because dropping the module object
> +        // will drop the `Dir` handle. The base directory, the subdirectory, and the file will all
> +        // continue to exist until the module is unloaded.

Same with this comment.

@Greg: I know you proposed this one; for educational purposes I suppose. What's
your take on the above?
Re: [PATCH v3 4/4] rust: samples: Add debugfs sample
Posted by Greg Kroah-Hartman 9 months, 1 week ago
On Fri, May 02, 2025 at 09:01:01AM +0200, Danilo Krummrich wrote:
> On Thu, May 01, 2025 at 10:47:44PM +0000, Matthew Maurer wrote:
> > +struct RustDebugFs {
> > +    // As we only hold this for drop effect (to remove the directory) we have a leading underscore
> > +    // to indicate to the compiler that we don't expect to use this field directly.
> 
> This feels like an introduction to Rust in the kernel for Rust beginners, which
> is a great thing!
> 
> However, I wonder if, instead, we may want a dedicated (or even multiple) sample
> modules or sample drivers, where we go into such detail and leave those samples
> to focus only on the corresponding API?

People search for the specific example of what they want to do, so I
recommend just leaving all of these comments in for now as knowing to
search for a different example is usually not going to happen :)


> 
> > +    _debugfs: Dir,
> > +}
> > +
> > +static EXAMPLE: AtomicU32 = AtomicU32::new(8);
> > +
> > +impl kernel::Module for RustDebugFs {
> > +    fn init(_this: &'static ThisModule) -> Result<Self> {
> > +        // Create a debugfs directory in the root of the filesystem called "sample_debugfs".
> > +        let debugfs = Dir::new(c_str!("sample_debugfs"));
> > +
> > +        // Create a subdirectory, so "sample_debugfs/subdir" now exists.
> > +        let sub = debugfs.subdir(c_str!("subdir"));
> > +
> > +        // Create a single file in the subdirectory called "example" that will read from the
> > +        // `EXAMPLE` atomic variable.
> > +        sub.fmt_file(c_str!("example"), &EXAMPLE, &|example, f| {
> > +            writeln!(f, "Reading atomic: {}", example.load(Ordering::Relaxed))
> > +        });
> > +        // Now, "sample_debugfs/subdir/example" will print "Reading atomic: 8\n" when read.
> > +
> > +        // Change the value in the variable displayed by the file. This is intended to demonstrate
> > +        // that the module can continue to change the value used by the file.
> > +        EXAMPLE.store(10, Ordering::Relaxed);
> > +        // Now, "sample_debugfs/subdir/example" will print "Reading atomic: 10\n" when read.
> > +
> > +        // Save the root debugfs directory we created to our module object. It will be
> > +        // automatically cleaned up when our module is unloaded because dropping the module object
> > +        // will drop the `Dir` handle. The base directory, the subdirectory, and the file will all
> > +        // continue to exist until the module is unloaded.
> 
> Same with this comment.
> 
> @Greg: I know you proposed this one; for educational purposes I suppose. What's
> your take on the above?

I like it and want to see this here as it helps explain both how to use
this, AND how to have maintainers review code that uses the api that are
not that familiar with how Rust does things.

thanks,

greg k-h
Re: [PATCH v3 4/4] rust: samples: Add debugfs sample
Posted by Danilo Krummrich 9 months, 1 week ago
On Fri, May 02, 2025 at 09:13:28AM +0200, Greg Kroah-Hartman wrote:
> AND how to have maintainers review code that uses the api that are
> not that familiar with how Rust does things.

That sounds very reasonable -- I like it!