← Documents Documentation/filesystems/debugfs.rst GitHub 원문 ↗

Linux 6.18.37 · Filesystems

DebugFS

debugfs의 ABI 성격, 마운트와 directory·file·scalar·blob·register helper, module unload 정리를 다룬 전문 번역입니다.

Source pathDocumentation/filesystems/debugfs.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

debugfs.rst:1-243

debugfs는 안정 ABI 보장이 없는 개발·진단용 filesystem이지만 실제 사용자 의존 가능성을 고려해 신중히 설계해야 합니다. 일반 dentry·file operations부터 scalar, blob, register, array, seq_file helper까지 제공하며 module 종료 시 생성한 tree를 반드시 제거해야 합니다.

debugfs API 수명 주기
debugfs mount와 접근 권한 설정`debugfs_create_dir()`로 subsystem root 생성값 형식에 맞는 file 또는 helper 생성사용자 공간에서 진단 정보 접근`debugfs_remove()`로 전체 subtree 정리

마운트부터 항목 생성·사용·재귀 제거까지의 전체 흐름입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2 .. include:: <isonum.txt>
3
4 =======
5 DebugFS
6 =======
7
8 Copyright |copy| 2009 Jonathan Corbet <[email protected]>
9
10 Debugfs exists as a simple way for kernel developers to make information
11 available to user space. Unlike /proc, which is only meant for information
12 about a process, or sysfs, which has strict one-value-per-file rules,
13 debugfs has no rules at all. Developers can put any information they want
14 there. The debugfs filesystem is also intended to not serve as a stable
15 ABI to user space; in theory, there are no stability constraints placed on
16 files exported there. The real world is not always so simple, though [1]_;
17 even debugfs interfaces are best designed with the idea that they will need
18 to be maintained forever.
19
20 Debugfs is typically mounted with a command like::
21
22 mount -t debugfs none /sys/kernel/debug
23
24 (Or an equivalent /etc/fstab line).
25 The debugfs root directory is accessible only to the root user by
26 default. To change access to the tree the "uid", "gid" and "mode" mount
27 options can be used.
28
29 Note that the debugfs API is exported GPL-only to modules.
30
31 Code using debugfs should include <linux/debugfs.h>. Then, the first order
32 of business will be to create at least one directory to hold a set of
33 debugfs files::
34
35 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
36
37 This call, if successful, will make a directory called name underneath the
38 indicated parent directory. If parent is NULL, the directory will be
39 created in the debugfs root. On success, the return value is a struct
40 dentry pointer which can be used to create files in the directory (and to
41 clean it up at the end). An ERR_PTR(-ERROR) return value indicates that
42 something went wrong. If ERR_PTR(-ENODEV) is returned, that is an
43 indication that the kernel has been built without debugfs support and none
44 of the functions described below will work.
45
46 The most general way to create a file within a debugfs directory is with::
47
48 struct dentry *debugfs_create_file(const char *name, umode_t mode,
49 struct dentry *parent, void *data,
50 const struct file_operations *fops);
51
52 Here, name is the name of the file to create, mode describes the access
53 permissions the file should have, parent indicates the directory which
54 should hold the file, data will be stored in the i_private field of the
55 resulting inode structure, and fops is a set of file operations which
56 implement the file's behavior. At a minimum, the read() and/or write()
57 operations should be provided; others can be included as needed. Again,
58 the return value will be a dentry pointer to the created file,
59 ERR_PTR(-ERROR) on error, or ERR_PTR(-ENODEV) if debugfs support is
60 missing.
61
62 Create a file with an initial size, the following function can be used
63 instead::
64
65 void debugfs_create_file_size(const char *name, umode_t mode,
66 struct dentry *parent, void *data,
67 const struct file_operations *fops,
68 loff_t file_size);
69
70 file_size is the initial file size. The other parameters are the same
71 as the function debugfs_create_file.
72
73 In a number of cases, the creation of a set of file operations is not
74 actually necessary; the debugfs code provides a number of helper functions
75 for simple situations. Files containing a single integer value can be
76 created with any of::
77
78 void debugfs_create_u8(const char *name, umode_t mode,
79 struct dentry *parent, u8 *value);
80 void debugfs_create_u16(const char *name, umode_t mode,
81 struct dentry *parent, u16 *value);
82 void debugfs_create_u32(const char *name, umode_t mode,
83 struct dentry *parent, u32 *value);
84 void debugfs_create_u64(const char *name, umode_t mode,
85 struct dentry *parent, u64 *value);
86
87 These files support both reading and writing the given value; if a specific
88 file should not be written to, simply set the mode bits accordingly. The
89 values in these files are in decimal; if hexadecimal is more appropriate,
90 the following functions can be used instead::
91
92 void debugfs_create_x8(const char *name, umode_t mode,
93 struct dentry *parent, u8 *value);
94 void debugfs_create_x16(const char *name, umode_t mode,
95 struct dentry *parent, u16 *value);
96 void debugfs_create_x32(const char *name, umode_t mode,
97 struct dentry *parent, u32 *value);
98 void debugfs_create_x64(const char *name, umode_t mode,
99 struct dentry *parent, u64 *value);
100
101 These functions are useful as long as the developer knows the size of the
102 value to be exported. Some types can have different widths on different
103 architectures, though, complicating the situation somewhat. There are
104 functions meant to help out in such special cases::
105
106 void debugfs_create_size_t(const char *name, umode_t mode,
107 struct dentry *parent, size_t *value);
108
109 As might be expected, this function will create a debugfs file to represent
110 a variable of type size_t.
111
112 Similarly, there are helpers for variables of type unsigned long, in decimal
113 and hexadecimal::
114
115 struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
116 struct dentry *parent,
117 unsigned long *value);
118 void debugfs_create_xul(const char *name, umode_t mode,
119 struct dentry *parent, unsigned long *value);
120
121 Boolean values can be placed in debugfs with::
122
123 void debugfs_create_bool(const char *name, umode_t mode,
124 struct dentry *parent, bool *value);
125
126 A read on the resulting file will yield either Y (for non-zero values) or
127 N, followed by a newline. If written to, it will accept either upper- or
128 lower-case values, or 1 or 0. Any other input will be silently ignored.
129
130 Also, atomic_t values can be placed in debugfs with::
131
132 void debugfs_create_atomic_t(const char *name, umode_t mode,
133 struct dentry *parent, atomic_t *value)
134
135 A read of this file will get atomic_t values, and a write of this file
136 will set atomic_t values.
137
138 Another option is exporting a block of arbitrary binary data, with
139 this structure and function::
140
141 struct debugfs_blob_wrapper {
142 void *data;
143 unsigned long size;
144 };
145
146 struct dentry *debugfs_create_blob(const char *name, umode_t mode,
147 struct dentry *parent,
148 struct debugfs_blob_wrapper *blob);
149
150 A read of this file will return the data pointed to by the
151 debugfs_blob_wrapper structure. Some drivers use "blobs" as a simple way
152 to return several lines of (static) formatted text output. This function
153 can be used to export binary information, but there does not appear to be
154 any code which does so in the mainline. Note that all files created with
155 debugfs_create_blob() are read-only.
156
157 If you want to dump a block of registers (something that happens quite
158 often during development, even if little such code reaches mainline),
159 debugfs offers two functions: one to make a registers-only file, and
160 another to insert a register block in the middle of another sequential
161 file::
162
163 struct debugfs_reg32 {
164 char *name;
165 unsigned long offset;
166 };
167
168 struct debugfs_regset32 {
169 const struct debugfs_reg32 *regs;
170 int nregs;
171 void __iomem *base;
172 struct device *dev; /* Optional device for Runtime PM */
173 };
174
175 debugfs_create_regset32(const char *name, umode_t mode,
176 struct dentry *parent,
177 struct debugfs_regset32 *regset);
178
179 void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
180 int nregs, void __iomem *base, char *prefix);
181
182 The "base" argument may be 0, but you may want to build the reg32 array
183 using __stringify, and a number of register names (macros) are actually
184 byte offsets over a base for the register block.
185
186 If you want to dump a u32 array in debugfs, you can create a file with::
187
188 struct debugfs_u32_array {
189 u32 *array;
190 u32 n_elements;
191 };
192
193 void debugfs_create_u32_array(const char *name, umode_t mode,
194 struct dentry *parent,
195 struct debugfs_u32_array *array);
196
197 The "array" argument wraps a pointer to the array's data and the number
198 of its elements. Note: Once array is created its size can not be changed.
199
200 There is a helper function to create a device-related seq_file::
201
202 void debugfs_create_devm_seqfile(struct device *dev,
203 const char *name,
204 struct dentry *parent,
205 int (*read_fn)(struct seq_file *s,
206 void *data));
207
208 The "dev" argument is the device related to this debugfs file, and
209 the "read_fn" is a function pointer which to be called to print the
210 seq_file content.
211
212 There are a couple of other directory-oriented helper functions::
213
214 struct dentry *debugfs_change_name(struct dentry *dentry,
215 const char *fmt, ...);
216
217 struct dentry *debugfs_create_symlink(const char *name,
218 struct dentry *parent,
219 const char *target);
220
221 A call to debugfs_change_name() will give a new name to an existing debugfs
222 file, always in the same directory. The new_name must not exist prior
223 to the call; the return value is 0 on success and -E... on failure.
224 Symbolic links can be created with debugfs_create_symlink().
225
226 There is one important thing that all debugfs users must take into account:
227 there is no automatic cleanup of any directories created in debugfs. If a
228 module is unloaded without explicitly removing debugfs entries, the result
229 will be a lot of stale pointers and no end of highly antisocial behavior.
230 So all debugfs users - at least those which can be built as modules - must
231 be prepared to remove all files and directories they create there. A file
232 or directory can be removed with::
233
234 void debugfs_remove(struct dentry *dentry);
235
236 The dentry value can be NULL or an error value, in which case nothing will
237 be removed. Note that this function will recursively remove all files and
238 directories underneath it. Previously, debugfs_remove_recursive() was used
239 to perform that task, but this function is now just an alias to
240 debugfs_remove(). debugfs_remove_recursive() should be considered
241 deprecated.
242
243 .. [1] http://lwn.net/Articles/309298/
244

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

목적, ABI 성격과 마운트

1-29

debugfs는 커널 개발자가 정보를 사용자 공간에 간단히 공개하도록 만든 파일시스템입니다. 프로세스 정보만을 위한 `/proc`이나 파일마다 값 하나라는 엄격한 규칙을 가진 sysfs와 달리, debugfs에는 내용 형식에 관한 규칙이 없습니다.

debugfs에 내보낸 파일은 사용자 공간을 위한 안정 ABI로 간주하지 않는 것이 원칙이며 이론적으로 안정성 제약도 없습니다. 하지만 실제 사용자는 이러한 인터페이스에도 의존할 수 있으므로, 처음부터 영구 유지해야 할 가능성을 염두에 두고 설계하는 편이 안전합니다.

일반적인 마운트 명령은 `mount -t debugfs none /sys/kernel/debug`이며 `/etc/fstab`에 동등한 항목을 둘 수도 있습니다. 기본적으로 debugfs 루트는 root 사용자만 접근할 수 있고, `uid`, `gid`, `mode` 마운트 옵션으로 트리의 접근 권한을 바꿀 수 있습니다.

모듈에 공개되는 debugfs API는 GPL 전용입니다.

debugfs 공개 경로
커널 코드가 debugfs API로 directory와 file 생성`/sys/kernel/debug`에 debugfs 마운트`uid`, `gid`, `mode`로 tree 접근 권한 조정사용자 공간 도구가 개발·진단 정보를 읽거나 허용된 값을 기록안정 ABI가 아니어도 장기 호환 가능성을 고려

개발용 커널 상태가 debugfs 파일을 거쳐 사용자 공간에 노출되는 흐름입니다.

.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>

=======
DebugFS
=======

Copyright |copy| 2009 Jonathan Corbet <[email protected]>

Debugfs exists as a simple way for kernel developers to make information
available to user space.  Unlike /proc, which is only meant for information
about a process, or sysfs, which has strict one-value-per-file rules,
debugfs has no rules at all.  Developers can put any information they want
there.  The debugfs filesystem is also intended to not serve as a stable
ABI to user space; in theory, there are no stability constraints placed on
files exported there.  The real world is not always so simple, though [1]_;
even debugfs interfaces are best designed with the idea that they will need
to be maintained forever.

Debugfs is typically mounted with a command like::

    mount -t debugfs none /sys/kernel/debug

(Or an equivalent /etc/fstab line).
The debugfs root directory is accessible only to the root user by
default. To change access to the tree the "uid", "gid" and "mode" mount
options can be used.

Note that the debugfs API is exported GPL-only to modules.

Directory와 일반 file 생성

30-71

debugfs를 사용하는 코드는 `<linux/debugfs.h>`를 포함해야 합니다. `debugfs_create_dir(name, parent)`는 지정한 parent 아래에 directory를 만들며, parent가 `NULL`이면 debugfs 루트에 생성합니다.

성공하면 새 directory의 `struct dentry *`를 반환합니다. 이 포인터는 하위 파일 생성과 종료 시 정리에 사용합니다. 실패는 `ERR_PTR(-ERROR)`이며, `ERR_PTR(-ENODEV)`는 커널이 debugfs 지원 없이 빌드되어 이후 API도 동작하지 않음을 뜻합니다.

가장 일반적인 파일 생성 함수는 `debugfs_create_file()`입니다. `name`은 파일 이름, `mode`는 접근 권한, `parent`는 소속 directory, `data`는 생성된 inode의 `i_private`에 저장할 값, `fops`는 동작을 구현하는 `struct file_operations`입니다. 최소한 `read()` 또는 `write()` 중 하나를 제공하고 필요에 따라 다른 operation을 추가합니다.

`debugfs_create_file()`도 성공 시 dentry, 일반 실패 시 `ERR_PTR(-ERROR)`, debugfs 미지원 시 `ERR_PTR(-ENODEV)`를 반환합니다. 초기 파일 크기가 필요하면 같은 인자에 `loff_t file_size`를 더한 `debugfs_create_file_size()`를 사용합니다.

debugfs 기본 생성 API
API핵심 인자결과
`debugfs_create_dir()``name`, `parent`성공 dentry, 실패 `ERR_PTR`
`debugfs_create_file()``name`, `mode`, `parent`, `data`, `fops`inode `i_private`와 file operations 연결
`debugfs_create_file_size()`일반 file 인자와 `file_size`초기 크기를 가진 file 생성
debugfs 미지원`CONFIG_DEBUG_FS` 없음`ERR_PTR(-ENODEV)`

directory와 일반 file 생성 함수의 인자와 반환 계약을 비교합니다.


Code using debugfs should include <linux/debugfs.h>.  Then, the first order
of business will be to create at least one directory to hold a set of
debugfs files::

    struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);

This call, if successful, will make a directory called name underneath the
indicated parent directory.  If parent is NULL, the directory will be
created in the debugfs root.  On success, the return value is a struct
dentry pointer which can be used to create files in the directory (and to
clean it up at the end).  An ERR_PTR(-ERROR) return value indicates that
something went wrong.  If ERR_PTR(-ENODEV) is returned, that is an
indication that the kernel has been built without debugfs support and none
of the functions described below will work.

The most general way to create a file within a debugfs directory is with::

    struct dentry *debugfs_create_file(const char *name, umode_t mode,
                                       struct dentry *parent, void *data,
                                       const struct file_operations *fops);

Here, name is the name of the file to create, mode describes the access
permissions the file should have, parent indicates the directory which
should hold the file, data will be stored in the i_private field of the
resulting inode structure, and fops is a set of file operations which
implement the file's behavior.  At a minimum, the read() and/or write()
operations should be provided; others can be included as needed.  Again,
the return value will be a dentry pointer to the created file,
ERR_PTR(-ERROR) on error, or ERR_PTR(-ENODEV) if debugfs support is
missing.

Create a file with an initial size, the following function can be used
instead::

    void debugfs_create_file_size(const char *name, umode_t mode,
                                  struct dentry *parent, void *data,
                                  const struct file_operations *fops,
                                  loff_t file_size);

file_size is the initial file size. The other parameters are the same
as the function debugfs_create_file.

정수와 architecture 의존 scalar helper

72-120

단순한 단일 정수 값을 내보낼 때는 별도 file operations를 작성할 필요가 없습니다. `debugfs_create_u8()`, `u16()`, `u32()`, `u64()` helper는 지정한 unsigned 정수 포인터를 10진수 파일로 공개하며 읽기와 쓰기를 모두 지원합니다. 쓰기를 금지하려면 `mode`에서 쓰기 권한을 빼면 됩니다.

16진 표현이 더 알맞으면 대응하는 `debugfs_create_x8()`, `x16()`, `x32()`, `x64()`를 사용합니다. 개발자가 값의 폭을 알고 있을 때 이 고정 폭 helper를 선택합니다.

architecture에 따라 폭이 달라지는 형식에는 전용 helper가 있습니다. `debugfs_create_size_t()`는 `size_t` 변수를 공개하고, `debugfs_create_ulong()`과 `debugfs_create_xul()`은 `unsigned long`을 각각 10진수와 16진수로 공개합니다.

Scalar helper 선택
C type10진수 helper16진수 helper
`u8``debugfs_create_u8()``debugfs_create_x8()`
`u16``debugfs_create_u16()``debugfs_create_x16()`
`u32``debugfs_create_u32()``debugfs_create_x32()`
`u64``debugfs_create_u64()``debugfs_create_x64()`
`size_t``debugfs_create_size_t()`전용 helper 없음
`unsigned long``debugfs_create_ulong()``debugfs_create_xul()`

값의 C type과 표시 radix에 맞는 helper를 정리합니다.


In a number of cases, the creation of a set of file operations is not
actually necessary; the debugfs code provides a number of helper functions
for simple situations.  Files containing a single integer value can be
created with any of::

    void debugfs_create_u8(const char *name, umode_t mode,
                           struct dentry *parent, u8 *value);
    void debugfs_create_u16(const char *name, umode_t mode,
                            struct dentry *parent, u16 *value);
    void debugfs_create_u32(const char *name, umode_t mode,
                            struct dentry *parent, u32 *value);
    void debugfs_create_u64(const char *name, umode_t mode,
                            struct dentry *parent, u64 *value);

These files support both reading and writing the given value; if a specific
file should not be written to, simply set the mode bits accordingly.  The
values in these files are in decimal; if hexadecimal is more appropriate,
the following functions can be used instead::

    void debugfs_create_x8(const char *name, umode_t mode,
                           struct dentry *parent, u8 *value);
    void debugfs_create_x16(const char *name, umode_t mode,
                            struct dentry *parent, u16 *value);
    void debugfs_create_x32(const char *name, umode_t mode,
                            struct dentry *parent, u32 *value);
    void debugfs_create_x64(const char *name, umode_t mode,
                            struct dentry *parent, u64 *value);

These functions are useful as long as the developer knows the size of the
value to be exported.  Some types can have different widths on different
architectures, though, complicating the situation somewhat.  There are
functions meant to help out in such special cases::

    void debugfs_create_size_t(const char *name, umode_t mode,
                               struct dentry *parent, size_t *value);

As might be expected, this function will create a debugfs file to represent
a variable of type size_t.

Similarly, there are helpers for variables of type unsigned long, in decimal
and hexadecimal::

    struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
                                        struct dentry *parent,
                                        unsigned long *value);
    void debugfs_create_xul(const char *name, umode_t mode,
                            struct dentry *parent, unsigned long *value);

Boolean, atomic_t와 blob

121-155

`debugfs_create_bool()`은 `bool` 값을 파일로 공개합니다. 읽으면 0이 아닌 값은 `Y`, 0은 `N`과 newline으로 나타납니다. 쓰기는 대소문자 boolean 표현 또는 `1`, `0`을 받아들이며 다른 입력은 조용히 무시합니다.

`debugfs_create_atomic_t()`는 `atomic_t` 값을 읽고 쓰는 파일을 만듭니다. 읽기는 현재 atomic 값을 얻고 쓰기는 atomic 값을 설정합니다.

임의의 binary block은 data 포인터와 크기를 가진 `struct debugfs_blob_wrapper`를 준비해 `debugfs_create_blob()`으로 내보냅니다. 일부 driver는 여러 줄의 정적 formatted text를 반환하는 간단한 수단으로 blob을 사용합니다.

binary 정보도 공개할 수 있지만 mainline에는 그렇게 사용하는 코드가 없는 것으로 보입니다. `debugfs_create_blob()`으로 만든 모든 파일은 read-only입니다.

특수 값 helper
Helper대상읽기·쓰기 특성
`debugfs_create_bool()``bool *``Y/N` 읽기, boolean 또는 `1/0` 쓰기
`debugfs_create_atomic_t()``atomic_t *`atomic 값 읽기와 설정
`debugfs_create_blob()``debugfs_blob_wrapper *`고정 data block, read-only

단일 scalar 이외의 간단한 값을 공개하는 계약입니다.

Boolean values can be placed in debugfs with::

    void debugfs_create_bool(const char *name, umode_t mode,
                             struct dentry *parent, bool *value);

A read on the resulting file will yield either Y (for non-zero values) or
N, followed by a newline.  If written to, it will accept either upper- or
lower-case values, or 1 or 0.  Any other input will be silently ignored.

Also, atomic_t values can be placed in debugfs with::

    void debugfs_create_atomic_t(const char *name, umode_t mode,
                                 struct dentry *parent, atomic_t *value)

A read of this file will get atomic_t values, and a write of this file
will set atomic_t values.

Another option is exporting a block of arbitrary binary data, with
this structure and function::

    struct debugfs_blob_wrapper {
        void *data;
        unsigned long size;
    };

    struct dentry *debugfs_create_blob(const char *name, umode_t mode,
                                       struct dentry *parent,
                                       struct debugfs_blob_wrapper *blob);

A read of this file will return the data pointed to by the
debugfs_blob_wrapper structure.  Some drivers use "blobs" as a simple way
to return several lines of (static) formatted text output.  This function
can be used to export binary information, but there does not appear to be
any code which does so in the mainline.  Note that all files created with
debugfs_create_blob() are read-only.

Register dump, u32 array와 device seq_file

156-210

register block을 덤프할 때는 `struct debugfs_reg32` 배열에 register 이름과 base 상대 offset을 기록하고, `struct debugfs_regset32`에 배열, 개수, MMIO base, 선택적인 Runtime PM device를 묶습니다. `debugfs_create_regset32()`는 register 전용 파일을 만들고 `debugfs_print_regs32()`는 다른 순차 파일 중간에 같은 register block을 출력합니다.

`base`는 0일 수 있습니다. register 이름이 실제로 base에 대한 byte offset macro라면 `__stringify`를 사용해 `reg32` 배열을 구성할 수 있습니다.

u32 배열은 data pointer와 element 수를 가진 `struct debugfs_u32_array`로 감싸 `debugfs_create_u32_array()`에 전달합니다. 파일을 만든 뒤에는 배열 크기를 변경할 수 없습니다.

device 관련 `seq_file`은 `debugfs_create_devm_seqfile()`로 만듭니다. `dev`는 파일과 관련된 device이며, `read_fn` callback은 `seq_file` 내용을 출력할 때 호출됩니다.

복합 debugfs 출력 구성
register 이름·offset을 `debugfs_reg32[]`로 작성MMIO base·개수·선택적 device를 `debugfs_regset32`에 결합독립 파일은 `debugfs_create_regset32()`로 생성기존 seq_file 중간 출력은 `debugfs_print_regs32()` 사용u32 배열은 고정 크기 `debugfs_u32_array`로 공개device seq_file은 managed `debugfs_create_devm_seqfile()`로 생성

register, array, device seq_file에 맞는 wrapper와 helper를 고르는 흐름입니다.


If you want to dump a block of registers (something that happens quite
often during development, even if little such code reaches mainline),
debugfs offers two functions: one to make a registers-only file, and
another to insert a register block in the middle of another sequential
file::

    struct debugfs_reg32 {
        char *name;
        unsigned long offset;
    };

    struct debugfs_regset32 {
        const struct debugfs_reg32 *regs;
        int nregs;
        void __iomem *base;
        struct device *dev;     /* Optional device for Runtime PM */
    };

    debugfs_create_regset32(const char *name, umode_t mode,
                            struct dentry *parent,
                            struct debugfs_regset32 *regset);

    void debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
                         int nregs, void __iomem *base, char *prefix);

The "base" argument may be 0, but you may want to build the reg32 array
using __stringify, and a number of register names (macros) are actually
byte offsets over a base for the register block.

If you want to dump a u32 array in debugfs, you can create a file with::

    struct debugfs_u32_array {
        u32 *array;
        u32 n_elements;
    };

    void debugfs_create_u32_array(const char *name, umode_t mode,
                        struct dentry *parent,
                        struct debugfs_u32_array *array);

The "array" argument wraps a pointer to the array's data and the number
of its elements. Note: Once array is created its size can not be changed.

There is a helper function to create a device-related seq_file::

   void debugfs_create_devm_seqfile(struct device *dev,
                                const char *name,
                                struct dentry *parent,
                                int (*read_fn)(struct seq_file *s,
                                        void *data));

The "dev" argument is the device related to this debugfs file, and
the "read_fn" is a function pointer which to be called to print the
seq_file content.

이름 변경, symlink와 필수 정리

211-243

directory 지향 helper로 `debugfs_change_name()`과 `debugfs_create_symlink()`가 있습니다. 전자는 기존 debugfs 항목을 같은 directory 안에서 새 이름으로 바꾸며, 새 이름은 호출 전에 존재하지 않아야 합니다. 원문 설명은 성공 시 0, 실패 시 `-E...`라고 기술합니다. 후자는 symbolic link를 만듭니다.

debugfs는 생성한 directory를 자동으로 정리하지 않습니다. 모듈 unload 전에 항목을 명시적으로 제거하지 않으면 stale pointer가 남아 심각한 오동작을 일으킬 수 있습니다. 따라서 모듈로 빌드될 수 있는 사용자는 자신이 만든 모든 file과 directory를 제거할 준비를 해야 합니다.

`debugfs_remove(dentry)`는 해당 항목과 모든 하위 file·directory를 재귀적으로 제거합니다. dentry가 `NULL`이거나 error value이면 아무것도 제거하지 않습니다. 과거의 `debugfs_remove_recursive()`는 이제 `debugfs_remove()`의 alias이므로 deprecated로 간주해야 합니다.

debugfs lifetime
module 초기화 중 directory와 file 생성필요하면 같은 parent 안에서 이름 변경 또는 symlink 생성운영 중 dentry pointer 보존module 종료 전에 root dentry를 `debugfs_remove()`에 전달하위 tree 재귀 제거 완료 후 module unload

생성한 dentry tree를 module lifetime에 맞춰 정리하는 필수 순서입니다.


There are a couple of other directory-oriented helper functions::

    struct dentry *debugfs_change_name(struct dentry *dentry,
                                          const char *fmt, ...);

    struct dentry *debugfs_create_symlink(const char *name,
                                          struct dentry *parent,
                                                const char *target);

A call to debugfs_change_name() will give a new name to an existing debugfs
file, always in the same directory.  The new_name must not exist prior
to the call; the return value is 0 on success and -E... on failure.
Symbolic links can be created with debugfs_create_symlink().

There is one important thing that all debugfs users must take into account:
there is no automatic cleanup of any directories created in debugfs.  If a
module is unloaded without explicitly removing debugfs entries, the result
will be a lot of stale pointers and no end of highly antisocial behavior.
So all debugfs users - at least those which can be built as modules - must
be prepared to remove all files and directories they create there.  A file
or directory can be removed with::

    void debugfs_remove(struct dentry *dentry);

The dentry value can be NULL or an error value, in which case nothing will
be removed.  Note that this function will recursively remove all files and
directories underneath it.  Previously, debugfs_remove_recursive() was used
to perform that task, but this function is now just an alias to
debugfs_remove().  debugfs_remove_recursive() should be considered
deprecated.

.. [1] http://lwn.net/Articles/309298/