[PATCH] Add seq_file howto to Documentation/



Add seq_file howto to Documentation/

Signed-off-by: Martin J. Bligh <mbligh@xxxxxxxxxx>

Taken from kernelnewbies with Randy's permission. diff -aurpN -X /home/mbligh/.diff.exclude linux-2.6.22/Documentation/seq_file_howto.txt 2.6.22-seq_file_doc/Documentation/seq_file_howto.txt
--- linux-2.6.22/Documentation/seq_file_howto.txt 1969-12-31 16:00:00.000000000 -0800
+++ 2.6.22-seq_file_doc/Documentation/seq_file_howto.txt 2007-07-23 12:41:24.000000000 -0700
@@ -0,0 +1,246 @@
+Linux kernel seq_file HOWTO
+Randy Dunlap <rddunlap@xxxxxxxx>
+v0: 2003-02-22
+v1: 2003-03-14
+
+Parts of this seq_file HOWTO were contributed by Andries Brouwer
+(aeb%win!tue!nl).
+
+[Another seq_file reference is "Driver porting: The seq_file interface"
+at <http://lwn.net/Articles/22355/>, which is part of the
+LWN.net series "Porting Drivers to 2.5" that is located at
+<http://lwn.net/Articles/driver-porting/>.]
+
+======================================================================
+
+* Introduction
+
+The "seq_file" interface to the /proc filesystem was introduced in
+Linux 2.4.15-pre3 and Linux 2.4.13-ac8. It provides a safer interface
+to the /proc filesystem than previous procfs methods because it protects
+against overflow of the output buffer and easily handles procfs files
+that are larger than one page. It also provides methods for
+traversing a list of kernel items and iterating on that list.
+It provides procfs output facilities that are less error-prone than
+the previous procfs interfaces.
+
+Overview: seq_file operates by using "pull" methods, pulling or asking
+for data from seq_file operations methods, whereas the previous procfs
+methods pushed data into output buffers.
+
+======================================================================
+
+* seq_file creation and data structures
+
+A seq_file-type /proc file is created by using create_proc_entry() and
+setting the resulting proc_dir_entry->proc_fops pointer to the
+desired struct file_operations. E.g. (from linux/mm/swapfile.c):
+
+static int __init procswaps_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_entry("swaps", 0, NULL);
+ if (entry)
+ entry->proc_fops = &proc_swaps_operations;
+ return 0;
+}
+
+struct file_operations for the seq_file-type proc file describes 4
+I/O methods, e.g.:
+
+static struct file_operations proc_swaps_operations = {
+ .open = swaps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+The last 3 are reusable seq_file-supplied methods. The open method
+is what must be supplied for each proc file, and that open()
+function only needs to call seq_open() with a pointer to a struct
+seq_operations descriptor. E.g. (still from linux/mm/swapfile.c):
+
+static int swaps_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &swaps_op);
+}
+
+struct seq_file seq_operations swaps_op supplies 4 methods for
+producing seq_file output: start(), next(), stop(), and show().
+These are described below. The structure typically looks like:
+
+static struct seq_operations swaps_op = {
+ .start = swap_start,
+ .next = swap_next,
+ .stop = swap_stop,
+ .show = swap_show
+};
+
+======================================================================
+
+* seq_file methods
+
+The seq_file routines never take any locks between the ->open() and
+->stop() functions, so seq_file callers are free to use anything --
+spinlocks, etc.
+
+The seq_file interface does require more data structures to be setup
+to point to methods that are used during seq_file access. In return
+for this, you (we) get much safer /proc output methods. These four
+methods are in struct seq_operations:
+
+struct seq_operations {
+ void * (*start) (struct seq_file *m, loff_t *pos);
+ void (*stop) (struct seq_file *m, void *v);
+ void * (*next) (struct seq_file *m, void *v, loff_t *pos);
+ int (*show) (struct seq_file *m, void *v);
+};
+
+The .start method is used to initialize data for walking through a list
+of kernel items. This list can be an array, a linked list, a hash table,
+etc. Its actual data type doesn't matter. This function should lock
+whatever needs to be locked for safety and return an entry by number
+(0 for the first entry). This method should also honor file offset
+semantics by using the "loff_t *pos" (second) parameter.
+The "entry number" value is passed to the stop, next, and show
+methods as the "void *v" parameter.
+In case of error, return ERR_PTR(error_code).
+
+If you need to show a header line or something, then return
+SEQ_START_TOKEN in your start() and recognise that in next() and
+show(). IOW, pos == 0 will be the header line, and pos == 1
+will correspond to the first actual item on your list, and so on.
+See net/netlink/af_netlink.c for a simple example.
+
+If there is any locking that needs to be done to iterate through the
+kernel list, the lock(s) can be acquired in the .start method. However,
+if the .show method is very time-consuming and the .show method lends
+itself to locking there, that may be a better place for it.
+
+struct seq_file contains a "void *private" that can be used by the
+struct seq_operations functions to hold any private data that needs
+to be available to all of these related methods. For example, the
+.start method might allocate some memory and save its address in
+seq_file.private so that the .next and .show methods can use it,
+then the .stop method would free that memory.
+
+The .stop method is called after the .next method has nothing more to
+do. This method is used for cleanups, unlocking, freeing resources, etc.
+The .stop method is always called if the .start method was called, even
+if the .start method fails, so that all cleanups can be done in .stop.
+
+The .next method is the iterator for the items (list, array, table, etc.)
+that is being traversed for /proc file output. It advances to the next
+item of interest to be shown in the /proc output file and indicates
+when there are no more items by returning NULL or an error (like -ENOMEM
+or -EACCES). If there are more items to be shown, it returns the next
+element (entry) of the sequence by entry number.
+
+The .show method is used to show an entry (write output to the /proc
+file) by using seq_...() as you would use stdio functions. It can
+write static headings or variable data into the seq_file output buffer.
+It uses seq_{putc, puts, printf, ...} to format the output (see below).
+In case of error, return a negative error_code; otherwise return 0.
+
+======================================================================
+
+* seq_file output routines
+
+The seq_file output methods are:
+
+/*
+ * seq_putc:
+ * print one character to the seq_file output buffer
+ * returns 0 for success or -1 for error
+ */
+int seq_putc(struct seq_file *m, char c);
+
+/*
+ * seq_puts:
+ * print a null-terminated string to the seq_file output buffer
+ * returns 0 for success or -1 for error
+ */
+int seq_puts(struct seq_file *m, const char *s);
+
+/*
+ * seq_printf:
+ * print a formatted string and variable data to the seq_file output buffer
+ * returns 0 for success or -1 for error
+ */
+int seq_printf(struct seq_file *m, const char *f, ...);
+
+/*
+ * seq_open: initialize sequential file
+ * @file: file to initialize
+ * @op: method table describing the sequence
+ *
+ * seq_open() sets @file, associating it with a sequence described
+ * by @op. @op->start() sets the iterator up and returns the first
+ * element of sequence. @op->stop() shuts it down. @op->next()
+ * returns the next element of sequence. @op->show() prints element
+ * into the buffer. In case of error ->start() and ->next() return
+ * ERR_PTR(error). In the end of sequence they return %NULL. ->show()
+ * returns 0 in case of success and negative number in case of error.
+ */
+int seq_open(struct file *file, struct seq_operations *op);
+
+/*
+ * seq_read: ->read() method for sequential files.
+ * @file, @buf, @size, @ppos: see file_operations method
+ *
+ * Ready-made ->f_op->read()
+ */
+ssize_t seq_read(struct file *file, char *buf, size_t size, loff_t *ppos);
+
+/*
+ * seq_lseek: ->llseek() method for sequential files.
+ * @file, @offset, @origin: see file_operations method
+ *
+ * Ready-made ->f_op->llseek()
+ */
+loff_t seq_lseek(struct file *file, loff_t offset, int origin);
+
+/*
+ * seq_release: free the structures associated with sequential file.
+ * @file: file in question
+ * @inode: file->f_dentry->d_inode
+ *
+ * Frees the structures associated with sequential file; can be used
+ * as ->f_op->release() if you don't have private data to destroy.
+ */
+int seq_release(struct inode *inode, struct file *file);
+
+/*
+ * seq_escape: print string into buffer, escaping some characters
+ * @m: target buffer
+ * @s: string
+ * @esc: set of characters that need escaping
+ *
+ * Puts string into buffer, replacing each occurence of character from
+ * @esc with usual octal escape. Returns 0 in case of success
+ * or -1 in case of overflow.
+ */
+int seq_escape(struct seq_file *m, const char *s, const char *esc);
+
+======================================================================
+
+* Simplified seq_file methods
+
+If you only need a single function entry (call) to produce all the
+desired proc-fs output, just use single_open() and single_release().
+
+single_open() gets a parameter that is the "show" function for the data
+that is to be written to /proc. The "show" function does everything
+that is needed to write the data, all in one function call. This is
+useful either for writing small amounts of data to /proc, for cases in
+which the output is not iterative, or for cases in which recursion is
+more appropriate, since the non-single methods don't fit well with
+recursive techniques. Examples of appropriate uses of single_open()
+"show" functions are:
+
+ linux/kernel/dma.c::proc_dma_show() : small quantity of data to write
+ linux/net/ipv4/proc.c::sockstat_seq_show() : non-iterative data
+ linux/net/sunrpc/rpc_pipe.c::rpc_show_info() : non-iterative data
+
+###


Relevant Pages

  • Gcov-kernel patch update for 2.6.0-test3
    ... Here's another resync of the kernel patch (originally by Hubertus Franke ... and Rajan Ravindran) to allow the gcov coverage analysis tool to be used ... * The .ctors-section contains a list of pointers to constructor ... static struct memchunk *freechunks; ...
    (Linux-Kernel)
  • On-disk indexing for "Project Ideas" page
    ... The kernel usually does the lookup by starting at the beginning ... of the directory and going through, comparing each entry in turn. ... name cache described in Section 6.6. ...
    (freebsd-current)
  • [PATCH] ppc32: rename head_e500.S to head_fsl_booke.S
    ... * Kernel execution entry point code. ... Initial PowerPC version. ... -/* Note that the SPE support is closely modeled after the AltiVec ...
    (Linux-Kernel)
  • Re: Grub not right on new install.
    ... # Set the default entry to the entry number NUM. ... # Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST ... ## should update-grub create alternative automagic boot options ... Linux install includes an entry for Windows in the menu.list ...
    (Ubuntu)
  • [PATCH 2 of 18] ipath - core driver header files
    ... ipath_debug.h contains mask values used for controlling driver debugging. ... * to communicate between kernel and user code. ... * This struct must have explict pad fields where type sizes ... * We could have a single register get/put routine, that takes a group type, ...
    (Linux-Kernel)