How To Use debugfs
Table of Contents
In the Linux Kernel, many drivers and subsystems have support for a special file system called debugfs. Debugfs is very similar to other virtual filesystems, such as sysfs and procfs, but it has no functional purpose except to provide debugging information. The files in this filesystem are generated by the kernel, and the contents will vary depending on the driver/subsystem. When writing new drivers, debugfs is preferred to printk statements, since it is much easier to enable/disable, and provides a much more standardized interface. This document provides basic information about using and implementing debugfs files.
Prerequisites
- Kernel build with the following configuration options:
- CONFIG_DEBUG_FS=y
Mounting debugfs
Debugfs can be mounted much like any other virtual filesystem using the mount command. To mount the debugfs filesystem:
- Create a mount point. The default is typically /sys/kernel/debug/, which may already exist.
# mkdir /sys/kernel/debug
- Mount the filesystem using the mount command:
# mount -t debugfs none /sys/kernel/debug
- Use the cat command to view the contents of the file system:
# cat /sys/kernel/debug/gpio GPIOs 32-63, A: [ds5] GPIOA6: [gpio] set [ds1] GPIOA9: [gpio] clear [sda] GPIOA23: [gpio] set [scl] GPIOA24: [gpio] set [Button 3] GPIOA30: [gpio] set [Button 4] GPIOA31: [gpio] set GPIOs 64-95, B: GPIOs 96-127, C: [udc_vbus] GPIOC5: [gpio] set [nand_rdy] GPIOC13: [gpio] set [nand_enable] GPIOC14: [gpio] set
Adding debugfs Support to a Driver
The debugfs API is documented in the kernel source files fs/debugfs/inode.c and fs/debugfs/file.c
Creating debugfs files for a given driver or subsystem is relatively easy. It has three main steps:
- Determine directory structure
- Create file operation functions for each file.
- Register files with debugfs filesystem.
Debugfs Directory Structure
You can split your debugfs entries into multiple files, and even organize them in a hierarchical directory structure. Some possibilities include having single file, one file for register values and one for reading the contents of a buffer, or mostly any organization you want. Ultimately, try to choose a structure that will be the most helpful to somebody that is debugging a problem.
The hierarchy is determined by the use of the debugfs_create_dir and debugfs_create_file functions, which are described in more detail later in this document and in the kernel source code.
File Operation Functions
In most cases, you will need to define functions for the file operations:
- open
- release
- llseek
- read
You will have to define operations for each file. You may be able to use generic file operations (especially in the case of llseek) if they are appropriate for your file.
Once the functions are defined within the driver, they must be assigned to the appropriate function pointers in a file_operations struct. You should have one struct per file.
Please see Chapter 3 of Linux Device Drivers, 3rd Edition for more information regarding file operations.
Registering Files
The function debugfs_create_file is used to register a file with the debugfs file system. This function takes a filename, file permission mask, and file_operations structure (as well as other things) as parameters. This function should be called once per file, when the driver/subsystem is initialized with the kernel.
To create subdirectories in the debugfs filesystem, use the function debugfs_create_dir.
These functions are documented in the kernel source code, in the directory fs/debugfs.
Code Samples
There are plenty of code samples in the Linux kernel for using debugfs. These are a few:
- drivers/gpio/gpiolib.c - GPIOLIB subsystem
- drivers/usb/gadget/atmel_ubsa_udc.c - Atmel USBA Gadget Ethernet Driver