From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C135E4A3877; Thu, 3 Sep 2026 15:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788448082; cv=none; b=byl2MTP+W4kgy6ismZySrW3DMldkYNPYmzTNCpAFa4qm2LNfghCt7YHAuwgSIHGLGqPzsiH8dORPVbzNCemW4YKeowU5+n9u65Jv7Q96xrAm3eT6FthEIKHnYx9yIYL2fNnZVZ4d1hn7qJopJnNI9r8fxAxf1Sqa+cIpb/gXojE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788448082; c=relaxed/simple; bh=2PuFcsWylNH31snrVJJoReAm/Nn0OKsJychGKCVWiQ8=; h=Mime-Version:Content-Type:Date:Message-Id:Subject:Cc:To:From: References:In-Reply-To; b=oTb9Vmtq7aW/cys99BfCdZHwUGmvbejVRkQi6sib/dJMZr4r28b+E1y1/3AmViVHWCImQaGLN2yIOCwuf73kM9YkYohVNEZOplL6tzkHfvtu1Io426avYjYiS0OWc3pKtG0tM42ZMCgufaCGU3wU6WgEqLIUgbF4eIXgu64bTMI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GwobO+Us; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GwobO+Us" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 953AA1F00A3A; Thu, 3 Sep 2026 15:07:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788448080; bh=4qmYNKLvmK56Y3vExZhL5LncOr+j7eNZrKKmYJsXYNE=; h=Date:Subject:Cc:To:From:References:In-Reply-To; b=GwobO+UsGz08X5+CX/F/wgchM6dWjckrK7hRPiukogUSoSOraKrwEQ023cSteyd15 uGLnrA8WETQlR+nrq6PD2oVwUadiUfNb1gdmgpvNAtTKjweXNhKEtAiLN1etIMGsBa 0iiPjXXslAV0gGRb0xXiau9pCUVVHDUpLKl8XRmjNHHtowSwcxrURwoehCWUj3035y vp643ZLZZcIVJcGSOZNHSa9hrzP4PQQ7piqzHSyzNkSwUPMxKu241C6JiX/Ec0vZMX QDmVkZFbWhmFjahUmSfPEb7UzStGl+jBELTX6MbbymVdVPhtHh74Jz+i70IiIqIFiz NGcrgShWLLf5A== Precedence: bulk X-Mailing-List: rust-for-linux@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8 Date: Thu, 03 Sep 2026 17:07:55 +0200 Message-Id: Subject: Re: [PATCH 1/4] rust: debugfs: drop 'static bound from ScopedDir file creation methods Cc: , , , , , , , , , , , , , , , , , , , , To: "Gary Guo" From: "Danilo Krummrich" References: <20260830193824.471089-1-dakr@kernel.org> <20260830193824.471089-2-dakr@kernel.org> In-Reply-To: On Thu Sep 3, 2026 at 3:12 PM CEST, Gary Guo wrote: > This can be better done by storing `&'static bindings::file_operations` i= n > `FileOps` instead of just by value. That is actually better than the c= urrent > impl, IMO, because `mode` for example doesn't have to be in static storag= e. (You > can also then make `FileOps` `Copy`). That's a great suggestion, thanks. It simplifies the patch to: Author: Danilo Krummrich 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() too= k &'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. Signed-off-by: Danilo Krummrich 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) -> ScopedDi= r<'data, 'dir2> { } } - fn create_file(&self, name: &CStr, data: &'data T, vtable: &'= static FileOps) { + fn create_file(&self, name: &CStr, data: &'data T, vtable: &F= ileOps) { #[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: &'dat= a T, vtable: &'static Fil /// This function does not produce an owning handle to the file. The c= reated /// 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, dat= a: &'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 c= reated 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: &C= Str, data: &'data T) { self.create_file(name, data, &T::FILE_OPS) } @@ -596,11 +592,7 @@ pub fn read_callback_file(&self, name: &CStr, da= ta: &'data T, _f: &'static /// This function does not produce an owning handle to the file. The c= reated /// 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 =3D &>::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 c= reated 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 c= reated /// 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, da= ta: &'data T) { let vtable =3D &>::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 c= reated 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..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` 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 f= or a file whose /// inode has a pointer to `T` in its private data that is safe to con= vert into a reference. - const unsafe fn new(operations: bindings::file_operations, mode: u16) = -> Self { + const unsafe fn new(operations: &'static bindings::file_operations, mo= de: 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 =3D 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,11 +127,11 @@ pub(crate) trait ReadFile { impl ReadFile for T { const FILE_OPS: FileOps =3D { - let operations =3D bindings::file_operations { + let operations =3D &bindings::file_operations { read: Some(bindings::seq_read), llseek: Some(bindings::seq_lseek), release: Some(bindings::single_release), - open: Some(writer_open::), + open: Some(writer_open::), ..pin_init::zeroed() }; // SAFETY: `operations` is all stock `seq_file` implementations ex= cept for `writer_open`. @@ -181,7 +178,7 @@ pub(crate) trait ReadWriteFile { impl ReadWriteFile for T { const FILE_OPS: FileOps =3D { - let operations =3D bindings::file_operations { + let operations =3D &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 =3D { - let operations =3D bindings::file_operations { + let operations =3D &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 =3D { - let operations =3D bindings::file_operations { + let operations =3D &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 =3D { - let operations =3D bindings::file_operations { + let operations =3D &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 =3D { - let operations =3D bindings::file_operations { + let operations =3D &bindings::file_operations { read: Some(blob_read::), write: Some(blob_write::), llseek: Some(bindings::default_llseek),