rust: debugfs: Replace the usage of Rust native atomics

Rust native atomics are not allowed to use in kernel due to the mismatch
of memory model with Linux kernel memory model, hence remove the usage
of Rust native atomics in debufs.

Reviewed-by: Matthew Maurer <mmaurer@google.com>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Tested-by: David Gow <davidgow@google.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://patch.msgid.link/20251022035324.70785-4-boqun.feng@gmail.com
This commit is contained in:
Boqun Feng 2025-10-21 23:53:24 -04:00
parent 013f912eb5
commit f74cf399e0
3 changed files with 25 additions and 46 deletions

View File

@ -4,14 +4,11 @@
//! Traits for rendering or updating values exported to DebugFS. //! Traits for rendering or updating values exported to DebugFS.
use crate::prelude::*; use crate::prelude::*;
use crate::sync::atomic::{Atomic, AtomicBasicOps, AtomicType, Relaxed};
use crate::sync::Mutex; use crate::sync::Mutex;
use crate::uaccess::UserSliceReader; use crate::uaccess::UserSliceReader;
use core::fmt::{self, Debug, Formatter}; use core::fmt::{self, Debug, Formatter};
use core::str::FromStr; use core::str::FromStr;
use core::sync::atomic::{
AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64,
AtomicU8, AtomicUsize, Ordering,
};
/// A trait for types that can be written into a string. /// A trait for types that can be written into a string.
/// ///
@ -66,10 +63,10 @@ fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
} }
} }
macro_rules! impl_reader_for_atomic { impl<T: AtomicType + FromStr> Reader for Atomic<T>
($(($atomic_type:ty, $int_type:ty)),*) => { where
$( T::Repr: AtomicBasicOps,
impl Reader for $atomic_type { {
fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result { fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
let mut buf = [0u8; 21]; // Enough for a 64-bit number. let mut buf = [0u8; 21]; // Enough for a 64-bit number.
if reader.len() > buf.len() { if reader.len() > buf.len() {
@ -79,24 +76,8 @@ fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
reader.read_slice(&mut buf[..n])?; reader.read_slice(&mut buf[..n])?;
let s = core::str::from_utf8(&buf[..n]).map_err(|_| EINVAL)?; let s = core::str::from_utf8(&buf[..n]).map_err(|_| EINVAL)?;
let val = s.trim().parse::<$int_type>().map_err(|_| EINVAL)?; let val = s.trim().parse::<T>().map_err(|_| EINVAL)?;
self.store(val, Ordering::Relaxed); self.store(val, Relaxed);
Ok(()) Ok(())
} }
}
)*
};
} }
impl_reader_for_atomic!(
(AtomicI16, i16),
(AtomicI32, i32),
(AtomicI64, i64),
(AtomicI8, i8),
(AtomicIsize, isize),
(AtomicU16, u16),
(AtomicU32, u32),
(AtomicU64, u64),
(AtomicU8, u8),
(AtomicUsize, usize)
);

View File

@ -32,14 +32,12 @@
//! ``` //! ```
use core::str::FromStr; use core::str::FromStr;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;
use kernel::c_str; use kernel::c_str;
use kernel::debugfs::{Dir, File}; use kernel::debugfs::{Dir, File};
use kernel::new_mutex; use kernel::new_mutex;
use kernel::prelude::*; use kernel::prelude::*;
use kernel::sync::atomic::{Atomic, Relaxed};
use kernel::sync::Mutex; use kernel::sync::Mutex;
use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef}; use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef};
kernel::module_platform_driver! { kernel::module_platform_driver! {
@ -59,7 +57,7 @@ struct RustDebugFs {
#[pin] #[pin]
_compatible: File<CString>, _compatible: File<CString>,
#[pin] #[pin]
counter: File<AtomicUsize>, counter: File<Atomic<usize>>,
#[pin] #[pin]
inner: File<Mutex<Inner>>, inner: File<Mutex<Inner>>,
} }
@ -109,7 +107,7 @@ fn probe(
) -> Result<Pin<KBox<Self>>> { ) -> Result<Pin<KBox<Self>>> {
let result = KBox::try_pin_init(RustDebugFs::new(pdev), GFP_KERNEL)?; let result = KBox::try_pin_init(RustDebugFs::new(pdev), GFP_KERNEL)?;
// We can still mutate fields through the files which are atomic or mutexed: // We can still mutate fields through the files which are atomic or mutexed:
result.counter.store(91, Ordering::Relaxed); result.counter.store(91, Relaxed);
{ {
let mut guard = result.inner.lock(); let mut guard = result.inner.lock();
guard.x = guard.y; guard.x = guard.y;
@ -120,8 +118,8 @@ fn probe(
} }
impl RustDebugFs { impl RustDebugFs {
fn build_counter(dir: &Dir) -> impl PinInit<File<AtomicUsize>> + '_ { fn build_counter(dir: &Dir) -> impl PinInit<File<Atomic<usize>>> + '_ {
dir.read_write_file(c_str!("counter"), AtomicUsize::new(0)) dir.read_write_file(c_str!("counter"), Atomic::<usize>::new(0))
} }
fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ { fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ {

View File

@ -6,9 +6,9 @@
//! `Scope::dir` to create a variety of files without the need to separately //! `Scope::dir` to create a variety of files without the need to separately
//! track them all. //! track them all.
use core::sync::atomic::AtomicUsize;
use kernel::debugfs::{Dir, Scope}; use kernel::debugfs::{Dir, Scope};
use kernel::prelude::*; use kernel::prelude::*;
use kernel::sync::atomic::Atomic;
use kernel::sync::Mutex; use kernel::sync::Mutex;
use kernel::{c_str, new_mutex, str::CString}; use kernel::{c_str, new_mutex, str::CString};
@ -62,7 +62,7 @@ fn create_file_write(
let file_name = CString::try_from_fmt(fmt!("{name_str}"))?; let file_name = CString::try_from_fmt(fmt!("{name_str}"))?;
for sub in items { for sub in items {
nums.push( nums.push(
AtomicUsize::new(sub.parse().map_err(|_| EINVAL)?), Atomic::<usize>::new(sub.parse().map_err(|_| EINVAL)?),
GFP_KERNEL, GFP_KERNEL,
)?; )?;
} }
@ -109,7 +109,7 @@ fn init(device_dir: Dir) -> impl PinInit<Self> {
struct DeviceData { struct DeviceData {
name: CString, name: CString,
nums: KVec<AtomicUsize>, nums: KVec<Atomic<usize>>,
} }
fn init_control(base_dir: &Dir, dyn_dirs: Dir) -> impl PinInit<Scope<ModuleData>> + '_ { fn init_control(base_dir: &Dir, dyn_dirs: Dir) -> impl PinInit<Scope<ModuleData>> + '_ {