diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/jffs/jffs_proc.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/jffs/jffs_proc.c')
-rw-r--r-- | fs/jffs/jffs_proc.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/fs/jffs/jffs_proc.c b/fs/jffs/jffs_proc.c new file mode 100644 index 000000000000..9bdd99a557c2 --- /dev/null +++ b/fs/jffs/jffs_proc.c | |||
@@ -0,0 +1,261 @@ | |||
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 | |||
24 | #include <linux/errno.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/jffs.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/proc_fs.h> | ||
29 | #include <linux/time.h> | ||
30 | #include <linux/types.h> | ||
31 | #include "jffs_fm.h" | ||
32 | #include "jffs_proc.h" | ||
33 | |||
34 | /* | ||
35 | * Structure for a JFFS partition in the system | ||
36 | */ | ||
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; | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * Structure for top-level entry in '/proc/fs' directory | ||
47 | */ | ||
48 | struct proc_dir_entry *jffs_proc_root; | ||
49 | |||
50 | /* | ||
51 | * Linked list of 'jffs_partition_dirs' to help us track | ||
52 | * the mounted JFFS partitions in the system | ||
53 | */ | ||
54 | static struct jffs_partition_dir *jffs_part_dirs; | ||
55 | |||
56 | /* | ||
57 | * Read functions for entries | ||
58 | */ | ||
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); | ||
63 | |||
64 | |||
65 | /* | ||
66 | * Register a JFFS partition directory (called upon mount) | ||
67 | */ | ||
68 | int jffs_register_jffs_proc_dir(int mtd, struct jffs_control *c) | ||
69 | { | ||
70 | struct jffs_partition_dir *part_dir; | ||
71 | struct proc_dir_entry *part_info = NULL; | ||
72 | struct proc_dir_entry *part_layout = NULL; | ||
73 | struct proc_dir_entry *part_root = NULL; | ||
74 | char name[10]; | ||
75 | |||
76 | sprintf(name, "%d", mtd); | ||
77 | /* Allocate structure for local JFFS partition table */ | ||
78 | part_dir = (struct jffs_partition_dir *) | ||
79 | kmalloc(sizeof (struct jffs_partition_dir), GFP_KERNEL); | ||
80 | if (!part_dir) | ||
81 | goto out; | ||
82 | |||
83 | /* Create entry for this partition */ | ||
84 | part_root = proc_mkdir(name, jffs_proc_root); | ||
85 | if (!part_root) | ||
86 | goto out1; | ||
87 | |||
88 | /* Create entry for 'info' file */ | ||
89 | part_info = create_proc_entry ("info", 0, part_root); | ||
90 | if (!part_info) | ||
91 | goto out2; | ||
92 | part_info->read_proc = jffs_proc_info_read; | ||
93 | part_info->data = (void *) c; | ||
94 | |||
95 | /* Create entry for 'layout' file */ | ||
96 | part_layout = create_proc_entry ("layout", 0, part_root); | ||
97 | if (!part_layout) | ||
98 | goto out3; | ||
99 | part_layout->read_proc = jffs_proc_layout_read; | ||
100 | part_layout->data = (void *) c; | ||
101 | |||
102 | /* Fill in structure for table and insert in the list */ | ||
103 | part_dir->c = c; | ||
104 | part_dir->part_root = part_root; | ||
105 | part_dir->part_info = part_info; | ||
106 | part_dir->part_layout = part_layout; | ||
107 | part_dir->next = jffs_part_dirs; | ||
108 | jffs_part_dirs = part_dir; | ||
109 | |||
110 | /* Return happy */ | ||
111 | return 0; | ||
112 | |||
113 | out3: | ||
114 | remove_proc_entry("info", part_root); | ||
115 | out2: | ||
116 | remove_proc_entry(name, jffs_proc_root); | ||
117 | out1: | ||
118 | kfree(part_dir); | ||
119 | out: | ||
120 | return -ENOMEM; | ||
121 | } | ||
122 | |||
123 | |||
124 | /* | ||
125 | * Unregister a JFFS partition directory (called at umount) | ||
126 | */ | ||
127 | int jffs_unregister_jffs_proc_dir(struct jffs_control *c) | ||
128 | { | ||
129 | struct jffs_partition_dir *part_dir = jffs_part_dirs; | ||
130 | struct jffs_partition_dir *prev_part_dir = NULL; | ||
131 | |||
132 | while (part_dir) { | ||
133 | if (part_dir->c == c) { | ||
134 | /* Remove entries for partition */ | ||
135 | remove_proc_entry (part_dir->part_info->name, | ||
136 | part_dir->part_root); | ||
137 | remove_proc_entry (part_dir->part_layout->name, | ||
138 | part_dir->part_root); | ||
139 | remove_proc_entry (part_dir->part_root->name, | ||
140 | jffs_proc_root); | ||
141 | |||
142 | /* Remove entry from list */ | ||
143 | if (prev_part_dir) | ||
144 | prev_part_dir->next = part_dir->next; | ||
145 | else | ||
146 | jffs_part_dirs = part_dir->next; | ||
147 | |||
148 | /* | ||
149 | * Check to see if this is the last one | ||
150 | * and remove the entry from '/proc/fs' | ||
151 | * if it is. | ||
152 | */ | ||
153 | if (jffs_part_dirs == part_dir->next) | ||
154 | remove_proc_entry ("jffs", proc_root_fs); | ||
155 | |||
156 | /* Free memory for entry */ | ||
157 | kfree(part_dir); | ||
158 | |||
159 | /* Return happy */ | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* Move to next entry */ | ||
164 | prev_part_dir = part_dir; | ||
165 | part_dir = part_dir->next; | ||
166 | } | ||
167 | |||
168 | /* Return unhappy */ | ||
169 | return -1; | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | ||
174 | * Read a JFFS partition's `info' file | ||
175 | */ | ||
176 | static int jffs_proc_info_read (char *page, char **start, off_t off, | ||
177 | int count, int *eof, void *data) | ||
178 | { | ||
179 | struct jffs_control *c = (struct jffs_control *) data; | ||
180 | int len = 0; | ||
181 | |||
182 | /* Get information on the parition */ | ||
183 | len += sprintf (page, | ||
184 | "partition size: %08lX (%u)\n" | ||
185 | "sector size: %08lX (%u)\n" | ||
186 | "used size: %08lX (%u)\n" | ||
187 | "dirty size: %08lX (%u)\n" | ||
188 | "free size: %08lX (%u)\n\n", | ||
189 | (unsigned long) c->fmc->flash_size, c->fmc->flash_size, | ||
190 | (unsigned long) c->fmc->sector_size, c->fmc->sector_size, | ||
191 | (unsigned long) c->fmc->used_size, c->fmc->used_size, | ||
192 | (unsigned long) c->fmc->dirty_size, c->fmc->dirty_size, | ||
193 | (unsigned long) (c->fmc->flash_size - | ||
194 | (c->fmc->used_size + c->fmc->dirty_size)), | ||
195 | c->fmc->flash_size - (c->fmc->used_size + c->fmc->dirty_size)); | ||
196 | |||
197 | /* We're done */ | ||
198 | *eof = 1; | ||
199 | |||
200 | /* Return length */ | ||
201 | return len; | ||
202 | } | ||
203 | |||
204 | |||
205 | /* | ||
206 | * Read a JFFS partition's `layout' file | ||
207 | */ | ||
208 | static int jffs_proc_layout_read (char *page, char **start, off_t off, | ||
209 | int count, int *eof, void *data) | ||
210 | { | ||
211 | struct jffs_control *c = (struct jffs_control *) data; | ||
212 | struct jffs_fm *fm = NULL; | ||
213 | struct jffs_fm *last_fm = NULL; | ||
214 | int len = 0; | ||
215 | |||
216 | /* Get the first item in the list */ | ||
217 | fm = c->fmc->head; | ||
218 | |||
219 | /* Print free space */ | ||
220 | if (fm && fm->offset) { | ||
221 | len += sprintf (page, "00000000 %08lX free\n", | ||
222 | (unsigned long) fm->offset); | ||
223 | } | ||
224 | |||
225 | /* Loop through all of the flash control structures */ | ||
226 | while (fm && (len < (off + count))) { | ||
227 | if (fm->nodes) { | ||
228 | len += sprintf (page + len, | ||
229 | "%08lX %08lX ino=%08lX, ver=%08lX\n", | ||
230 | (unsigned long) fm->offset, | ||
231 | (unsigned long) fm->size, | ||
232 | (unsigned long) fm->nodes->node->ino, | ||
233 | (unsigned long) fm->nodes->node->version); | ||
234 | } | ||
235 | else { | ||
236 | len += sprintf (page + len, | ||
237 | "%08lX %08lX dirty\n", | ||
238 | (unsigned long) fm->offset, | ||
239 | (unsigned long) fm->size); | ||
240 | } | ||
241 | last_fm = fm; | ||
242 | fm = fm->next; | ||
243 | } | ||
244 | |||
245 | /* Print free space */ | ||
246 | if ((len < (off + count)) && last_fm | ||
247 | && (last_fm->offset < c->fmc->flash_size)) { | ||
248 | len += sprintf (page + len, | ||
249 | "%08lX %08lX free\n", | ||
250 | (unsigned long) last_fm->offset + | ||
251 | last_fm->size, | ||
252 | (unsigned long) (c->fmc->flash_size - | ||
253 | (last_fm->offset + last_fm->size))); | ||
254 | } | ||
255 | |||
256 | /* We're done */ | ||
257 | *eof = 1; | ||
258 | |||
259 | /* Return length */ | ||
260 | return len; | ||
261 | } | ||