All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Danilo Krummrich" <dakr@kernel.org>
To: "Gary Guo" <gary@garyguo.net>
Cc: <abdiel.janulgue@gmail.com>, <daniel.almeida@collabora.com>,
	<robin.murphy@arm.com>, <a.hindborg@kernel.org>,
	<gregkh@linuxfoundation.org>, <rafael@kernel.org>,
	<aliceryhl@google.com>, <acourbot@nvidia.com>, <ojeda@kernel.org>,
	<boqun@kernel.org>, <bjorn3_gh@protonmail.com>,
	<lossin@kernel.org>, <tmgross@umich.edu>, <tamird@kernel.org>,
	<work@onurozkan.dev>, <mmaurer@google.com>,
	<driver-core@lists.linux.dev>, <nova-gpu@lists.linux.dev>,
	<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>,
	<rust-for-linux@vger.kernel.org>
Subject: Re: [PATCH 1/4] rust: debugfs: drop 'static bound from ScopedDir file creation methods
Date: Thu, 03 Sep 2026 17:07:55 +0200	[thread overview]
Message-ID: <DL5RXJCC43FY.CACM7A2UNBCI@kernel.org> (raw)
In-Reply-To: <DL5PH2S8AP7E.25CW1PZIQ8BM3@garyguo.net>

On Thu Sep 3, 2026 at 3:12 PM CEST, Gary Guo wrote:
> This can be better done by storing `&'static bindings::file_operations` in
> `FileOps<T>` instead of just by value. That is actually better than the current
> impl, IMO, because `mode` for example doesn't have to be in static storage. (You
> can also then make `FileOps<T>` `Copy`).

That's a great suggestion, thanks. It simplifies the patch to:

Author: Danilo Krummrich <dakr@kernel.org>
Date:   Sat Aug 29 14:42:54 2026 +0200

    rust: debugfs: drop 'static bound from ScopedDir file creation methods

    Drop the T: 'static bound from ScopedDir's file creation methods
    (read_binary_file(), read_only_file(), etc.) to support registering
    debugfs files backed by types that contain non-'static references, such
    as dma::Coherent<'a, T>.

    The previous 'static bound existed because ScopedDir::create_file() took
    &'static FileOps<T>, and &'static requires T: 'static for well-
    formedness. However, this was overly conservative: the file_operations
    pointer passed to the C debugfs API just needs to be 'static, not the
    entire FileOps<T>.

    Store &'static bindings::file_operations in FileOps<T> instead of the
    file_operations by value. In each trait impl, take a reference to the
    file_operations struct within the const block; since
    bindings::file_operations does not mention T, the reference is promoted
    to 'static regardless of T's lifetime parameters.

    Replace the Deref impl with an explicit fops() method that returns the
    stored &'static reference.

    Signed-off-by: Danilo Krummrich <dakr@kernel.org>

diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs
index d7b8014a6474..2beb55d444ca 100644
--- a/rust/kernel/debugfs.rs
+++ b/rust/kernel/debugfs.rs
@@ -538,7 +538,7 @@ pub fn dir<'dir2>(&'dir2 self, name: &CStr) -> ScopedDir<'data, 'dir2> {
         }
     }

-    fn create_file<T: Sync>(&self, name: &CStr, data: &'data T, vtable: &'static FileOps<T>) {
+    fn create_file<T: Sync>(&self, name: &CStr, data: &'data T, vtable: &FileOps<T>) {
         #[cfg(CONFIG_DEBUG_FS)]
         core::mem::forget(Entry::file(name, &self.entry, data, vtable));
     }
@@ -550,7 +550,7 @@ fn create_file<T: Sync>(&self, name: &CStr, data: &'data T, vtable: &'static Fil
     /// This function does not produce an owning handle to the file. The created
     /// file is removed when the [`Scope`] that this directory belongs
     /// to is dropped.
-    pub fn read_only_file<T: Writer + Send + Sync + 'static>(&self, name: &CStr, data: &'data T) {
+    pub fn read_only_file<T: Writer + Send + Sync>(&self, name: &CStr, data: &'data T) {
         self.create_file(name, data, &T::FILE_OPS)
     }

@@ -560,11 +560,7 @@ pub fn read_only_file<T: Writer + Send + Sync + 'static>(&self, name: &CStr, dat
     ///
     /// This function does not produce an owning handle to the file. The created file is removed
     /// when the [`Scope`] that this directory belongs to is dropped.
-    pub fn read_binary_file<T: BinaryWriter + Send + Sync + 'static>(
-        &self,
-        name: &CStr,
-        data: &'data T,
-    ) {
+    pub fn read_binary_file<T: BinaryWriter + Send + Sync>(&self, name: &CStr, data: &'data T) {
         self.create_file(name, data, &T::FILE_OPS)
     }

@@ -596,11 +592,7 @@ pub fn read_callback_file<T, F>(&self, name: &CStr, data: &'data T, _f: &'static
     /// This function does not produce an owning handle to the file. The created
     /// file is removed when the [`Scope`] that this directory belongs
     /// to is dropped.
-    pub fn read_write_file<T: Writer + Reader + Send + Sync + 'static>(
-        &self,
-        name: &CStr,
-        data: &'data T,
-    ) {
+    pub fn read_write_file<T: Writer + Reader + Send + Sync>(&self, name: &CStr, data: &'data T) {
         let vtable = &<T as ReadWriteFile<_>>::FILE_OPS;
         self.create_file(name, data, vtable)
     }
@@ -612,7 +604,7 @@ pub fn read_write_file<T: Writer + Reader + Send + Sync + 'static>(
     ///
     /// This function does not produce an owning handle to the file. The created file is removed
     /// when the [`Scope`] that this directory belongs to is dropped.
-    pub fn read_write_binary_file<T: BinaryWriter + BinaryReader + Send + Sync + 'static>(
+    pub fn read_write_binary_file<T: BinaryWriter + BinaryReader + Send + Sync>(
         &self,
         name: &CStr,
         data: &'data T,
@@ -655,7 +647,7 @@ pub fn read_write_callback_file<T, F, W>(
     /// This function does not produce an owning handle to the file. The created
     /// file is removed when the [`Scope`] that this directory belongs
     /// to is dropped.
-    pub fn write_only_file<T: Reader + Send + Sync + 'static>(&self, name: &CStr, data: &'data T) {
+    pub fn write_only_file<T: Reader + Send + Sync>(&self, name: &CStr, data: &'data T) {
         let vtable = &<T as WriteFile<_>>::FILE_OPS;
         self.create_file(name, data, vtable)
     }
@@ -666,11 +658,7 @@ pub fn write_only_file<T: Reader + Send + Sync + 'static>(&self, name: &CStr, da
     ///
     /// This function does not produce an owning handle to the file. The created file is removed
     /// when the [`Scope`] that this directory belongs to is dropped.
-    pub fn write_binary_file<T: BinaryReader + Send + Sync + 'static>(
-        &self,
-        name: &CStr,
-        data: &'data T,
-    ) {
+    pub fn write_binary_file<T: BinaryReader + Send + Sync>(&self, name: &CStr, data: &'data T) {
         self.create_file(name, data, &T::FILE_OPS)
     }

diff --git a/rust/kernel/debugfs/entry.rs b/rust/kernel/debugfs/entry.rs
index 46aad64896ec..88a870d8c295 100644
--- a/rust/kernel/debugfs/entry.rs
+++ b/rust/kernel/debugfs/entry.rs
@@ -74,7 +74,7 @@ pub(crate) unsafe fn dynamic_file<T>(
                 parent.as_ptr(),
                 core::ptr::from_ref(data) as *mut c_void,
                 core::ptr::null(),
-                &**file_ops,
+                file_ops.fops(),
             )
         };

@@ -127,7 +127,7 @@ pub(crate) fn file<T>(
                 parent.as_ptr(),
                 core::ptr::from_ref(data) as *mut c_void,
                 core::ptr::null(),
-                &**file_ops,
+                file_ops.fops(),
             )
         };

diff --git a/rust/kernel/debugfs/file_ops.rs b/rust/kernel/debugfs/file_ops.rs
index f15908f71c4a..5c16a3196ca2 100644
--- a/rust/kernel/debugfs/file_ops.rs
+++ b/rust/kernel/debugfs/file_ops.rs
@@ -20,9 +20,6 @@

 use core::marker::PhantomData;

-#[cfg(CONFIG_DEBUG_FS)]
-use core::ops::Deref;
-
 /// # Invariant
 ///
 /// `FileOps<T>` will always contain an `operations` which is safe to use for a file backed
@@ -30,7 +27,7 @@
 /// into a reference.
 pub(super) struct FileOps<T> {
     #[cfg(CONFIG_DEBUG_FS)]
-    operations: bindings::file_operations,
+    operations: &'static bindings::file_operations,
     #[cfg(CONFIG_DEBUG_FS)]
     mode: u16,
     _phantom: PhantomData<T>,
@@ -41,7 +38,7 @@ impl<T> FileOps<T> {
     ///
     /// The caller asserts that the provided `operations` is safe to use for a file whose
     /// inode has a pointer to `T` in its private data that is safe to convert into a reference.
-    const unsafe fn new(operations: bindings::file_operations, mode: u16) -> Self {
+    const unsafe fn new(operations: &'static bindings::file_operations, mode: u16) -> Self {
         Self {
             #[cfg(CONFIG_DEBUG_FS)]
             operations,
@@ -65,11 +62,11 @@ pub(super) const fn adapt(&self) -> &FileOps<T::Inner> {
 }

 #[cfg(CONFIG_DEBUG_FS)]
-impl<T> Deref for FileOps<T> {
-    type Target = bindings::file_operations;
-
-    fn deref(&self) -> &Self::Target {
-        &self.operations
+impl<T> FileOps<T> {
+    /// Returns a `'static` reference to the inner `file_operations`.
+    #[inline]
+    pub(crate) fn fops(&self) -> &'static bindings::file_operations {
+        self.operations
     }
 }

@@ -130,11 +127,11 @@ pub(crate) trait ReadFile<T> {

 impl<T: Writer + Sync> ReadFile<T> for T {
     const FILE_OPS: FileOps<T> = {
-        let operations = bindings::file_operations {
+        let operations = &bindings::file_operations {
             read: Some(bindings::seq_read),
             llseek: Some(bindings::seq_lseek),
             release: Some(bindings::single_release),
-            open: Some(writer_open::<Self>),
+            open: Some(writer_open::<T>),
             ..pin_init::zeroed()
         };
         // SAFETY: `operations` is all stock `seq_file` implementations except for `writer_open`.
@@ -181,7 +178,7 @@ pub(crate) trait ReadWriteFile<T> {

 impl<T: Writer + Reader + Sync> ReadWriteFile<T> for T {
     const FILE_OPS: FileOps<T> = {
-        let operations = bindings::file_operations {
+        let operations = &bindings::file_operations {
             open: Some(writer_open::<T>),
             read: Some(bindings::seq_read),
             write: Some(write::<T>),
@@ -238,7 +235,7 @@ pub(crate) trait WriteFile<T> {

 impl<T: Reader + Sync> WriteFile<T> for T {
     const FILE_OPS: FileOps<T> = {
-        let operations = bindings::file_operations {
+        let operations = &bindings::file_operations {
             open: Some(write_only_open),
             write: Some(write_only_write::<T>),
             llseek: Some(bindings::noop_llseek),
@@ -290,7 +287,7 @@ pub(crate) trait BinaryReadFile<T> {

 impl<T: BinaryWriter + Sync> BinaryReadFile<T> for T {
     const FILE_OPS: FileOps<T> = {
-        let operations = bindings::file_operations {
+        let operations = &bindings::file_operations {
             read: Some(blob_read::<T>),
             llseek: Some(bindings::default_llseek),
             open: Some(bindings::simple_open),
@@ -344,7 +341,7 @@ pub(crate) trait BinaryWriteFile<T> {

 impl<T: BinaryReader + Sync> BinaryWriteFile<T> for T {
     const FILE_OPS: FileOps<T> = {
-        let operations = bindings::file_operations {
+        let operations = &bindings::file_operations {
             write: Some(blob_write::<T>),
             llseek: Some(bindings::default_llseek),
             open: Some(bindings::simple_open),
@@ -368,7 +365,7 @@ pub(crate) trait BinaryReadWriteFile<T> {

 impl<T: BinaryWriter + BinaryReader + Sync> BinaryReadWriteFile<T> for T {
     const FILE_OPS: FileOps<T> = {
-        let operations = bindings::file_operations {
+        let operations = &bindings::file_operations {
             read: Some(blob_read::<T>),
             write: Some(blob_write::<T>),
             llseek: Some(bindings::default_llseek),

  reply	other threads:[~2026-09-03 15:08 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-30 19:37 [PATCH 0/4] rust: dma: tie DMA allocations to the device's bound lifetime Danilo Krummrich
2026-08-30 19:37 ` [PATCH 1/4] rust: debugfs: drop 'static bound from ScopedDir file creation methods Danilo Krummrich
2026-08-30 19:53   ` sashiko-bot
2026-09-03 13:12   ` Gary Guo
2026-09-03 15:07     ` Danilo Krummrich [this message]
2026-09-03 15:16       ` Gary Guo
2026-08-30 19:37 ` [PATCH 2/4] rust: dma: tie CoherentHandle to the device's bound lifetime Danilo Krummrich
2026-09-03 13:12   ` Gary Guo
2026-08-30 19:37 ` [PATCH 3/4] samples: rust_dma: separate driver type from driver data Danilo Krummrich
2026-08-30 19:57   ` sashiko-bot
2026-09-03 13:13   ` Gary Guo
2026-08-30 19:37 ` [PATCH 4/4] rust: dma: tie Coherent and CoherentBox to the device's bound lifetime Danilo Krummrich
2026-08-30 19:47   ` sashiko-bot
2026-09-03 13:20   ` Gary Guo
2026-09-03 15:22     ` Danilo Krummrich
2026-09-03 15:42       ` Gary Guo
2026-09-06 15:37 ` [PATCH 0/4] rust: dma: tie DMA allocations " Danilo Krummrich
2026-09-07 21:06   ` Danilo Krummrich

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=DL5RXJCC43FY.CACM7A2UNBCI@kernel.org \
    --to=dakr@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=abdiel.janulgue@gmail.com \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=driver-core@lists.linux.dev \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=mmaurer@google.com \
    --cc=nova-gpu@lists.linux.dev \
    --cc=ojeda@kernel.org \
    --cc=rafael@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    /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.