All of lore.kernel.org
 help / color / mirror / Atom feed
From: Danilo Krummrich <dakr@kernel.org>
To: gregkh@linuxfoundation.org, rafael@kernel.org, ojeda@kernel.org,
	alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net,
	bjorn3_gh@protonmail.com, lossin@kernel.org,
	a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu,
	mmaurer@google.com
Cc: rust-for-linux@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org, Danilo Krummrich <dakr@kernel.org>
Subject: [PATCH v2 5/8] rust: debugfs: support blobs from smart pointers
Date: Tue, 21 Oct 2025 00:26:17 +0200	[thread overview]
Message-ID: <20251020222722.240473-6-dakr@kernel.org> (raw)
In-Reply-To: <20251020222722.240473-1-dakr@kernel.org>

Extend Rust debugfs binary support to allow exposing data stored in
common smart pointers and heap-allocated collections.

- Implement BinaryWriter for Box<T>, Pin<Box<T>>, Arc<T>, and Vec<T>.
- Introduce BinaryReaderMut for mutable binary access with outer locks.
- Implement BinaryReaderMut for Box<T>, Vec<T>, and base types.
- Update BinaryReader to delegate to BinaryReaderMut for Mutex<T>,
  Box<T>, Pin<Box<T>> and Arc<T>.

This enables debugfs files to directly expose or update data stored
inside heap-allocated, reference-counted, or lock-protected containers
without manual dereferencing or locking.

Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
 rust/kernel/debugfs.rs        |   2 +-
 rust/kernel/debugfs/traits.rs | 148 +++++++++++++++++++++++++++++++++-
 2 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs
index 95cd3376ecbe..d2bc7550d81e 100644
--- a/rust/kernel/debugfs.rs
+++ b/rust/kernel/debugfs.rs
@@ -21,7 +21,7 @@
 use core::ops::Deref;
 
 mod traits;
-pub use traits::{BinaryReader, BinaryWriter, Reader, Writer};
+pub use traits::{BinaryReader, BinaryReaderMut, BinaryWriter, Reader, Writer};
 
 mod callback_adapters;
 use callback_adapters::{FormatAdapter, NoWriter, WritableAdapter};
diff --git a/rust/kernel/debugfs/traits.rs b/rust/kernel/debugfs/traits.rs
index 5f80ce77bf17..c1adf4d9f270 100644
--- a/rust/kernel/debugfs/traits.rs
+++ b/rust/kernel/debugfs/traits.rs
@@ -3,12 +3,15 @@
 
 //! Traits for rendering or updating values exported to DebugFS.
 
+use crate::alloc::Allocator;
 use crate::fs::file;
 use crate::prelude::*;
+use crate::sync::Arc;
 use crate::sync::Mutex;
 use crate::transmute::{AsBytes, FromBytes};
 use crate::uaccess::{UserSliceReader, UserSliceWriter};
 use core::fmt::{self, Debug, Formatter};
+use core::ops::{Deref, DerefMut};
 use core::str::FromStr;
 use core::sync::atomic::{
     AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64,
@@ -51,12 +54,14 @@ pub trait BinaryWriter {
     fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize>;
 }
 
+// Base implementation for any `T: AsBytes`.
 impl<T: AsBytes> BinaryWriter for T {
     fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize> {
         writer.write_slice_partial(self.as_bytes(), offset)
     }
 }
 
+// Delegate for `Mutex<T>`: Support a `T` with an outer mutex.
 impl<T: BinaryWriter> BinaryWriter for Mutex<T> {
     fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize> {
         let guard = self.lock();
@@ -65,6 +70,56 @@ fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) ->
     }
 }
 
+// Delegate for `Box<T, A>`: Support a `Box<T, A>` with no lock or an inner lock.
+impl<T, A> BinaryWriter for Box<T, A>
+where
+    T: BinaryWriter,
+    A: Allocator,
+{
+    fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize> {
+        self.deref().write_to_slice(writer, offset)
+    }
+}
+
+// Delegate for `Pin<Box<T, A>>`: Support a `Pin<Box<T, A>>` with no lock or an inner lock.
+impl<T, A> BinaryWriter for Pin<Box<T, A>>
+where
+    T: BinaryWriter,
+    A: Allocator,
+{
+    fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize> {
+        self.deref().write_to_slice(writer, offset)
+    }
+}
+
+// Delegate for `Arc<T>`: Support a `Arc<T>` with no lock or an inner lock.
+impl<T> BinaryWriter for Arc<T>
+where
+    T: BinaryWriter,
+{
+    fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize> {
+        self.deref().write_to_slice(writer, offset)
+    }
+}
+
+// Delegate for `Vec<T, A>`.
+impl<T, A> BinaryWriter for Vec<T, A>
+where
+    T: AsBytes,
+    A: Allocator,
+{
+    fn write_to_slice(&self, writer: &mut UserSliceWriter, offset: file::Offset) -> Result<usize> {
+        let slice = self.as_slice();
+
+        // SAFETY: `T: AsBytes` allows us to treat `&[T]` as `&[u8]`.
+        let buffer = unsafe {
+            core::slice::from_raw_parts(slice.as_ptr().cast(), core::mem::size_of_val(slice))
+        };
+
+        writer.write_slice_partial(buffer, offset)
+    }
+}
+
 /// A trait for types that can be updated from a user slice.
 ///
 /// This works similarly to `FromStr`, but operates on a `UserSliceReader` rather than a &str.
@@ -93,6 +148,73 @@ fn read_from_slice(&self, reader: &mut UserSliceReader) -> Result {
 }
 
 /// Trait for types that can be constructed from a binary representation.
+///
+/// See also [`BinaryReader`] for interior mutability.
+pub trait BinaryReaderMut {
+    /// Reads the binary form of `self` from `reader`.
+    ///
+    /// Same as [`BinaryReader::read_from_slice`], but takes a mutable reference.
+    ///
+    /// `offset` is the requested offset into the binary representation of `self`.
+    ///
+    /// On success, returns the number of bytes read from `reader`.
+    fn read_from_slice_mut(
+        &mut self,
+        reader: &mut UserSliceReader,
+        offset: file::Offset,
+    ) -> Result<usize>;
+}
+
+// Base implementation for any `T: AsBytes + FromBytes`.
+impl<T: AsBytes + FromBytes> BinaryReaderMut for T {
+    fn read_from_slice_mut(
+        &mut self,
+        reader: &mut UserSliceReader,
+        offset: file::Offset,
+    ) -> Result<usize> {
+        reader.read_slice_partial(self.as_bytes_mut(), offset)
+    }
+}
+
+// Delegate for `Box<T, A>`: Support a `Box<T, A>` with an outer lock.
+impl<T: ?Sized + BinaryReaderMut, A: Allocator> BinaryReaderMut for Box<T, A> {
+    fn read_from_slice_mut(
+        &mut self,
+        reader: &mut UserSliceReader,
+        offset: file::Offset,
+    ) -> Result<usize> {
+        self.deref_mut().read_from_slice_mut(reader, offset)
+    }
+}
+
+// Delegate for `Vec<T, A>`: Support a `Vec<T, A>` with an outer lock.
+impl<T, A> BinaryReaderMut for Vec<T, A>
+where
+    T: AsBytes + FromBytes,
+    A: Allocator,
+{
+    fn read_from_slice_mut(
+        &mut self,
+        reader: &mut UserSliceReader,
+        offset: file::Offset,
+    ) -> Result<usize> {
+        let slice = self.as_mut_slice();
+
+        // SAFETY: `T: AsBytes + FromBytes` allows us to treat `&mut [T]` as `&mut [u8]`.
+        let buffer = unsafe {
+            core::slice::from_raw_parts_mut(
+                slice.as_mut_ptr().cast(),
+                core::mem::size_of_val(slice),
+            )
+        };
+
+        reader.read_slice_partial(buffer, offset)
+    }
+}
+
+/// Trait for types that can be constructed from a binary representation.
+///
+/// See also [`BinaryReaderMut`] for the mutable version.
 pub trait BinaryReader {
     /// Reads the binary form of `self` from `reader`.
     ///
@@ -102,11 +224,33 @@ pub trait BinaryReader {
     fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::Offset) -> Result<usize>;
 }
 
-impl<T: AsBytes + FromBytes> BinaryReader for Mutex<T> {
+// Delegate for `Mutex<T>`: Support a `T` with an outer `Mutex`.
+impl<T: BinaryReaderMut> BinaryReader for Mutex<T> {
     fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::Offset) -> Result<usize> {
         let mut this = self.lock();
 
-        reader.read_slice_partial(this.as_bytes_mut(), offset)
+        this.read_from_slice_mut(reader, offset)
+    }
+}
+
+// Delegate for `Box<T, A>`: Support a `Box<T, A>` with an inner lock.
+impl<T: ?Sized + BinaryReader, A: Allocator> BinaryReader for Box<T, A> {
+    fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::Offset) -> Result<usize> {
+        self.deref().read_from_slice(reader, offset)
+    }
+}
+
+// Delegate for `Pin<Box<T, A>>`: Support a `Pin<Box<T, A>>` with an inner lock.
+impl<T: ?Sized + BinaryReader, A: Allocator> BinaryReader for Pin<Box<T, A>> {
+    fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::Offset) -> Result<usize> {
+        self.deref().read_from_slice(reader, offset)
+    }
+}
+
+// Delegate for `Arc<T>`: Support an `Arc<T>` with an inner lock.
+impl<T: ?Sized + BinaryReader> BinaryReader for Arc<T> {
+    fn read_from_slice(&self, reader: &mut UserSliceReader, offset: file::Offset) -> Result<usize> {
+        self.deref().read_from_slice(reader, offset)
     }
 }
 
-- 
2.51.0


  parent reply	other threads:[~2025-10-20 22:28 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-20 22:26 [PATCH v2 0/8] Binary Large Objects for Rust DebugFS Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 1/8] rust: fs: add file::Offset type alias Danilo Krummrich
2025-10-21 13:40   ` Alice Ryhl
2025-10-21 15:08   ` Miguel Ojeda
2025-10-21 15:26     ` Danilo Krummrich
2025-10-21 16:00       ` Miguel Ojeda
2025-10-21 16:25         ` Danilo Krummrich
2025-10-21 16:47           ` Miguel Ojeda
2025-10-21 17:34             ` Danilo Krummrich
2025-10-21 23:16               ` Miguel Ojeda
2025-10-29 12:49   ` Christian Brauner
2025-10-29 15:26     ` Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 2/8] rust: uaccess: add UserSliceReader::read_slice_partial() Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 3/8] rust: uaccess: add UserSliceWriter::write_slice_partial() Danilo Krummrich
2025-10-21 14:00   ` Alice Ryhl
2025-10-21 14:14     ` Danilo Krummrich
2025-10-21 14:18       ` Alice Ryhl
2025-10-21 14:34         ` Danilo Krummrich
2025-10-22  8:22           ` Alice Ryhl
2025-10-22  9:06             ` Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 4/8] rust: debugfs: support for binary large objects Danilo Krummrich
2025-10-21 14:03   ` Alice Ryhl
2025-10-22  5:58   ` Alexandre Courbot
2025-10-20 22:26 ` Danilo Krummrich [this message]
2025-10-22  5:57   ` [PATCH v2 5/8] rust: debugfs: support blobs from smart pointers Alexandre Courbot
2025-10-22  9:34     ` Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 6/8] samples: rust: debugfs: add example for blobs Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 7/8] rust: debugfs: support binary large objects for ScopedDir Danilo Krummrich
2025-10-20 22:26 ` [PATCH v2 8/8] samples: rust: debugfs_scoped: add example for blobs Danilo Krummrich
2025-10-21  7:09 ` [PATCH v2 0/8] Binary Large Objects for Rust DebugFS Greg KH
2025-10-21 21:26   ` Matthew Maurer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251020222722.240473-6-dakr@kernel.org \
    --to=dakr@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=mmaurer@google.com \
    --cc=ojeda@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.