2 * JFFS -- Journaling Flash File System, Linux implementation.
4 * Copyright (C) 2000 Axis Communications AB.
6 * Created by Simon Kagstrom <simonk@axis.com>.
8 * $Id: jffs_proc.c,v 1.5 2001/06/02 14:34:55 dwmw2 Exp $
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.
16 * This file defines JFFS partition entries in the proc file system.
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.
24 #include <linux/errno.h>
26 #include <linux/jffs.h>
27 #include <linux/slab.h>
28 #include <linux/proc_fs.h>
29 #include <linux/sched.h>
30 #include <linux/types.h>
32 #include "jffs_proc.h"
35 * Structure for a JFFS partition in the system
37 struct jffs_partition_dir {
38 struct jffs_control *c;
39 struct proc_dir_entry *part_root;
40 struct proc_dir_entry *part_info;
41 struct proc_dir_entry *part_layout;
42 struct jffs_partition_dir *next;
46 * Structure for top-level entry in '/proc/fs' directory
48 struct proc_dir_entry *jffs_proc_root;
51 * Linked list of 'jffs_partition_dirs' to help us track
52 * the mounted JFFS partitions in the system
54 static struct jffs_partition_dir *jffs_part_dirs = 0;
57 * Read functions for entries
59 static int jffs_proc_info_read(char *page, char **start, off_t off,
60 int count, int *eof, void *data);
61 static int jffs_proc_layout_read (char *page, char **start, off_t off,
62 int count, int *eof, void *data);
66 * Register a JFFS partition directory (called upon mount)
68 int jffs_register_jffs_proc_dir(kdev_t dev, struct jffs_control *c)
70 struct jffs_partition_dir *part_dir;
71 struct proc_dir_entry *part_info = 0;
72 struct proc_dir_entry *part_layout = 0;
73 struct proc_dir_entry *part_root = 0;
75 /* Allocate structure for local JFFS partition table */
76 if (!(part_dir = (struct jffs_partition_dir *)
77 kmalloc (sizeof (struct jffs_partition_dir), GFP_KERNEL))) {
81 /* Create entry for this partition */
82 if ((part_root = create_proc_entry (kdevname(dev),
83 S_IFDIR | S_IRUGO | S_IXUGO, jffs_proc_root))) {
84 part_root->read_proc = jffs_proc_info_read;
85 part_root->data = (void *) c;
92 /* Create entry for 'info' file */
93 if ((part_info = create_proc_entry ("info", 0, part_root))) {
94 part_info->read_proc = jffs_proc_info_read;
95 part_info->data = (void *) c;
98 remove_proc_entry (part_root->name, jffs_proc_root);
103 /* Create entry for 'layout' file */
104 if ((part_layout = create_proc_entry ("layout", 0, part_root))) {
105 part_layout->read_proc = jffs_proc_layout_read;
106 part_layout->data = (void *) c;
109 remove_proc_entry (part_info->name, part_root);
110 remove_proc_entry (part_root->name, jffs_proc_root);
115 /* Fill in structure for table and insert in the list */
117 part_dir->part_root = part_root;
118 part_dir->part_info = part_info;
119 part_dir->part_layout = part_layout;
120 part_dir->next = jffs_part_dirs;
121 jffs_part_dirs = part_dir;
129 * Unregister a JFFS partition directory (called at umount)
131 int jffs_unregister_jffs_proc_dir(struct jffs_control *c)
133 struct jffs_partition_dir *part_dir = jffs_part_dirs;
134 struct jffs_partition_dir *prev_part_dir = 0;
137 if (part_dir->c == c) {
138 /* Remove entries for partition */
139 remove_proc_entry (part_dir->part_info->name,
140 part_dir->part_root);
141 remove_proc_entry (part_dir->part_layout->name,
142 part_dir->part_root);
143 remove_proc_entry (part_dir->part_root->name,
146 /* Remove entry from list */
148 prev_part_dir->next = part_dir->next;
150 jffs_part_dirs = part_dir->next;
153 * Check to see if this is the last one
154 * and remove the entry from '/proc/fs'
157 if (jffs_part_dirs == part_dir->next)
158 #if LINUX_VERSION_CODE < 0x020300
159 remove_proc_entry ("jffs", &proc_root_fs);
161 remove_proc_entry ("jffs", proc_root_fs);
164 /* Free memory for entry */
171 /* Move to next entry */
172 prev_part_dir = part_dir;
173 part_dir = part_dir->next;
182 * Read a JFFS partition's `info' file
184 static int jffs_proc_info_read (char *page, char **start, off_t off,
185 int count, int *eof, void *data)
187 struct jffs_control *c = (struct jffs_control *) data;
190 /* Get information on the parition */
191 len += sprintf (page,
192 "partition size: %08lX (%u)\n"
193 "sector size: %08lX (%u)\n"
194 "used size: %08lX (%u)\n"
195 "dirty size: %08lX (%u)\n"
196 "free size: %08lX (%u)\n\n",
197 (unsigned long) c->fmc->flash_size, c->fmc->flash_size,
198 (unsigned long) c->fmc->sector_size, c->fmc->sector_size,
199 (unsigned long) c->fmc->used_size, c->fmc->used_size,
200 (unsigned long) c->fmc->dirty_size, c->fmc->dirty_size,
201 (unsigned long) (c->fmc->flash_size -
202 (c->fmc->used_size + c->fmc->dirty_size)),
203 c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size));
214 * Read a JFFS partition's `layout' file
216 static int jffs_proc_layout_read (char *page, char **start, off_t off,
217 int count, int *eof, void *data)
219 struct jffs_control *c = (struct jffs_control *) data;
220 struct jffs_fm *fm = 0;
221 struct jffs_fm *last_fm = 0;
224 /* Get the first item in the list */
227 /* Print free space */
228 if (fm && fm->offset) {
229 len += sprintf (page, "00000000 %08lX free\n",
230 (unsigned long) fm->offset);
233 /* Loop through all of the flash control structures */
234 while (fm && (len < (off + count))) {
236 len += sprintf (page + len,
237 "%08lX %08lX ino=%08lX, ver=%08lX\n",
238 (unsigned long) fm->offset,
239 (unsigned long) fm->size,
240 (unsigned long) fm->nodes->node->ino,
241 (unsigned long) fm->nodes->node->version);
244 len += sprintf (page + len,
245 "%08lX %08lX dirty\n",
246 (unsigned long) fm->offset,
247 (unsigned long) fm->size);
253 /* Print free space */
254 if ((len < (off + count)) && last_fm
255 && (last_fm->offset < c->fmc->flash_size)) {
256 len += sprintf (page + len,
257 "%08lX %08lX free\n",
258 (unsigned long) last_fm->offset +
260 (unsigned long) (c->fmc->flash_size -
261 (last_fm->offset + last_fm->size)));