rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] rust: add seqfile abstraction
@ 2024-10-01  9:07 Alice Ryhl
  2024-10-01  9:10 ` Alice Ryhl
  2024-10-01 10:23 ` Christian Brauner
  0 siblings, 2 replies; 3+ messages in thread
From: Alice Ryhl @ 2024-10-01  9:07 UTC (permalink / raw)
  To: Christian Brauner, Alexander Viro, Miguel Ojeda, Andrew Morton
  Cc: Kees Cook, Andy Shevchenko, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, linux-kernel, linux-fsdevel, rust-for-linux,
	Alice Ryhl

This adds a simple seq file abstraction that lets you print to a seq
file using ordinary Rust printing syntax.

An example user from Rust Binder:

    pub(crate) fn full_debug_print(
        &self,
        m: &SeqFile,
        owner_inner: &mut ProcessInner,
    ) -> Result<()> {
        let prio = self.node_prio();
        let inner = self.inner.access_mut(owner_inner);
        seq_print!(
            m,
            "  node {}: u{:016x} c{:016x} pri {}:{} hs {} hw {} cs {} cw {}",
            self.debug_id,
            self.ptr,
            self.cookie,
            prio.sched_policy,
            prio.prio,
            inner.strong.has_count,
            inner.weak.has_count,
            inner.strong.count,
            inner.weak.count,
        );
        if !inner.refs.is_empty() {
            seq_print!(m, " proc");
            for node_ref in &inner.refs {
                seq_print!(m, " {}", node_ref.process.task.pid());
            }
        }
        seq_print!(m, "\n");
        for t in &inner.oneway_todo {
            t.debug_print_inner(m, "    pending async transaction ");
        }
        Ok(())
    }

The `SeqFile` type is marked not thread safe so that `call_printf` can
be a `&self` method. The alternative is to use `self: Pin<&mut Self>`
which is inconvenient, or to have `SeqFile` wrap a pointer instead of
wrapping the C struct directly.

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
 rust/kernel/lib.rs      |  1 +
 rust/kernel/seq_file.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index ff7d88022c57..bb6919c4e9bc 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -49,6 +49,7 @@
 pub mod sizes;
 pub mod rbtree;
 pub mod security;
+pub mod seq_file;
 mod static_assert;
 #[doc(hidden)]
 pub mod std_vendor;
diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs
new file mode 100644
index 000000000000..6ca29d576d02
--- /dev/null
+++ b/rust/kernel/seq_file.rs
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Seq file bindings.
+//!
+//! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.h)
+
+use crate::{bindings, c_str, types::NotThreadSafe, types::Opaque};
+
+/// A utility for generating the contents of a seq file.
+#[repr(transparent)]
+pub struct SeqFile {
+    inner: Opaque<bindings::seq_file>,
+    _not_send: NotThreadSafe,
+}
+
+impl SeqFile {
+    /// Creates a new [`SeqFile`] from a raw pointer.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that for the duration of 'a the following is satisfied:
+    /// * The pointer points at a valid `struct seq_file`.
+    /// * The `struct seq_file` is not accessed from any other thread.
+    pub unsafe fn from_raw<'a>(ptr: *mut bindings::seq_file) -> &'a SeqFile {
+        // SAFETY: The caller ensures that the reference is valid for 'a. There's no way to trigger
+        // a data race by using the `&SeqFile` since this is the only thread accessing the seq_file.
+        //
+        // CAST: The layout of `struct seq_file` and `SeqFile` is compatible.
+        unsafe { &*ptr.cast() }
+    }
+
+    /// Used by the [`seq_print`] macro.
+    pub fn call_printf(&self, args: core::fmt::Arguments<'_>) {
+        // SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`.
+        unsafe {
+            bindings::seq_printf(
+                self.inner.get(),
+                c_str!("%pA").as_char_ptr(),
+                &args as *const _ as *const core::ffi::c_void,
+            );
+        }
+    }
+}
+
+/// Write to a [`SeqFile`] with the ordinary Rust formatting syntax.
+#[macro_export]
+macro_rules! seq_print {
+    ($m:expr, $($arg:tt)+) => (
+        $m.call_printf(format_args!($($arg)+))
+    );
+}
+pub use seq_print;

---
base-commit: e9980e40804730de33c1563d9ac74d5b51591ec0
change-id: 20241001-seqfile-91d2243b8e99

Best regards,
-- 
Alice Ryhl <aliceryhl@google.com>


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] rust: add seqfile abstraction
  2024-10-01  9:07 [PATCH] rust: add seqfile abstraction Alice Ryhl
@ 2024-10-01  9:10 ` Alice Ryhl
  2024-10-01 10:23 ` Christian Brauner
  1 sibling, 0 replies; 3+ messages in thread
From: Alice Ryhl @ 2024-10-01  9:10 UTC (permalink / raw)
  To: Christian Brauner, Alexander Viro, Miguel Ojeda, Andrew Morton
  Cc: Kees Cook, Andy Shevchenko, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, linux-kernel, linux-fsdevel, rust-for-linux

On Tue, Oct 1, 2024 at 11:07 AM Alice Ryhl <aliceryhl@google.com> wrote:
>
> This adds a simple seq file abstraction that lets you print to a seq
> file using ordinary Rust printing syntax.
>
> An example user from Rust Binder:
>
>     pub(crate) fn full_debug_print(
>         &self,
>         m: &SeqFile,
>         owner_inner: &mut ProcessInner,
>     ) -> Result<()> {
>         let prio = self.node_prio();
>         let inner = self.inner.access_mut(owner_inner);
>         seq_print!(
>             m,
>             "  node {}: u{:016x} c{:016x} pri {}:{} hs {} hw {} cs {} cw {}",
>             self.debug_id,
>             self.ptr,
>             self.cookie,
>             prio.sched_policy,
>             prio.prio,
>             inner.strong.has_count,
>             inner.weak.has_count,
>             inner.strong.count,
>             inner.weak.count,
>         );
>         if !inner.refs.is_empty() {
>             seq_print!(m, " proc");
>             for node_ref in &inner.refs {
>                 seq_print!(m, " {}", node_ref.process.task.pid());
>             }
>         }
>         seq_print!(m, "\n");
>         for t in &inner.oneway_todo {
>             t.debug_print_inner(m, "    pending async transaction ");
>         }
>         Ok(())
>     }
>
> The `SeqFile` type is marked not thread safe so that `call_printf` can
> be a `&self` method. The alternative is to use `self: Pin<&mut Self>`
> which is inconvenient, or to have `SeqFile` wrap a pointer instead of
> wrapping the C struct directly.
>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>

It's supposed to say this below the --- line:

This series is based on top of vfs.rust.file for the NotThreadSafe type.

I have no idea why b4 decided to drop this information ...

Alice

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] rust: add seqfile abstraction
  2024-10-01  9:07 [PATCH] rust: add seqfile abstraction Alice Ryhl
  2024-10-01  9:10 ` Alice Ryhl
@ 2024-10-01 10:23 ` Christian Brauner
  1 sibling, 0 replies; 3+ messages in thread
From: Christian Brauner @ 2024-10-01 10:23 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Christian Brauner, Kees Cook, Andy Shevchenko, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, linux-kernel, linux-fsdevel,
	rust-for-linux, Alexander Viro, Miguel Ojeda, Andrew Morton

On Tue, 01 Oct 2024 09:07:02 +0000, Alice Ryhl wrote:
> This adds a simple seq file abstraction that lets you print to a seq
> file using ordinary Rust printing syntax.
> 
> An example user from Rust Binder:
> 
>     pub(crate) fn full_debug_print(
>         &self,
>         m: &SeqFile,
>         owner_inner: &mut ProcessInner,
>     ) -> Result<()> {
>         let prio = self.node_prio();
>         let inner = self.inner.access_mut(owner_inner);
>         seq_print!(
>             m,
>             "  node {}: u{:016x} c{:016x} pri {}:{} hs {} hw {} cs {} cw {}",
>             self.debug_id,
>             self.ptr,
>             self.cookie,
>             prio.sched_policy,
>             prio.prio,
>             inner.strong.has_count,
>             inner.weak.has_count,
>             inner.strong.count,
>             inner.weak.count,
>         );
>         if !inner.refs.is_empty() {
>             seq_print!(m, " proc");
>             for node_ref in &inner.refs {
>                 seq_print!(m, " {}", node_ref.process.task.pid());
>             }
>         }
>         seq_print!(m, "\n");
>         for t in &inner.oneway_todo {
>             t.debug_print_inner(m, "    pending async transaction ");
>         }
>         Ok(())
>     }
> 
> [...]

Seems straightforward.

---

Applied to the vfs.rust.file branch of the vfs/vfs.git tree.
Patches in the vfs.rust.file branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.rust.file

[1/1] rust: add seqfile abstraction
      https://git.kernel.org/vfs/vfs/c/66423ace209c

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-10-01 10:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-01  9:07 [PATCH] rust: add seqfile abstraction Alice Ryhl
2024-10-01  9:10 ` Alice Ryhl
2024-10-01 10:23 ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).