Every free Linux kernel development course eventually reaches the question: how do driver authors expose rich debug information without breaking the stable sysfs ABI? The answer is debugfs. This lesson is part of our free Linux device drivers course and free embedded systems course track, and walks you through debugfs on a current 6.x kernel.
What You Will Learn
- What debugfs is and why it exists
- How debugfs differs from sysfs and procfs
- How to check if debugfs is enabled and mounted
- Creating debugfs entries with modern helper APIs
- Cleanup, licensing, and security notes
Prerequisites
Before this lesson, you should be comfortable with:
- Writing and loading a basic kernel module
- Sysfs basics (see our previous lesson on the sysfs one value per file rule)
- Reading a kernel config with zcat /proc/config.gz
What Is Debugfs?
Debugfs is a purpose-built virtual filesystem, normally mounted at /sys/kernel/debug, that the kernel offers specifically for debugging. Unlike sysfs, debugfs has no one-value-per-file restriction, no stable ABI guarantee, and no formatting conventions. It exists purely so driver authors can dump whatever internal state is useful during development or field debugging.
- One value per file
- Stable user space ABI
- Mounted at /sys
- Any format, any content
- No ABI stability promise
- Mounted at /sys/kernel/debug
Checking If Debugfs Is Enabled
Debugfs depends on the CONFIG_DEBUG_FS kernel config option and is enabled by default on almost every modern distribution kernel. You can confirm it two ways.
# Check the running kernel's config (requires CONFIG_IKCONFIG_PROC)
$ zcat /proc/config.gz | grep -w CONFIG_DEBUG_FS
CONFIG_DEBUG_FS=y
# Confirm the mount point
$ mount | grep -w debugfs
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
Never hard-code /sys/kernel/debug in a script without first verifying it — filesystems can technically be mounted at alternate locations, and defensive checks avoid subtle bugs.
Creating Debugfs Entries From a Kernel Module
The debugfs API offers convenience helpers so you rarely need to write full file_operations by hand for simple values. Here is a minimal, original example exposing a 32-bit counter for debugging purposes only — this is not meant to be a stable interface.
#include <linux/module.h>
#include <linux/debugfs.h>
static struct dentry *demo_dbgfs_dir;
static u32 demo_counter;
static int __init demo_debugfs_init(void)
{
demo_dbgfs_dir = debugfs_create_dir("demo_driver", NULL);
if (IS_ERR(demo_dbgfs_dir))
return PTR_ERR(demo_dbgfs_dir);
/* Exposes demo_counter as /sys/kernel/debug/demo_driver/counter */
debugfs_create_u32("counter", 0644, demo_dbgfs_dir, &demo_counter);
return 0;
}
static void __exit demo_debugfs_exit(void)
{
debugfs_remove_recursive(demo_dbgfs_dir);
}
module_init(demo_debugfs_init);
module_exit(demo_debugfs_exit);
MODULE_LICENSE("GPL");
Two points are easy to miss for newcomers:
- All debugfs symbols are exported GPL-only, so your module must be GPL licensed
- Always tear down the directory with debugfs_remove_recursive() on module unload
Debugfs Entry Lifecycle
Common Mistakes With Debugfs
- Forgetting debugfs_remove_recursive() on unload, leaking dentries
- Relying on debugfs as a stable ABI for production tooling
- Assuming /sys/kernel/debug is always the mount point without checking
- Exposing sensitive kernel state without restricting permissions
Best Practices
- Use debugfs only for debug output, never for a stable driver interface
- Group related entries under one debugfs_create_dir()
- Always pair creation with a matching removal on module exit
- Prefer sysfs for anything user space tools depend on long term
Security Considerations
Because debugfs has no formatting or stability rules, it is tempting to dump too much internal state through it. On production systems debugfs is often restricted to root only, and many distributions disable or lock it down. Never expose secrets, keys, or raw memory addresses through a debugfs entry, since it can widen the kernel’s attack surface if left accessible.
Summary / Key Takeaways
- Debugfs is a rule-free virtual filesystem meant purely for debugging
- It is normally mounted at /sys/kernel/debug and gated by CONFIG_DEBUG_FS
- Debugfs helper APIs like debugfs_create_u32() simplify entry creation
- All debugfs symbols are GPL-only exports
- Always clean up entries with debugfs_remove_recursive()
Frequently Asked Questions
Q1. What is debugfs used for in the Linux kernel?
Debugfs gives driver authors a free-form filesystem interface for exposing internal debug information to user space, without any formatting restrictions.
Q2. Where is debugfs normally mounted?
It is typically mounted at /sys/kernel/debug, though a script should always verify this rather than assume it.
Q3. Is debugfs a stable ABI like sysfs?
No. The kernel community explicitly does not guarantee debugfs stability, so it should never be relied on by production tooling.
Q4. Why do debugfs functions require a GPL license?
All debugfs kernel APIs are exported GPL-only, so any module using them must declare a GPL-compatible MODULE_LICENSE.
Q5. What happens if I forget to remove my debugfs entries?
The dentries remain allocated after your module unloads, which can lead to stale references and memory leaks.
Q6. Can I use debugfs on a production embedded Linux system?
You can, but it is often restricted to root or disabled entirely, since debugfs can expose sensitive internal kernel state.
Conclusion
Debugfs fills exactly the gap that the sysfs one-value-per-file rule leaves open: a flexible, no-rules debug interface for kernel developers. As you continue through this free Linux kernel programming course, use sysfs for stable attributes and debugfs whenever you just need to dump internal state during development.
More lessons on device drivers, kernel synchronization, and embedded Linux are coming up on EmbeddedPathashala.

2 Comments