From e05f0677637b2816c5aef852b3e52b135b51ae7e Mon Sep 17 00:00:00 2001 From: Fabien Parent Date: Wed, 3 May 2023 01:01:08 +0200 Subject: [PATCH] samples: rust: add debugfs samples Add some basic debugfs sample module to show how to use the debugfs API. The sample module is showing: * How to create a directory * How to define and register a debugfs file by implementing file::Operations * How to use the attribute macro to expose simple numerical debugfs values. This is the equivalent of the C macro DEFINE_DEBUGFS_ATTRIBUTE{,_SIGNED} Signed-off-by: Fabien Parent --- samples/rust/Kconfig | 10 +++ samples/rust/Makefile | 1 + samples/rust/rust_debugfs.rs | 114 +++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 samples/rust/rust_debugfs.rs diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index b0f74a81c8f9ad..fc26dafc6fa386 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -10,6 +10,16 @@ menuconfig SAMPLES_RUST if SAMPLES_RUST +config SAMPLE_RUST_DEBUGFS + tristate "Debugfs" + help + This option builds the Rust debugfs module sample. + + To compile this as a module, choose M here: + the module will be called rust_debugfs. + + If unsure, say N. + config SAMPLE_RUST_MINIMAL tristate "Minimal" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 03086dabbea44f..f80ff73028b40c 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_SAMPLE_RUST_DEBUGFS) += rust_debugfs.o obj-$(CONFIG_SAMPLE_RUST_MINIMAL) += rust_minimal.o obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o diff --git a/samples/rust/rust_debugfs.rs b/samples/rust/rust_debugfs.rs new file mode 100644 index 00000000000000..063cfd21ea324c --- /dev/null +++ b/samples/rust/rust_debugfs.rs @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust debugfs device sample + +#![allow(missing_docs)] + +use kernel::{ + c_str, debugfs, file, + file::File, + io_buffer::IoBufferWriter, + prelude::*, + sync::{Arc, SpinLock}, + types::Mode, +}; + +struct SampleFile; + +#[vtable] +impl file::Operations for SampleFile { + fn open(_data: &(), _file: &File) -> Result { + Ok(()) + } + + fn read( + _data: (), + _file: &File, + writer: &mut impl IoBufferWriter, + offset: u64, + ) -> Result { + let data = b"Sample debugfs file implementing file::Operations\n"; + let offset = offset as usize; + + if offset > data.len() { + return Ok(0); + } + + let len = core::cmp::min(writer.len(), data.len() - offset); + writer.write_slice(&data[offset..(offset + len)])?; + Ok(len) + } +} + +#[pin_data] +struct IncAttribute { + #[pin] + data: SpinLock, +} + +impl debugfs::attr::Attribute for IncAttribute { + fn get(&self) -> Result { + let mut guard = self.data.lock(); + let ret = *guard; + *guard = ret + 1; + Ok(ret) + } + + fn set(&self, val: i64) -> Result { + let mut guard = self.data.lock(); + *guard = val; + Ok(()) + } +} + +debugfs::attribute_signed!(IncAttribute, "%#d\n"); + +struct RustDebugfs { + _sample_file: debugfs::PinnedRegistration, + _inc_attribute: debugfs::PinnedRegistration>, + _symlink: debugfs::Registration<()>, +} +impl kernel::Module for RustDebugfs { + fn init(_module: &'static ThisModule) -> Result { + let dir = Arc::try_new(debugfs::Registration::register_dir( + c_str!("rust_samples"), + None, + )?)?; + + let sample_file = debugfs::Registration::register_file::( + c_str!("sample"), + Mode::from_int(0444), + (), + Some(dir.clone()), + )?; + + let symlink = debugfs::Registration::register_symlink( + c_str!("sample_symlink"), + Some(dir.clone()), + c_str!("sample"), + )?; + + let attribute = Arc::pin_init(pin_init!(IncAttribute { + data <- kernel::new_spinlock!(0x42), + }))?; + let inc_attribute = attribute.register( + c_str!("inc_attribute"), + Mode::from_int(0666), + Some(dir.clone()), + )?; + + Ok(Self { + _sample_file: sample_file, + _inc_attribute: inc_attribute, + _symlink: symlink, + }) + } +} + +module! { + type: RustDebugfs, + name: "rust_debugfs", + author: "Fabien Parent ", + description: "Rust debugfs sample", + license: "GPL", +}