debugfs Linux Kernel Tutorial: The Right Way to Expose Driver Debug Data
Free Linux Kernel Development Course • Free Linux Device Drivers Course
What You Will Learn
- Why debugfs exists alongside sysfs instead of replacing it
- How to create debugfs files for integers, booleans, and custom data
- Why debugfs is never treated as a stable user-space ABI
- How to safely check whether debugfs failed to mount, without crashing your driver
CONFIG_DEBUG_FS enabled in your kernel configuration.
What Is debugfs and Why Does It Exist?
sysfs enforces a strict, stable, one-value-per-file convention because user-space tools depend on it and the kernel promises never to break that contract. That discipline is exactly what makes sysfs unsuitable for quick debug dumps: a developer bringing up new hardware wants to print register contents, ring buffer state, or driver-internal counters without worrying about ABI stability. debugfs, usually mounted at /sys/kernel/debug, fills that gap. Anything under debugfs can change shape or disappear between kernel versions without any deprecation process, because it is explicitly documented as a debug-only interface, never a stable API.
| sysfs Stable ABI |
←→ | procfs Mostly legacy |
←→ | debugfs No ABI guarantee |
Creating Debug Files
For the common cases of exposing a simple integer or boolean, debugfs ships ready-made helpers so you rarely need to write your own file operations:
#include <linux/debugfs.h>
static struct dentry *mydriver_debug_dir;
static u32 error_count;
static bool tracing_enabled;
static int __init my_init(void)
{
mydriver_debug_dir = debugfs_create_dir("mydriver", NULL);
if (IS_ERR(mydriver_debug_dir))
return PTR_ERR(mydriver_debug_dir);
debugfs_create_u32("error_count", 0644, mydriver_debug_dir, &error_count);
debugfs_create_bool("tracing_enabled", 0644, mydriver_debug_dir, &tracing_enabled);
return 0;
}
static void __exit my_exit(void)
{
debugfs_remove_recursive(mydriver_debug_dir);
}
For custom formatted output, such as dumping a whole ring buffer, use debugfs_create_file() with your own file_operations, or the simpler DEFINE_SHOW_ATTRIBUTE macro paired with debugfs_create_file() when a seq_file-style show function is enough.
static int stats_show(struct seq_file *m, void *v)
{
seq_printf(m, "errors: %u\n", error_count);
seq_printf(m, "tracing: %s\n", tracing_enabled ? "on" : "off");
return 0;
}
DEFINE_SHOW_ATTRIBUTE(stats);
/* inside init: */
debugfs_create_file("stats", 0444, mydriver_debug_dir, NULL, &stats_fops);
Handling a Disabled debugfs Gracefully
A production kernel may ship with CONFIG_DEBUG_FS turned off entirely. In that case debugfs calls return an error pointer rather than crashing, so your driver must never treat debugfs failures as fatal. The correct pattern is to check the return value, log a warning if you want, and continue loading the driver normally, since debug output is a convenience, not a requirement for correct operation.
Common Mistakes
- Treating a debugfs file as a stable interface that other programs depend on, which breaks the moment the kernel changes it.
- Failing to check for an error pointer from
debugfs_create_dir()whenCONFIG_DEBUG_FSis disabled, causing an unnecessary driver load failure. - Forgetting
debugfs_remove_recursive()in the exit path, leaving orphaned debug entries behind. - Exposing sensitive hardware registers writable to any user without restricting the mount permissions of
/sys/kernel/debug.
Security Considerations
Because debugfs can expose raw internal state, most distributions restrict /sys/kernel/debug to the root user by default. Never assume an unprivileged process can read your debug files, and never rely on debugfs to pass security-sensitive data that regular users should not see.
FAQ
Q1: Is debugfs safe to use in a production driver?
Yes for debug and diagnostics, but never as the primary interface user-space applications depend on, since its layout can change without notice.
Q2: What happens if CONFIG_DEBUG_FS is disabled?
debugfs calls return error pointers instead of valid dentries; a well-written driver checks for this and continues without debug output.
Q3: Where is debugfs normally mounted?
Typically at /sys/kernel/debug, though it is a separate filesystem type from sysfs even though the path sits under /sys.
Q4: Can debugfs replace sysfs entirely?
No, they serve different purposes: sysfs is stable and ABI-bound, debugfs is unstable and debug-only.
Q5: Do I need root access to read debugfs files?
Usually yes, because most distributions mount /sys/kernel/debug as root-only by default.

2 Comments