From 9dc6cedcd971d084a64a9bd11d9c822e1125b798 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Sat, 29 Aug 2026 14:42:54 +0200 Subject: [PATCH] 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, 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. Store &'static bindings::file_operations in FileOps 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. Link: https://lore.kernel.org/driver-core/20260830193824.471089-2-dakr@kernel.org Reviewed-by: Gary Guo Link: https://patch.msgid.link/20260830193824.471089-2-dakr@kernel.org [ Remove unrelated change from Self to T. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/debugfs.rs | 26 +++++++------------------- rust/kernel/debugfs/entry.rs | 4 ++-- rust/kernel/debugfs/file_ops.rs | 29 +++++++++++++---------------- 3 files changed, 22 insertions(+), 37 deletions(-) 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(&self, name: &CStr, data: &'data T, vtable: &'static FileOps) { + fn create_file(&self, name: &CStr, data: &'data T, vtable: &FileOps) { #[cfg(CONFIG_DEBUG_FS)] core::mem::forget(Entry::file(name, &self.entry, data, vtable)); } @@ -550,7 +550,7 @@ fn create_file(&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(&self, name: &CStr, data: &'data T) { + pub fn read_only_file(&self, name: &CStr, data: &'data T) { self.create_file(name, data, &T::FILE_OPS) } @@ -560,11 +560,7 @@ pub fn read_only_file(&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( - &self, - name: &CStr, - data: &'data T, - ) { + pub fn read_binary_file(&self, name: &CStr, data: &'data T) { self.create_file(name, data, &T::FILE_OPS) } @@ -596,11 +592,7 @@ pub fn read_callback_file(&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( - &self, - name: &CStr, - data: &'data T, - ) { + pub fn read_write_file(&self, name: &CStr, data: &'data T) { let vtable = &>::FILE_OPS; self.create_file(name, data, vtable) } @@ -612,7 +604,7 @@ pub fn read_write_file( /// /// 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( + pub fn read_write_binary_file( &self, name: &CStr, data: &'data T, @@ -655,7 +647,7 @@ pub fn read_write_callback_file( /// 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(&self, name: &CStr, data: &'data T) { + pub fn write_only_file(&self, name: &CStr, data: &'data T) { let vtable = &>::FILE_OPS; self.create_file(name, data, vtable) } @@ -666,11 +658,7 @@ pub fn write_only_file(&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( - &self, - name: &CStr, - data: &'data T, - ) { + pub fn write_binary_file(&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( 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( 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..47acc4851d47 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` 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 { #[cfg(CONFIG_DEBUG_FS)] - operations: bindings::file_operations, + operations: &'static bindings::file_operations, #[cfg(CONFIG_DEBUG_FS)] mode: u16, _phantom: PhantomData, @@ -41,7 +38,7 @@ impl FileOps { /// /// 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 { } #[cfg(CONFIG_DEBUG_FS)] -impl Deref for FileOps { - type Target = bindings::file_operations; - - fn deref(&self) -> &Self::Target { - &self.operations +impl FileOps { + /// Returns a `'static` reference to the inner `file_operations`. + #[inline] + pub(crate) fn fops(&self) -> &'static bindings::file_operations { + self.operations } } @@ -130,7 +127,7 @@ pub(crate) trait ReadFile { impl ReadFile for T { const FILE_OPS: FileOps = { - 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), @@ -181,7 +178,7 @@ pub(crate) trait ReadWriteFile { impl ReadWriteFile for T { const FILE_OPS: FileOps = { - let operations = bindings::file_operations { + let operations = &bindings::file_operations { open: Some(writer_open::), read: Some(bindings::seq_read), write: Some(write::), @@ -238,7 +235,7 @@ pub(crate) trait WriteFile { impl WriteFile for T { const FILE_OPS: FileOps = { - let operations = bindings::file_operations { + let operations = &bindings::file_operations { open: Some(write_only_open), write: Some(write_only_write::), llseek: Some(bindings::noop_llseek), @@ -290,7 +287,7 @@ pub(crate) trait BinaryReadFile { impl BinaryReadFile for T { const FILE_OPS: FileOps = { - let operations = bindings::file_operations { + let operations = &bindings::file_operations { read: Some(blob_read::), llseek: Some(bindings::default_llseek), open: Some(bindings::simple_open), @@ -344,7 +341,7 @@ pub(crate) trait BinaryWriteFile { impl BinaryWriteFile for T { const FILE_OPS: FileOps = { - let operations = bindings::file_operations { + let operations = &bindings::file_operations { write: Some(blob_write::), llseek: Some(bindings::default_llseek), open: Some(bindings::simple_open), @@ -368,7 +365,7 @@ pub(crate) trait BinaryReadWriteFile { impl BinaryReadWriteFile for T { const FILE_OPS: FileOps = { - let operations = bindings::file_operations { + let operations = &bindings::file_operations { read: Some(blob_read::), write: Some(blob_write::), llseek: Some(bindings::default_llseek),