On Thu Dec 18, 2025 at 2:39 AM CET, Timur Tabi wrote:
> 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};

Again, please use kernel vertical style.

>  
>  #[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.

This is not correct, subdirectories have a reference count of their parent
directory. Hence, the drop order does not matter.

>      #[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"));

I'd just inline this statement below.

> +
>          try_pin_init!(Self {
>              _driver <- kernel::driver::Registration::new(MODULE_NAME, 
> module),
> +            _debugfs_root: debugfs_root,
>          })
>      }
>  }
> -- 
> 2.52.0

Reply via email to