aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/Makefile17
-rw-r--r--Documentation/DocBook/procfs-guide.tmpl626
-rw-r--r--Documentation/DocBook/procfs_example.c201
3 files changed, 3 insertions, 841 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index ab8300f67182..ee34ceb9ad5f 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -8,7 +8,7 @@
8 8
9DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ 9DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
10 kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ 10 kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
11 procfs-guide.xml writing_usb_driver.xml networking.xml \ 11 writing_usb_driver.xml networking.xml \
12 kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ 12 kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
13 gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ 13 gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
14 genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ 14 genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
@@ -65,7 +65,7 @@ KERNELDOC = $(srctree)/scripts/kernel-doc
65DOCPROC = $(objtree)/scripts/basic/docproc 65DOCPROC = $(objtree)/scripts/basic/docproc
66 66
67XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl 67XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl
68#XMLTOFLAGS += --skip-validation 68XMLTOFLAGS += --skip-validation
69 69
70### 70###
71# DOCPROC is used for two purposes: 71# DOCPROC is used for two purposes:
@@ -101,17 +101,6 @@ endif
101# Changes in kernel-doc force a rebuild of all documentation 101# Changes in kernel-doc force a rebuild of all documentation
102$(BOOKS): $(KERNELDOC) 102$(BOOKS): $(KERNELDOC)
103 103
104###
105# procfs guide uses a .c file as example code.
106# This requires an explicit dependency
107C-procfs-example = procfs_example.xml
108C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
109$(obj)/procfs-guide.xml: $(C-procfs-example2)
110
111# List of programs to build
112##oops, this is a kernel module::hostprogs-y := procfs_example
113obj-m += procfs_example.o
114
115# Tell kbuild to always build the programs 104# Tell kbuild to always build the programs
116always := $(hostprogs-y) 105always := $(hostprogs-y)
117 106
@@ -238,7 +227,7 @@ clean-files := $(DOCBOOKS) \
238 $(patsubst %.xml, %.pdf, $(DOCBOOKS)) \ 227 $(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
239 $(patsubst %.xml, %.html, $(DOCBOOKS)) \ 228 $(patsubst %.xml, %.html, $(DOCBOOKS)) \
240 $(patsubst %.xml, %.9, $(DOCBOOKS)) \ 229 $(patsubst %.xml, %.9, $(DOCBOOKS)) \
241 $(C-procfs-example) $(index) 230 $(index)
242 231
243clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man 232clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
244 233
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
deleted file mode 100644
index 9eba4b7af73d..000000000000
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ /dev/null
@@ -1,626 +0,0 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
3 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
4<!ENTITY procfsexample SYSTEM "procfs_example.xml">
5]>
6
7<book id="LKProcfsGuide">
8 <bookinfo>
9 <title>Linux Kernel Procfs Guide</title>
10
11 <authorgroup>
12 <author>
13 <firstname>Erik</firstname>
14 <othername>(J.A.K.)</othername>
15 <surname>Mouw</surname>
16 <affiliation>
17 <address>
18 <email>mouw@nl.linux.org</email>
19 </address>
20 </affiliation>
21 </author>
22 <othercredit>
23 <contrib>
24 This software and documentation were written while working on the
25 LART computing board
26 (<ulink url="http://www.lartmaker.nl/">http://www.lartmaker.nl/</ulink>),
27 which was sponsored by the Delt University of Technology projects
28 Mobile Multi-media Communications and Ubiquitous Communications.
29 </contrib>
30 </othercredit>
31 </authorgroup>
32
33 <revhistory>
34 <revision>
35 <revnumber>1.0</revnumber>
36 <date>May 30, 2001</date>
37 <revremark>Initial revision posted to linux-kernel</revremark>
38 </revision>
39 <revision>
40 <revnumber>1.1</revnumber>
41 <date>June 3, 2001</date>
42 <revremark>Revised after comments from linux-kernel</revremark>
43 </revision>
44 </revhistory>
45
46 <copyright>
47 <year>2001</year>
48 <holder>Erik Mouw</holder>
49 </copyright>
50
51
52 <legalnotice>
53 <para>
54 This documentation is free software; you can redistribute it
55 and/or modify it under the terms of the GNU General Public
56 License as published by the Free Software Foundation; either
57 version 2 of the License, or (at your option) any later
58 version.
59 </para>
60
61 <para>
62 This documentation is distributed in the hope that it will be
63 useful, but WITHOUT ANY WARRANTY; without even the implied
64 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
65 PURPOSE. See the GNU General Public License for more details.
66 </para>
67
68 <para>
69 You should have received a copy of the GNU General Public
70 License along with this program; if not, write to the Free
71 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
72 MA 02111-1307 USA
73 </para>
74
75 <para>
76 For more details see the file COPYING in the source
77 distribution of Linux.
78 </para>
79 </legalnotice>
80 </bookinfo>
81
82
83
84
85 <toc>
86 </toc>
87
88
89
90
91 <preface id="Preface">
92 <title>Preface</title>
93
94 <para>
95 This guide describes the use of the procfs file system from
96 within the Linux kernel. The idea to write this guide came up on
97 the #kernelnewbies IRC channel (see <ulink
98 url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>),
99 when Jeff Garzik explained the use of procfs and forwarded me a
100 message Alexander Viro wrote to the linux-kernel mailing list. I
101 agreed to write it up nicely, so here it is.
102 </para>
103
104 <para>
105 I'd like to thank Jeff Garzik
106 <email>jgarzik@pobox.com</email> and Alexander Viro
107 <email>viro@parcelfarce.linux.theplanet.co.uk</email> for their input,
108 Tim Waugh <email>twaugh@redhat.com</email> for his <ulink
109 url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
110 and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
111 proofreading.
112 </para>
113
114 <para>
115 Erik
116 </para>
117 </preface>
118
119
120
121
122 <chapter id="intro">
123 <title>Introduction</title>
124
125 <para>
126 The <filename class="directory">/proc</filename> file system
127 (procfs) is a special file system in the linux kernel. It's a
128 virtual file system: it is not associated with a block device
129 but exists only in memory. The files in the procfs are there to
130 allow userland programs access to certain information from the
131 kernel (like process information in <filename
132 class="directory">/proc/[0-9]+/</filename>), but also for debug
133 purposes (like <filename>/proc/ksyms</filename>).
134 </para>
135
136 <para>
137 This guide describes the use of the procfs file system from
138 within the Linux kernel. It starts by introducing all relevant
139 functions to manage the files within the file system. After that
140 it shows how to communicate with userland, and some tips and
141 tricks will be pointed out. Finally a complete example will be
142 shown.
143 </para>
144
145 <para>
146 Note that the files in <filename
147 class="directory">/proc/sys</filename> are sysctl files: they
148 don't belong to procfs and are governed by a completely
149 different API described in the Kernel API book.
150 </para>
151 </chapter>
152
153
154
155
156 <chapter id="managing">
157 <title>Managing procfs entries</title>
158
159 <para>
160 This chapter describes the functions that various kernel
161 components use to populate the procfs with files, symlinks,
162 device nodes, and directories.
163 </para>
164
165 <para>
166 A minor note before we start: if you want to use any of the
167 procfs functions, be sure to include the correct header file!
168 This should be one of the first lines in your code:
169 </para>
170
171 <programlisting>
172#include &lt;linux/proc_fs.h&gt;
173 </programlisting>
174
175
176
177
178 <sect1 id="regularfile">
179 <title>Creating a regular file</title>
180
181 <funcsynopsis>
182 <funcprototype>
183 <funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef>
184 <paramdef>const char* <parameter>name</parameter></paramdef>
185 <paramdef>mode_t <parameter>mode</parameter></paramdef>
186 <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
187 </funcprototype>
188 </funcsynopsis>
189
190 <para>
191 This function creates a regular file with the name
192 <parameter>name</parameter>, file mode
193 <parameter>mode</parameter> in the directory
194 <parameter>parent</parameter>. To create a file in the root of
195 the procfs, use <constant>NULL</constant> as
196 <parameter>parent</parameter> parameter. When successful, the
197 function will return a pointer to the freshly created
198 <structname>struct proc_dir_entry</structname>; otherwise it
199 will return <constant>NULL</constant>. <xref
200 linkend="userland"/> describes how to do something useful with
201 regular files.
202 </para>
203
204 <para>
205 Note that it is specifically supported that you can pass a
206 path that spans multiple directories. For example
207 <function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>)
208 will create the <filename class="directory">via0</filename>
209 directory if necessary, with standard
210 <constant>0755</constant> permissions.
211 </para>
212
213 <para>
214 If you only want to be able to read the file, the function
215 <function>create_proc_read_entry</function> described in <xref
216 linkend="convenience"/> may be used to create and initialise
217 the procfs entry in one single call.
218 </para>
219 </sect1>
220
221
222
223
224 <sect1 id="Creating_a_symlink">
225 <title>Creating a symlink</title>
226
227 <funcsynopsis>
228 <funcprototype>
229 <funcdef>struct proc_dir_entry*
230 <function>proc_symlink</function></funcdef> <paramdef>const
231 char* <parameter>name</parameter></paramdef>
232 <paramdef>struct proc_dir_entry*
233 <parameter>parent</parameter></paramdef> <paramdef>const
234 char* <parameter>dest</parameter></paramdef>
235 </funcprototype>
236 </funcsynopsis>
237
238 <para>
239 This creates a symlink in the procfs directory
240 <parameter>parent</parameter> that points from
241 <parameter>name</parameter> to
242 <parameter>dest</parameter>. This translates in userland to
243 <literal>ln -s</literal> <parameter>dest</parameter>
244 <parameter>name</parameter>.
245 </para>
246 </sect1>
247
248 <sect1 id="Creating_a_directory">
249 <title>Creating a directory</title>
250
251 <funcsynopsis>
252 <funcprototype>
253 <funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef>
254 <paramdef>const char* <parameter>name</parameter></paramdef>
255 <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
256 </funcprototype>
257 </funcsynopsis>
258
259 <para>
260 Create a directory <parameter>name</parameter> in the procfs
261 directory <parameter>parent</parameter>.
262 </para>
263 </sect1>
264
265
266
267
268 <sect1 id="Removing_an_entry">
269 <title>Removing an entry</title>
270
271 <funcsynopsis>
272 <funcprototype>
273 <funcdef>void <function>remove_proc_entry</function></funcdef>
274 <paramdef>const char* <parameter>name</parameter></paramdef>
275 <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
276 </funcprototype>
277 </funcsynopsis>
278
279 <para>
280 Removes the entry <parameter>name</parameter> in the directory
281 <parameter>parent</parameter> from the procfs. Entries are
282 removed by their <emphasis>name</emphasis>, not by the
283 <structname>struct proc_dir_entry</structname> returned by the
284 various create functions. Note that this function doesn't
285 recursively remove entries.
286 </para>
287
288 <para>
289 Be sure to free the <structfield>data</structfield> entry from
290 the <structname>struct proc_dir_entry</structname> before
291 <function>remove_proc_entry</function> is called (that is: if
292 there was some <structfield>data</structfield> allocated, of
293 course). See <xref linkend="usingdata"/> for more information
294 on using the <structfield>data</structfield> entry.
295 </para>
296 </sect1>
297 </chapter>
298
299
300
301
302 <chapter id="userland">
303 <title>Communicating with userland</title>
304
305 <para>
306 Instead of reading (or writing) information directly from
307 kernel memory, procfs works with <emphasis>call back
308 functions</emphasis> for files: functions that are called when
309 a specific file is being read or written. Such functions have
310 to be initialised after the procfs file is created by setting
311 the <structfield>read_proc</structfield> and/or
312 <structfield>write_proc</structfield> fields in the
313 <structname>struct proc_dir_entry*</structname> that the
314 function <function>create_proc_entry</function> returned:
315 </para>
316
317 <programlisting>
318struct proc_dir_entry* entry;
319
320entry->read_proc = read_proc_foo;
321entry->write_proc = write_proc_foo;
322 </programlisting>
323
324 <para>
325 If you only want to use a the
326 <structfield>read_proc</structfield>, the function
327 <function>create_proc_read_entry</function> described in <xref
328 linkend="convenience"/> may be used to create and initialise the
329 procfs entry in one single call.
330 </para>
331
332
333
334 <sect1 id="Reading_data">
335 <title>Reading data</title>
336
337 <para>
338 The read function is a call back function that allows userland
339 processes to read data from the kernel. The read function
340 should have the following format:
341 </para>
342
343 <funcsynopsis>
344 <funcprototype>
345 <funcdef>int <function>read_func</function></funcdef>
346 <paramdef>char* <parameter>buffer</parameter></paramdef>
347 <paramdef>char** <parameter>start</parameter></paramdef>
348 <paramdef>off_t <parameter>off</parameter></paramdef>
349 <paramdef>int <parameter>count</parameter></paramdef>
350 <paramdef>int* <parameter>peof</parameter></paramdef>
351 <paramdef>void* <parameter>data</parameter></paramdef>
352 </funcprototype>
353 </funcsynopsis>
354
355 <para>
356 The read function should write its information into the
357 <parameter>buffer</parameter>, which will be exactly
358 <literal>PAGE_SIZE</literal> bytes long.
359 </para>
360
361 <para>
362 The parameter
363 <parameter>peof</parameter> should be used to signal that the
364 end of the file has been reached by writing
365 <literal>1</literal> to the memory location
366 <parameter>peof</parameter> points to.
367 </para>
368
369 <para>
370 The <parameter>data</parameter>
371 parameter can be used to create a single call back function for
372 several files, see <xref linkend="usingdata"/>.
373 </para>
374
375 <para>
376 The rest of the parameters and the return value are described
377 by a comment in <filename>fs/proc/generic.c</filename> as follows:
378 </para>
379
380 <blockquote>
381 <para>
382 You have three ways to return data:
383 </para>
384 <orderedlist>
385 <listitem>
386 <para>
387 Leave <literal>*start = NULL</literal>. (This is the default.)
388 Put the data of the requested offset at that
389 offset within the buffer. Return the number (<literal>n</literal>)
390 of bytes there are from the beginning of the
391 buffer up to the last byte of data. If the
392 number of supplied bytes (<literal>= n - offset</literal>) is
393 greater than zero and you didn't signal eof
394 and the reader is prepared to take more data
395 you will be called again with the requested
396 offset advanced by the number of bytes
397 absorbed. This interface is useful for files
398 no larger than the buffer.
399 </para>
400 </listitem>
401 <listitem>
402 <para>
403 Set <literal>*start</literal> to an unsigned long value less than
404 the buffer address but greater than zero.
405 Put the data of the requested offset at the
406 beginning of the buffer. Return the number of
407 bytes of data placed there. If this number is
408 greater than zero and you didn't signal eof
409 and the reader is prepared to take more data
410 you will be called again with the requested
411 offset advanced by <literal>*start</literal>. This interface is
412 useful when you have a large file consisting
413 of a series of blocks which you want to count
414 and return as wholes.
415 (Hack by Paul.Russell@rustcorp.com.au)
416 </para>
417 </listitem>
418 <listitem>
419 <para>
420 Set <literal>*start</literal> to an address within the buffer.
421 Put the data of the requested offset at <literal>*start</literal>.
422 Return the number of bytes of data placed there.
423 If this number is greater than zero and you
424 didn't signal eof and the reader is prepared to
425 take more data you will be called again with the
426 requested offset advanced by the number of bytes
427 absorbed.
428 </para>
429 </listitem>
430 </orderedlist>
431 </blockquote>
432
433 <para>
434 <xref linkend="example"/> shows how to use a read call back
435 function.
436 </para>
437 </sect1>
438
439
440
441
442 <sect1 id="Writing_data">
443 <title>Writing data</title>
444
445 <para>
446 The write call back function allows a userland process to write
447 data to the kernel, so it has some kind of control over the
448 kernel. The write function should have the following format:
449 </para>
450
451 <funcsynopsis>
452 <funcprototype>
453 <funcdef>int <function>write_func</function></funcdef>
454 <paramdef>struct file* <parameter>file</parameter></paramdef>
455 <paramdef>const char* <parameter>buffer</parameter></paramdef>
456 <paramdef>unsigned long <parameter>count</parameter></paramdef>
457 <paramdef>void* <parameter>data</parameter></paramdef>
458 </funcprototype>
459 </funcsynopsis>
460
461 <para>
462 The write function should read <parameter>count</parameter>
463 bytes at maximum from the <parameter>buffer</parameter>. Note
464 that the <parameter>buffer</parameter> doesn't live in the
465 kernel's memory space, so it should first be copied to kernel
466 space with <function>copy_from_user</function>. The
467 <parameter>file</parameter> parameter is usually
468 ignored. <xref linkend="usingdata"/> shows how to use the
469 <parameter>data</parameter> parameter.
470 </para>
471
472 <para>
473 Again, <xref linkend="example"/> shows how to use this call back
474 function.
475 </para>
476 </sect1>
477
478
479
480
481 <sect1 id="usingdata">
482 <title>A single call back for many files</title>
483
484 <para>
485 When a large number of almost identical files is used, it's
486 quite inconvenient to use a separate call back function for
487 each file. A better approach is to have a single call back
488 function that distinguishes between the files by using the
489 <structfield>data</structfield> field in <structname>struct
490 proc_dir_entry</structname>. First of all, the
491 <structfield>data</structfield> field has to be initialised:
492 </para>
493
494 <programlisting>
495struct proc_dir_entry* entry;
496struct my_file_data *file_data;
497
498file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
499entry->data = file_data;
500 </programlisting>
501
502 <para>
503 The <structfield>data</structfield> field is a <type>void
504 *</type>, so it can be initialised with anything.
505 </para>
506
507 <para>
508 Now that the <structfield>data</structfield> field is set, the
509 <function>read_proc</function> and
510 <function>write_proc</function> can use it to distinguish
511 between files because they get it passed into their
512 <parameter>data</parameter> parameter:
513 </para>
514
515 <programlisting>
516int foo_read_func(char *page, char **start, off_t off,
517 int count, int *eof, void *data)
518{
519 int len;
520
521 if(data == file_data) {
522 /* special case for this file */
523 } else {
524 /* normal processing */
525 }
526
527 return len;
528}
529 </programlisting>
530
531 <para>
532 Be sure to free the <structfield>data</structfield> data field
533 when removing the procfs entry.
534 </para>
535 </sect1>
536 </chapter>
537
538
539
540
541 <chapter id="tips">
542 <title>Tips and tricks</title>
543
544
545
546
547 <sect1 id="convenience">
548 <title>Convenience functions</title>
549
550 <funcsynopsis>
551 <funcprototype>
552 <funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef>
553 <paramdef>const char* <parameter>name</parameter></paramdef>
554 <paramdef>mode_t <parameter>mode</parameter></paramdef>
555 <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
556 <paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef>
557 <paramdef>void* <parameter>data</parameter></paramdef>
558 </funcprototype>
559 </funcsynopsis>
560
561 <para>
562 This function creates a regular file in exactly the same way
563 as <function>create_proc_entry</function> from <xref
564 linkend="regularfile"/> does, but also allows to set the read
565 function <parameter>read_proc</parameter> in one call. This
566 function can set the <parameter>data</parameter> as well, like
567 explained in <xref linkend="usingdata"/>.
568 </para>
569 </sect1>
570
571
572
573 <sect1 id="Modules">
574 <title>Modules</title>
575
576 <para>
577 If procfs is being used from within a module, be sure to set
578 the <structfield>owner</structfield> field in the
579 <structname>struct proc_dir_entry</structname> to
580 <constant>THIS_MODULE</constant>.
581 </para>
582
583 <programlisting>
584struct proc_dir_entry* entry;
585
586entry->owner = THIS_MODULE;
587 </programlisting>
588 </sect1>
589
590
591
592
593 <sect1 id="Mode_and_ownership">
594 <title>Mode and ownership</title>
595
596 <para>
597 Sometimes it is useful to change the mode and/or ownership of
598 a procfs entry. Here is an example that shows how to achieve
599 that:
600 </para>
601
602 <programlisting>
603struct proc_dir_entry* entry;
604
605entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
606entry->uid = 0;
607entry->gid = 100;
608 </programlisting>
609
610 </sect1>
611 </chapter>
612
613
614
615
616 <chapter id="example">
617 <title>Example</title>
618
619 <!-- be careful with the example code: it shouldn't be wider than
620 approx. 60 columns, or otherwise it won't fit properly on a page
621 -->
622
623&procfsexample;
624
625 </chapter>
626</book>
diff --git a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c
deleted file mode 100644
index a5b11793b1e0..000000000000
--- a/Documentation/DocBook/procfs_example.c
+++ /dev/null
@@ -1,201 +0,0 @@
1/*
2 * procfs_example.c: an example proc interface
3 *
4 * Copyright (C) 2001, Erik Mouw (mouw@nl.linux.org)
5 *
6 * This file accompanies the procfs-guide in the Linux kernel
7 * source. Its main use is to demonstrate the concepts and
8 * functions described in the guide.
9 *
10 * This software has been developed while working on the LART
11 * computing board (http://www.lartmaker.nl), which was sponsored
12 * by the Delt University of Technology projects Mobile Multi-media
13 * Communications and Ubiquitous Communications.
14 *
15 * This program is free software; you can redistribute
16 * it and/or modify it under the terms of the GNU General
17 * Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your
19 * option) any later version.
20 *
21 * This program is distributed in the hope that it will be
22 * useful, but WITHOUT ANY WARRANTY; without even the implied
23 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
24 * PURPOSE. See the GNU General Public License for more
25 * details.
26 *
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, write to the
29 * Free Software Foundation, Inc., 59 Temple Place,
30 * Suite 330, Boston, MA 02111-1307 USA
31 *
32 */
33
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <linux/proc_fs.h>
38#include <linux/jiffies.h>
39#include <asm/uaccess.h>
40
41
42#define MODULE_VERS "1.0"
43#define MODULE_NAME "procfs_example"
44
45#define FOOBAR_LEN 8
46
47struct fb_data_t {
48 char name[FOOBAR_LEN + 1];
49 char value[FOOBAR_LEN + 1];
50};
51
52
53static struct proc_dir_entry *example_dir, *foo_file,
54 *bar_file, *jiffies_file, *symlink;
55
56
57struct fb_data_t foo_data, bar_data;
58
59
60static int proc_read_jiffies(char *page, char **start,
61 off_t off, int count,
62 int *eof, void *data)
63{
64 int len;
65
66 len = sprintf(page, "jiffies = %ld\n",
67 jiffies);
68
69 return len;
70}
71
72
73static int proc_read_foobar(char *page, char **start,
74 off_t off, int count,
75 int *eof, void *data)
76{
77 int len;
78 struct fb_data_t *fb_data = (struct fb_data_t *)data;
79
80 /* DON'T DO THAT - buffer overruns are bad */
81 len = sprintf(page, "%s = '%s'\n",
82 fb_data->name, fb_data->value);
83
84 return len;
85}
86
87
88static int proc_write_foobar(struct file *file,
89 const char *buffer,
90 unsigned long count,
91 void *data)
92{
93 int len;
94 struct fb_data_t *fb_data = (struct fb_data_t *)data;
95
96 if(count > FOOBAR_LEN)
97 len = FOOBAR_LEN;
98 else
99 len = count;
100
101 if(copy_from_user(fb_data->value, buffer, len))
102 return -EFAULT;
103
104 fb_data->value[len] = '\0';
105
106 return len;
107}
108
109
110static int __init init_procfs_example(void)
111{
112 int rv = 0;
113
114 /* create directory */
115 example_dir = proc_mkdir(MODULE_NAME, NULL);
116 if(example_dir == NULL) {
117 rv = -ENOMEM;
118 goto out;
119 }
120 /* create jiffies using convenience function */
121 jiffies_file = create_proc_read_entry("jiffies",
122 0444, example_dir,
123 proc_read_jiffies,
124 NULL);
125 if(jiffies_file == NULL) {
126 rv = -ENOMEM;
127 goto no_jiffies;
128 }
129
130 /* create foo and bar files using same callback
131 * functions
132 */
133 foo_file = create_proc_entry("foo", 0644, example_dir);
134 if(foo_file == NULL) {
135 rv = -ENOMEM;
136 goto no_foo;
137 }
138
139 strcpy(foo_data.name, "foo");
140 strcpy(foo_data.value, "foo");
141 foo_file->data = &foo_data;
142 foo_file->read_proc = proc_read_foobar;
143 foo_file->write_proc = proc_write_foobar;
144
145 bar_file = create_proc_entry("bar", 0644, example_dir);
146 if(bar_file == NULL) {
147 rv = -ENOMEM;
148 goto no_bar;
149 }
150
151 strcpy(bar_data.name, "bar");
152 strcpy(bar_data.value, "bar");
153 bar_file->data = &bar_data;
154 bar_file->read_proc = proc_read_foobar;
155 bar_file->write_proc = proc_write_foobar;
156
157 /* create symlink */
158 symlink = proc_symlink("jiffies_too", example_dir,
159 "jiffies");
160 if(symlink == NULL) {
161 rv = -ENOMEM;
162 goto no_symlink;
163 }
164
165 /* everything OK */
166 printk(KERN_INFO "%s %s initialised\n",
167 MODULE_NAME, MODULE_VERS);
168 return 0;
169
170no_symlink:
171 remove_proc_entry("bar", example_dir);
172no_bar:
173 remove_proc_entry("foo", example_dir);
174no_foo:
175 remove_proc_entry("jiffies", example_dir);
176no_jiffies:
177 remove_proc_entry(MODULE_NAME, NULL);
178out:
179 return rv;
180}
181
182
183static void __exit cleanup_procfs_example(void)
184{
185 remove_proc_entry("jiffies_too", example_dir);
186 remove_proc_entry("bar", example_dir);
187 remove_proc_entry("foo", example_dir);
188 remove_proc_entry("jiffies", example_dir);
189 remove_proc_entry(MODULE_NAME, NULL);
190
191 printk(KERN_INFO "%s %s removed\n",
192 MODULE_NAME, MODULE_VERS);
193}
194
195
196module_init(init_procfs_example);
197module_exit(cleanup_procfs_example);
198
199MODULE_AUTHOR("Erik Mouw");
200MODULE_DESCRIPTION("procfs examples");
201MODULE_LICENSE("GPL");