[PATCH RESEND v2 23/23] Documentation: seq_file: describe how a /proc file uses seq_file

From: Christian Brauner

Date: Wed Nov 04 2026 - 15:44:33 EST


The example in seq_file.rst hands proc_create() file operations built
from an open method that calls seq_open() and from seq_read(),
seq_lseek() and seq_release(). procfs doesn't work that way anymore. It
opens and releases the seq_file itself when the entry declares its
seq_operations or its show function in struct proc_ops. Say so, and
point the extra-simple version at ->proc_show() for /proc files.

Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
---
Documentation/filesystems/seq_file.rst | 42 ++++++++++++++++++++++++++--------
1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/Documentation/filesystems/seq_file.rst b/Documentation/filesystems/seq_file.rst
index d753d8177bcb..3e6ff1c1226d 100644
--- a/Documentation/filesystems/seq_file.rst
+++ b/Documentation/filesystems/seq_file.rst
@@ -68,7 +68,7 @@ kernel 3.10. Current versions require the following update::
- entry = create_proc_entry("sequence", 0, NULL);
- if (entry)
- entry->proc_fops = &ct_file_ops;
- + entry = proc_create("sequence", 0, NULL, &ct_file_ops);
+ + entry = proc_create("sequence", 0, NULL, &ct_proc_ops);

The iterator interface
======================
@@ -277,9 +277,10 @@ seq_file system, but we have not yet turned them into a file that a user
can see. Creating a file within the kernel requires, of course, the
creation of a set of file_operations which implement the operations on that
file. The seq_file interface provides a set of canned operations which do
-most of the work. The virtual file author still must implement the open()
-method, however, to hook everything up. The open function is often a single
-line, as in the example module::
+most of the work. A file in /proc is special, procfs hooks the seq_file up
+itself, see below. Everywhere else the virtual file author still must
+implement the open() method to do that. The open function is often a
+single line::

static int ct_open(struct inode *inode, struct file *file)
{
@@ -343,19 +344,38 @@ file_operations structure will look like::
There is also a seq_release_private() which passes the contents of the
seq_file private field to kfree() before releasing the structure.

-The final step is the creation of the /proc file itself. In the example
-code, that is done in the initialization code in the usual way::
+The final step is the creation of the file itself. A file in /proc is
+special here: procfs opens and releases the seq_file itself, so there is
+no open method and no file_operations for it. The entry declares its
+seq_operations in struct proc_ops instead, and the size of a private
+block in proc_state_size if it wants procfs to allocate one like
+seq_open_private() would::
+
+ static const struct proc_ops ct_proc_ops = {
+ .proc_seq_ops = &ct_seq_ops,
+ };

static int ct_init(void)
{
- struct proc_dir_entry *entry;
-
- proc_create("sequence", 0, NULL, &ct_file_ops);
+ proc_create("sequence", 0, NULL, &ct_proc_ops);
return 0;
}

module_init(ct_init);

+A ->proc_open() method of such an entry finds the seq_file in
+file->private_data and may set up more state; ->proc_release() releases
+only that. It runs when the entry is removed, which can be while a reader
+is still copying out of the seq_file, so it must leave the seq_file
+alone. procfs only calls into the entry with the entry pinned, between
+start() and stop() like in its other methods, so nothing that runs there
+may wait for something a reader can hold while it copies to userspace,
+like the seq_file's lock.
+An entry that wants to start out with a larger buffer, like
+single_open_size() gives, calls seq_preallocate() from ->proc_open().
+The file_operations above are what a file elsewhere, in debugfs for
+example, uses.
+
And that is pretty much it.


@@ -394,3 +414,7 @@ value given to single_open() can be found in the private field of the
seq_file structure. When using single_open(), the programmer should use
single_release() instead of seq_release() in the file_operations structure
to avoid a memory leak.
+
+A file in /proc puts the show() function into the proc_show field of its
+struct proc_ops instead and procfs does the rest, with the entry's data in
+the private field of the seq_file structure.

--
2.53.0