Create the 'nova_core' root debugfs entry when the driver loads. The Dir entry is part of the NovaCoreModule, so when the module unloads, the NovaCoreModule object is dropped, and that drops the _debugfs_root, which automatically deletes the debugfs file.
Field order in Rust structs determines drop order - fields are dropped in declaration order. By placing _driver before _debugfs_root: 1. The driver registration is dropped first, which removes all PCI devices and their associated debugfs subdirectories 2. Then _debugfs_root is dropped, removing the now-empty nova_core directory This ordering is critical because debugfs_remove() performs recursive removal. If the parent directory were removed first, it would free the child dentries, and then the child's drop would attempt to remove an already-freed dentry, causing a use-after-free crash. Signed-off-by: Timur Tabi <[email protected]> --- drivers/gpu/nova-core/nova_core.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs index 01353be103ca..f17505e5e2b3 100644 --- a/drivers/gpu/nova-core/nova_core.rs +++ b/drivers/gpu/nova-core/nova_core.rs @@ -2,8 +2,7 @@ //! Nova Core GPU Driver -use kernel::{error::Error, pci, prelude::*, InPlaceModule}; -use pin_init::{PinInit, pinned_drop}; +use kernel::{debugfs::Dir, error::Error, pci, prelude::*, InPlaceModule}; #[macro_use] mod bitfield; @@ -24,17 +23,24 @@ pub(crate) const MODULE_NAME: &kernel::str::CStr = <LocalModule as kernel::ModuleMetadata>::NAME; -#[pin_data(PinnedDrop)] +#[pin_data] struct NovaCoreModule { + // Note: field order matters for drop order. The driver must be dropped before + // the debugfs directory so that device subdirectories are removed first. #[pin] _driver: kernel::driver::Registration<pci::Adapter<driver::NovaCore>>, + _debugfs_root: Dir, } impl InPlaceModule for NovaCoreModule { fn init(module: &'static kernel::ThisModule) -> impl PinInit<Self, Error> { pr_info!("NovaCore GPU driver loaded\n"); + + let debugfs_root = Dir::new(kernel::c_str!("nova_core")); + try_pin_init!(Self { _driver <- kernel::driver::Registration::new(MODULE_NAME, module), + _debugfs_root: debugfs_root, }) } } -- 2.52.0
