Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 }
262 
  This page was automatically generated by the LXR engine.