record-example.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Sample dynamic sized record fifo implementation
  3. *
  4. * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
  5. *
  6. * Released under the GPL version 2 only.
  7. *
  8. */
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/proc_fs.h>
  12. #include <linux/mutex.h>
  13. #include <linux/kfifo.h>
  14. /*
  15. * This module shows how to create a variable sized record fifo.
  16. */
  17. /* fifo size in elements (bytes) */
  18. #define FIFO_SIZE 128
  19. /* name of the proc entry */
  20. #define PROC_FIFO "record-fifo"
  21. /* lock for procfs read access */
  22. static DEFINE_MUTEX(read_lock);
  23. /* lock for procfs write access */
  24. static DEFINE_MUTEX(write_lock);
  25. /*
  26. * define DYNAMIC in this example for a dynamically allocated fifo.
  27. *
  28. * Otherwise the fifo storage will be a part of the fifo structure.
  29. */
  30. #if 0
  31. #define DYNAMIC
  32. #endif
  33. /*
  34. * struct kfifo_rec_ptr_1 and STRUCT_KFIFO_REC_1 can handle records of a
  35. * length between 0 and 255 bytes.
  36. *
  37. * struct kfifo_rec_ptr_2 and STRUCT_KFIFO_REC_2 can handle records of a
  38. * length between 0 and 65535 bytes.
  39. */
  40. #ifdef DYNAMIC
  41. struct kfifo_rec_ptr_1 test;
  42. #else
  43. typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest;
  44. static mytest test;
  45. #endif
  46. static const char *expected_result[] = {
  47. "a",
  48. "bb",
  49. "ccc",
  50. "dddd",
  51. "eeeee",
  52. "ffffff",
  53. "ggggggg",
  54. "hhhhhhhh",
  55. "iiiiiiiii",
  56. "jjjjjjjjjj",
  57. };
  58. static int __init testfunc(void)
  59. {
  60. char buf[100];
  61. unsigned int i;
  62. unsigned int ret;
  63. struct { unsigned char buf[6]; } hello = { "hello" };
  64. printk(KERN_INFO "record fifo test start\n");
  65. kfifo_in(&test, &hello, sizeof(hello));
  66. /* show the size of the next record in the fifo */
  67. printk(KERN_INFO "fifo peek len: %u\n", kfifo_peek_len(&test));
  68. /* put in variable length data */
  69. for (i = 0; i < 10; i++) {
  70. memset(buf, 'a' + i, i + 1);
  71. kfifo_in(&test, buf, i + 1);
  72. }
  73. /* skip first element of the fifo */
  74. printk(KERN_INFO "skip 1st element\n");
  75. kfifo_skip(&test);
  76. printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));
  77. /* show the first record without removing from the fifo */
  78. ret = kfifo_out_peek(&test, buf, sizeof(buf));
  79. if (ret)
  80. printk(KERN_INFO "%.*s\n", ret, buf);
  81. /* check the correctness of all values in the fifo */
  82. i = 0;
  83. while (!kfifo_is_empty(&test)) {
  84. ret = kfifo_out(&test, buf, sizeof(buf));
  85. buf[ret] = '\0';
  86. printk(KERN_INFO "item = %.*s\n", ret, buf);
  87. if (strcmp(buf, expected_result[i++])) {
  88. printk(KERN_WARNING "value mismatch: test failed\n");
  89. return -EIO;
  90. }
  91. }
  92. if (i != ARRAY_SIZE(expected_result)) {
  93. printk(KERN_WARNING "size mismatch: test failed\n");
  94. return -EIO;
  95. }
  96. printk(KERN_INFO "test passed\n");
  97. return 0;
  98. }
  99. static ssize_t fifo_write(struct file *file, const char __user *buf,
  100. size_t count, loff_t *ppos)
  101. {
  102. int ret;
  103. unsigned int copied;
  104. if (mutex_lock_interruptible(&write_lock))
  105. return -ERESTARTSYS;
  106. ret = kfifo_from_user(&test, buf, count, &copied);
  107. mutex_unlock(&write_lock);
  108. return ret ? ret : copied;
  109. }
  110. static ssize_t fifo_read(struct file *file, char __user *buf,
  111. size_t count, loff_t *ppos)
  112. {
  113. int ret;
  114. unsigned int copied;
  115. if (mutex_lock_interruptible(&read_lock))
  116. return -ERESTARTSYS;
  117. ret = kfifo_to_user(&test, buf, count, &copied);
  118. mutex_unlock(&read_lock);
  119. return ret ? ret : copied;
  120. }
  121. static const struct file_operations fifo_fops = {
  122. .owner = THIS_MODULE,
  123. .read = fifo_read,
  124. .write = fifo_write,
  125. .llseek = noop_llseek,
  126. };
  127. static int __init example_init(void)
  128. {
  129. #ifdef DYNAMIC
  130. int ret;
  131. ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
  132. if (ret) {
  133. printk(KERN_ERR "error kfifo_alloc\n");
  134. return ret;
  135. }
  136. #else
  137. INIT_KFIFO(test);
  138. #endif
  139. if (testfunc() < 0) {
  140. #ifdef DYNAMIC
  141. kfifo_free(&test);
  142. #endif
  143. return -EIO;
  144. }
  145. if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
  146. #ifdef DYNAMIC
  147. kfifo_free(&test);
  148. #endif
  149. return -ENOMEM;
  150. }
  151. return 0;
  152. }
  153. static void __exit example_exit(void)
  154. {
  155. remove_proc_entry(PROC_FIFO, NULL);
  156. #ifdef DYNAMIC
  157. kfifo_free(&test);
  158. #endif
  159. }
  160. module_init(example_init);
  161. module_exit(example_exit);
  162. MODULE_LICENSE("GPL");
  163. MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");