]> bbs.cooldavid.org Git - net-next-2.6.git/blame - samples/kfifo/bytestream-example.c
kfifo: add explicit error checking in all the examples
[net-next-2.6.git] / samples / kfifo / bytestream-example.c
CommitLineData
5bf2b193
SS
1/*
2 * Sample kfifo byte stream implementation
3 *
4 * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
5 *
6 * Released under the GPL version 2 only.
7 *
8 */
9
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/proc_fs.h>
13#include <linux/mutex.h>
14#include <linux/kfifo.h>
15
16/*
17 * This module shows how to create a byte stream fifo.
18 */
19
20/* fifo size in elements (bytes) */
21#define FIFO_SIZE 32
22
23/* name of the proc entry */
24#define PROC_FIFO "bytestream-fifo"
25
26/* lock for procfs read access */
27static DEFINE_MUTEX(read_lock);
28
29/* lock for procfs write access */
30static DEFINE_MUTEX(write_lock);
31
32/*
33 * define DYNAMIC in this example for a dynamically allocated fifo.
34 *
35 * Otherwise the fifo storage will be a part of the fifo structure.
36 */
37#if 0
38#define DYNAMIC
39#endif
40
41#ifdef DYNAMIC
42static struct kfifo test;
43#else
44static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);
45#endif
46
a25effa4 47static const unsigned char expected_result[FIFO_SIZE] = {
2aaf2092
AR
48 3, 4, 5, 6, 7, 8, 9, 0,
49 1, 20, 21, 22, 23, 24, 25, 26,
50 27, 28, 29, 30, 31, 32, 33, 34,
51 35, 36, 37, 38, 39, 40, 41, 42,
52};
53
5bf2b193
SS
54static int __init testfunc(void)
55{
56 unsigned char buf[6];
2aaf2092 57 unsigned char i, j;
5bf2b193
SS
58 unsigned int ret;
59
60 printk(KERN_INFO "byte stream fifo test start\n");
61
62 /* put string into the fifo */
63 kfifo_in(&test, "hello", 5);
64
65 /* put values into the fifo */
66 for (i = 0; i != 10; i++)
67 kfifo_put(&test, &i);
68
69 /* show the number of used elements */
70 printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
71
72 /* get max of 5 bytes from the fifo */
73 i = kfifo_out(&test, buf, 5);
74 printk(KERN_INFO "buf: %.*s\n", i, buf);
75
76 /* get max of 2 elements from the fifo */
77 ret = kfifo_out(&test, buf, 2);
78 printk(KERN_INFO "ret: %d\n", ret);
79 /* and put it back to the end of the fifo */
80 ret = kfifo_in(&test, buf, ret);
81 printk(KERN_INFO "ret: %d\n", ret);
82
5ddf8391
AR
83 /* skip first element of the fifo */
84 printk(KERN_INFO "skip 1st element\n");
85 kfifo_skip(&test);
86
5bf2b193
SS
87 /* put values into the fifo until is full */
88 for (i = 20; kfifo_put(&test, &i); i++)
89 ;
90
91 printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
92
a25effa4
AR
93 /* show the first value without removing from the fifo */
94 if (kfifo_peek(&test, &i))
95 printk(KERN_INFO "%d\n", i);
96
2aaf2092
AR
97 /* check the correctness of all values in the fifo */
98 j = 0;
99 while (kfifo_get(&test, &i)) {
a25effa4 100 printk(KERN_INFO "item = %d\n", i);
2aaf2092
AR
101 if (i != expected_result[j++]) {
102 printk(KERN_WARNING "value mismatch: test failed\n");
103 return -EIO;
104 }
105 }
106 if (j != ARRAY_SIZE(expected_result)) {
107 printk(KERN_WARNING "size mismatch: test failed\n");
108 return -EIO;
109 }
110 printk(KERN_INFO "test passed\n");
5bf2b193
SS
111
112 return 0;
113}
114
115static ssize_t fifo_write(struct file *file, const char __user *buf,
116 size_t count, loff_t *ppos)
117{
118 int ret;
119 unsigned int copied;
120
121 if (mutex_lock_interruptible(&write_lock))
122 return -ERESTARTSYS;
123
124 ret = kfifo_from_user(&test, buf, count, &copied);
125
126 mutex_unlock(&write_lock);
127
128 return ret ? ret : copied;
129}
130
131static ssize_t fifo_read(struct file *file, char __user *buf,
132 size_t count, loff_t *ppos)
133{
134 int ret;
135 unsigned int copied;
136
137 if (mutex_lock_interruptible(&read_lock))
138 return -ERESTARTSYS;
139
140 ret = kfifo_to_user(&test, buf, count, &copied);
141
142 mutex_unlock(&read_lock);
143
144 return ret ? ret : copied;
145}
146
147static const struct file_operations fifo_fops = {
148 .owner = THIS_MODULE,
149 .read = fifo_read,
150 .write = fifo_write,
151};
152
153static int __init example_init(void)
154{
155#ifdef DYNAMIC
156 int ret;
157
158 ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
159 if (ret) {
160 printk(KERN_ERR "error kfifo_alloc\n");
161 return ret;
162 }
163#else
164 INIT_KFIFO(test);
165#endif
2aaf2092
AR
166 if (testfunc() < 0) {
167#ifdef DYNAMIC
168 kfifo_free(&test);
169#endif
170 return -EIO;
171 }
5bf2b193
SS
172
173 if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
174#ifdef DYNAMIC
175 kfifo_free(&test);
176#endif
177 return -ENOMEM;
178 }
179 return 0;
180}
181
182static void __exit example_exit(void)
183{
184 remove_proc_entry(PROC_FIFO, NULL);
185#ifdef DYNAMIC
186 kfifo_free(&test);
187#endif
188}
189
190module_init(example_init);
191module_exit(example_exit);
192MODULE_LICENSE("GPL");
193MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");