1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2025 Google LLC. 3 4 //! DebugFS Abstraction 5 //! 6 //! C header: [`include/linux/debugfs.h`](srctree/include/linux/debugfs.h) 7 8 // When DebugFS is disabled, many parameters are dead. Linting for this isn't helpful. 9 #![cfg_attr(not(CONFIG_DEBUG_FS), allow(unused_variables))] 10 11 #[cfg(CONFIG_DEBUG_FS)] 12 use crate::prelude::*; 13 use crate::str::CStr; 14 #[cfg(CONFIG_DEBUG_FS)] 15 use crate::sync::Arc; 16 17 #[cfg(CONFIG_DEBUG_FS)] 18 mod entry; 19 #[cfg(CONFIG_DEBUG_FS)] 20 use entry::Entry; 21 22 /// Owning handle to a DebugFS directory. 23 /// 24 /// The directory in the filesystem represented by [`Dir`] will be removed when handle has been 25 /// dropped *and* all children have been removed. 26 // If we have a parent, we hold a reference to it in the `Entry`. This prevents the `dentry` 27 // we point to from being cleaned up if our parent `Dir`/`Entry` is dropped before us. 28 // 29 // The `None` option indicates that the `Arc` could not be allocated, so our children would not be 30 // able to refer to us. In this case, we need to silently fail. All future child directories/files 31 // will silently fail as well. 32 #[derive(Clone)] 33 pub struct Dir(#[cfg(CONFIG_DEBUG_FS)] Option<Arc<Entry>>); 34 35 impl Dir { 36 /// Create a new directory in DebugFS. If `parent` is [`None`], it will be created at the root. 37 fn create(name: &CStr, parent: Option<&Dir>) -> Self { 38 #[cfg(CONFIG_DEBUG_FS)] 39 { 40 let parent_entry = match parent { 41 // If the parent couldn't be allocated, just early-return 42 Some(Dir(None)) => return Self(None), 43 Some(Dir(Some(entry))) => Some(entry.clone()), 44 None => None, 45 }; 46 Self( 47 // If Arc creation fails, the `Entry` will be dropped, so the directory will be 48 // cleaned up. 49 Arc::new(Entry::dynamic_dir(name, parent_entry), GFP_KERNEL).ok(), 50 ) 51 } 52 #[cfg(not(CONFIG_DEBUG_FS))] 53 Self() 54 } 55 56 /// Create a new directory in DebugFS at the root. 57 /// 58 /// # Examples 59 /// 60 /// ``` 61 /// # use kernel::c_str; 62 /// # use kernel::debugfs::Dir; 63 /// let debugfs = Dir::new(c_str!("parent")); 64 /// ``` 65 pub fn new(name: &CStr) -> Self { 66 Dir::create(name, None) 67 } 68 69 /// Creates a subdirectory within this directory. 70 /// 71 /// # Examples 72 /// 73 /// ``` 74 /// # use kernel::c_str; 75 /// # use kernel::debugfs::Dir; 76 /// let parent = Dir::new(c_str!("parent")); 77 /// let child = parent.subdir(c_str!("child")); 78 /// ``` 79 pub fn subdir(&self, name: &CStr) -> Self { 80 Dir::create(name, Some(self)) 81 } 82 } 83