Dir::scope() was declared as taking &'a self, which tied the returned
PinInit's lifetime to the Dir. This prevented using scope() with a
locally-created Dir:
let dir = Dir::lookup(...).unwrap_or_else(Dir::empty);
let scope = dir.scope(...); // Error: returns value referencing local
The borrow was unnecessary since scoped_dir() internally clones the
Arc<Entry>. Fix this by cloning self.0 before the closure, allowing the
closure to capture the cloned value via move instead of borrowing self.
This also removes the now-unused scoped_dir() helper method, inlining
its logic directly into scope().
Signed-off-by: Timur Tabi <[email protected]>
---
rust/kernel/debugfs.rs | 41 +++++++++++++++++------------------------
1 file changed, 17 insertions(+), 24 deletions(-)
diff --git a/rust/kernel/debugfs.rs b/rust/kernel/debugfs.rs
index b0cfe22982d6..35f9cbb261e7 100644
--- a/rust/kernel/debugfs.rs
+++ b/rust/kernel/debugfs.rs
@@ -397,27 +397,6 @@ pub fn write_callback_file<'a, T, E: 'a, W>(
self.create_file(name, data, file_ops)
}
- // While this function is safe, it is intentionally not public because
it's a bit of a
- // footgun.
- //
- // Unless you also extract the `entry` later and schedule it for `Drop` at
the appropriate
- // time, a `ScopedDir` with a `Dir` parent will never be deleted.
- fn scoped_dir<'data>(&self, name: &CStr) -> ScopedDir<'data, 'static> {
- #[cfg(CONFIG_DEBUG_FS)]
- {
- let parent_entry = match &self.0 {
- None => return ScopedDir::empty(),
- Some(entry) => entry.clone(),
- };
- ScopedDir {
- entry: ManuallyDrop::new(Entry::dynamic_dir(name,
Some(parent_entry))),
- _phantom: PhantomData,
- }
- }
- #[cfg(not(CONFIG_DEBUG_FS))]
- ScopedDir::empty()
- }
-
/// Creates a new scope, which is a directory associated with some data
`T`.
///
/// The created directory will be a subdirectory of `self`. The `init`
closure is called to
@@ -427,7 +406,7 @@ fn scoped_dir<'data>(&self, name: &CStr) ->
ScopedDir<'data, 'static> {
/// The entire directory tree created within the scope will be removed
when the returned
/// `Scope` handle is dropped.
pub fn scope<'a, T: 'a, E: 'a, F>(
- &'a self,
+ &self,
data: impl PinInit<T, E> + 'a,
name: &'a CStr,
init: F,
@@ -435,8 +414,22 @@ pub fn scope<'a, T: 'a, E: 'a, F>(
where
F: for<'data, 'dir> FnOnce(&'data T, &'dir ScopedDir<'data, 'dir>) +
'a,
{
- Scope::new(data, |data| {
- let scoped = self.scoped_dir(name);
+ // Clone the parent entry so the closure doesn't need to borrow `self`.
+ #[cfg(CONFIG_DEBUG_FS)]
+ let parent_entry = self.0.clone();
+
+ Scope::new(data, move |data| {
+ #[cfg(CONFIG_DEBUG_FS)]
+ let scoped = match parent_entry {
+ None => ScopedDir::empty(),
+ Some(entry) => ScopedDir {
+ entry: ManuallyDrop::new(Entry::dynamic_dir(name,
Some(entry))),
+ _phantom: PhantomData,
+ },
+ };
+ #[cfg(not(CONFIG_DEBUG_FS))]
+ let scoped = ScopedDir::empty();
+
init(data, &scoped);
scoped.into_entry()
})
--
2.52.0