jffs_proc.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * JFFS -- Journaling Flash File System, Linux implementation.
  3. *
  4. * Copyright (C) 2000 Axis Communications AB.
  5. *
  6. * Created by Simon Kagstrom <simonk@axis.com>.
  7. *
  8. * $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $
  9. *
  10. * This is free software; you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * Overview:
  16. * This file defines JFFS partition entries in the proc file system.
  17. *
  18. * TODO:
  19. * Create some more proc files for different kinds of info, i.e. statistics
  20. * about written and read bytes, number of calls to different routines,
  21. * reports about failures.
  22. */
  23. #include <linux/errno.h>
  24. #include <linux/fs.h>
  25. #include <linux/jffs.h>
  26. #include <linux/slab.h>
  27. #include <linux/proc_fs.h>
  28. #include <linux/time.h>
  29. #include <linux/types.h>
  30. #include "jffs_fm.h"
  31. #include "jffs_proc.h"
  32. /*
  33. * Structure for a JFFS partition in the system
  34. */
  35. struct jffs_partition_dir {
  36. struct jffs_control *c;
  37. struct proc_dir_entry *part_root;
  38. struct proc_dir_entry *part_info;
  39. struct proc_dir_entry *part_layout;
  40. struct jffs_partition_dir *next;
  41. };
  42. /*
  43. * Structure for top-level entry in '/proc/fs' directory
  44. */
  45. struct proc_dir_entry *jffs_proc_root;
  46. /*
  47. * Linked list of 'jffs_partition_dirs' to help us track
  48. * the mounted JFFS partitions in the system
  49. */
  50. static struct jffs_partition_dir *jffs_part_dirs;
  51. /*
  52. * Read functions for entries
  53. */
  54. static int jffs_proc_info_read(char *page, char **start, off_t off,
  55. int count, int *eof, void *data);
  56. static int jffs_proc_layout_read (char *page, char **start, off_t off,
  57. int count, int *eof, void *data);
  58. /*
  59. * Register a JFFS partition directory (called upon mount)
  60. */
  61. int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c)
  62. {
  63. struct jffs_partition_dir *part_dir;
  64. struct proc_dir_entry *part_info = NULL;
  65. struct proc_dir_entry *part_layout = NULL;
  66. struct proc_dir_entry *part_root = NULL;
  67. char name[10];
  68. sprintf(name, "%d", mtd);
  69. /* Allocate structure for local JFFS partition table */
  70. part_dir = (struct jffs_partition_dir *)
  71. kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL);
  72. if (!part_dir)
  73. goto out;
  74. /* Create entry for this partition */
  75. part_root = proc_mkdir(name, jffs_proc_root);
  76. if (!part_root)
  77. goto out1;
  78. /* Create entry for 'info' file */
  79. part_info = create_proc_entry ("info", 0, part_root);
  80. if (!part_info)
  81. goto out2;
  82. part_info->read_proc = jffs_proc_info_read;
  83. part_info->data = (void *) c;
  84. /* Create entry for 'layout' file */
  85. part_layout = create_proc_entry ("layout", 0, part_root);
  86. if (!part_layout)
  87. goto out3;
  88. part_layout->read_proc = jffs_proc_layout_read;
  89. part_layout->data = (void *) c;
  90. /* Fill in structure for table and insert in the list */
  91. part_dir->c = c;
  92. part_dir->part_root = part_root;
  93. part_dir->part_info = part_info;
  94. part_dir->part_layout = part_layout;
  95. part_dir->next = jffs_part_dirs;
  96. jffs_part_dirs = part_dir;
  97. /* Return happy */
  98. return 0;
  99. out3:
  100. remove_proc_entry("info", part_root);
  101. out2:
  102. remove_proc_entry(name, jffs_proc_root);
  103. out1:
  104. kfree(part_dir);
  105. out:
  106. return -ENOMEM;
  107. }
  108. /*
  109. * Unregister a JFFS partition directory (called at umount)
  110. */
  111. int jffs_unregister_jffs_proc_dir(struct jffs_control *c)
  112. {
  113. struct jffs_partition_dir *part_dir = jffs_part_dirs;
  114. struct jffs_partition_dir *prev_part_dir = NULL;
  115. while (part_dir) {
  116. if (part_dir->c == c) {
  117. /* Remove entries for partition */
  118. remove_proc_entry (part_dir->part_info->name,
  119. part_dir->part_root);
  120. remove_proc_entry (part_dir->part_layout->name,
  121. part_dir->part_root);
  122. remove_proc_entry (part_dir->part_root->name,
  123. jffs_proc_root);
  124. /* Remove entry from list */
  125. if (prev_part_dir)
  126. prev_part_dir->next = part_dir->next;
  127. else
  128. jffs_part_dirs = part_dir->next;
  129. /*
  130. * Check to see if this is the last one
  131. * and remove the entry from '/proc/fs'
  132. * if it is.
  133. */
  134. if (jffs_part_dirs == part_dir->next)
  135. remove_proc_entry ("jffs", proc_root_fs);
  136. /* Free memory for entry */
  137. kfree(part_dir);
  138. /* Return happy */
  139. return 0;
  140. }
  141. /* Move to next entry */
  142. prev_part_dir = part_dir;
  143. part_dir = part_dir->next;
  144. }
  145. /* Return unhappy */
  146. return -1;
  147. }
  148. /*
  149. * Read a JFFS partition's `info' file
  150. */
  151. static int jffs_proc_info_read (char *page, char **start, off_t off,
  152. int count, int *eof, void *data)
  153. {
  154. struct jffs_control *c = (struct jffs_control *) data;
  155. int len = 0;
  156. /* Get information on the parition */
  157. len += sprintf (page,
  158. "partition size: %08lX (%u)\n"
  159. "sector size: %08lX (%u)\n"
  160. "used size: %08lX (%u)\n"
  161. "dirty size: %08lX (%u)\n"
  162. "free size: %08lX (%u)\n\n",
  163. (unsigned long) c->fmc->flash_size, c->fmc->flash_size,
  164. (unsigned long) c->fmc->sector_size, c->fmc->sector_size,
  165. (unsigned long) c->fmc->used_size, c->fmc->used_size,
  166. (unsigned long) c->fmc->dirty_size, c->fmc->dirty_size,
  167. (unsigned long) (c->fmc->flash_size -
  168. (c->fmc->used_size + c->fmc->dirty_size)),
  169. c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size));
  170. /* We're done */
  171. *eof = 1;
  172. /* Return length */
  173. return len;
  174. }
  175. /*
  176. * Read a JFFS partition's `layout' file
  177. */
  178. static int jffs_proc_layout_read (char *page, char **start, off_t off,
  179. int count, int *eof, void *data)
  180. {
  181. struct jffs_control *c = (struct jffs_control *) data;
  182. struct jffs_fm *fm = NULL;
  183. struct jffs_fm *last_fm = NULL;
  184. int len = 0;
  185. /* Get the first item in the list */
  186. fm = c->fmc->head;
  187. /* Print free space */
  188. if (fm && fm->offset) {
  189. len += sprintf (page, "00000000 %08lX free\n",
  190. (unsigned long) fm->offset);
  191. }
  192. /* Loop through all of the flash control structures */
  193. while (fm && (len < (off + count))) {
  194. if (fm->nodes) {
  195. len += sprintf (page + len,
  196. "%08lX %08lX ino=%08lX, ver=%08lX\n",
  197. (unsigned long) fm->offset,
  198. (unsigned long) fm->size,
  199. (unsigned long) fm->nodes->node->ino,
  200. (unsigned long) fm->nodes->node->version);
  201. }
  202. else {
  203. len += sprintf (page + len,
  204. "%08lX %08lX dirty\n",
  205. (unsigned long) fm->offset,
  206. (unsigned long) fm->size);
  207. }
  208. last_fm = fm;
  209. fm = fm->next;
  210. }
  211. /* Print free space */
  212. if ((len < (off + count)) && last_fm
  213. && (last_fm->offset < c->fmc->flash_size)) {
  214. len += sprintf (page + len,
  215. "%08lX %08lX free\n",
  216. (unsigned long) last_fm->offset +
  217. last_fm->size,
  218. (unsigned long) (c->fmc->flash_size -
  219. (last_fm->offset + last_fm->size)));
  220. }
  221. /* We're done */
  222. *eof = 1;
  223. /* Return length */
  224. return len;
  225. }