kernel-2_6_6-1_441
[linux-2.6.git] / fs / jffs2 / proc.c
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright (C) 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5  *                    University of Szeged, Hungary
6  *
7  * For licensing information, see the file 'LICENCE' in this directory.
8  *
9  * $Id: proc.c,v 1.3 2004/06/24 09:51:38 havasi Exp $
10  *
11  * Files in /proc/fs/jffs2 directory:
12  *   compr_list
13  *         read:  shows the list of the loaded compressors 
14  *                (name, priority, enadbled/disabled)
15  *         write: compressors can be enabled/disabled and
16  *                the priority of them can be changed,
17  *                required formats:
18  *                    enable COMPRESSOR_NAME
19  *                    disble COMPRESSOR_NAME
20  *                    priority NEW_PRIORITY COMPRESSOR_NAME
21  *   compr_mode
22  *         read:  shows the name of the actual compression mode
23  *         write: sets the actual comperession mode
24  *   compr_stat
25  *         read:  shows compression statistics
26  */
27
28 #include <linux/errno.h>
29 #include <linux/fs.h>
30 #include <linux/jffs.h>
31 #include <linux/slab.h>
32 #include <linux/proc_fs.h>
33 #include <linux/sched.h>
34 #include <linux/types.h>
35 #include <linux/proc_fs.h>
36 #include "compr.h"
37
38 extern struct proc_dir_entry *jffs_proc_root;
39
40 /* Structure for top-level entry in '/proc/fs' directory */
41 static struct proc_dir_entry *jffs2_proc_root;
42
43 /* Structure for files in /proc/fs/jffs2 directory */
44 static struct proc_dir_entry *jffs2_proc_compr_stat;
45 static struct proc_dir_entry *jffs2_proc_compr_mode;
46
47 /* Read the JFFS2 'compr_stat' file */
48
49 static int jffs2_proc_stat_read (char *page, char **start, off_t off,
50                 int count, int *eof, void *data)
51 {
52         int len = 0,i;
53         char *stat = jffs2_stats();
54         
55         if (strlen(stat)<off) {
56                 *eof = 1;
57                 kfree(stat);
58                 return len;
59         }        
60         for (i=off;((stat[i]!=0)&&(len<count));i++,len++) {
61                 page[len]=stat[i];
62         }
63         if (off+len>=strlen(stat)) *eof = 1;
64         else *eof = 0;
65         kfree(stat);
66         return len;
67 }
68
69
70 /* Read the JFFS2 'compr_mode' file */
71
72 static int jffs2_proc_mode_read (char *page, char **start, off_t off,
73                 int count, int *eof, void *data)
74 {
75         int len = 0;
76         if (strlen(jffs2_get_compression_mode_name())+1>count) {
77                 /* it should not happen */
78                 *eof = 1;
79                 return 0;
80         }
81         len += sprintf(page, "%s\n",jffs2_get_compression_mode_name());
82         *eof = 1;
83         return len;
84 }
85
86 /* Write the JFFS2 'compr_mode' file
87  *   sets the actual compression mode
88  */
89
90 static int jffs2_proc_mode_write(struct file *file, const char *buffer,
91                            unsigned long count, void *data)
92 {
93         char *compr_name;
94
95         /* collect the name of the compression mode and set it */
96         compr_name = kmalloc(count+1,GFP_KERNEL);
97         if (sscanf(buffer,"%s",compr_name)>0) {
98                 if (jffs2_set_compression_mode_name(compr_name)) {
99                         printk(KERN_WARNING "JFFS2: error switching compression mode. Invalid parameter (%s)?\n",compr_name);
100                 }
101         }
102         else {
103                 printk(KERN_WARNING "JFFS2: error: parameter missing\n");
104         }
105         kfree(compr_name);
106         return count;
107 }
108
109 /* Read the JFFS2 'compr_list' file */
110
111 static int jffs2_proc_list_read (char *page, char **start, off_t off,
112                 int count, int *eof, void *data)
113 {
114         int len = 0;
115         char *list = jffs2_list_compressors();
116         if (strlen(list)+1>count) {
117                 /* it should not happen */
118                 *eof = 1;
119                 kfree(list);
120                 return 0;
121         }
122         len += sprintf(page,"%s",list);
123         *eof = 1;
124         kfree(list);
125         return len;
126 }
127
128 /* Write the JFFS2 'compr_list' file 
129  *   enable/disable a compressor or set the priority of it
130  */
131
132 static int jffs2_proc_list_write(struct file *file, const char *buffer,
133                            unsigned long count, void *data)
134 {
135         int prior;
136         char *compr_name,*compr_cmd;
137
138         compr_name = kmalloc(count+1,GFP_KERNEL);
139         compr_cmd = kmalloc(count+1,GFP_KERNEL);
140         if (!compr_name) {
141                 printk(KERN_WARNING "JFFS2: unable to allocate memory\n");
142                 goto list_write_end;
143         }
144         compr_name[0] = 0;
145
146         if (sscanf(buffer,"priority %d %s",&prior,compr_name)>1) {
147                 jffs2_set_compressor_priority(compr_name, prior);
148                 goto list_write_end;
149         }
150         if (sscanf(buffer,"enable %s",compr_name)>0) {
151                 jffs2_enable_compressor_name(compr_name);
152                 goto list_write_end;
153         }
154         if (sscanf(buffer,"disable %s",compr_name)>0) {
155                 jffs2_disable_compressor_name(compr_name);
156                 goto list_write_end;
157         }
158         printk(KERN_WARNING "JFFS2: usage of /proc/fs/jffs2/compr_list:\n"
159                "  echo \"enable COMPRESSOR_NAME\"  >/proc/fs/jffs2/compr_list\n"
160                "  echo \"disable COMPRESSOR_NAME\" >/proc/fs/jffs2/compr_list\n"
161                "  echo \"priority NEW_PRIORITY COMPRESSOR_NAME\" >/proc/fs/jffs2/compr_list\n");
162 list_write_end:
163         kfree(compr_cmd);
164         kfree(compr_name);
165         return count;
166 }
167
168 /* Register a JFFS2 proc directory */
169
170 int jffs2_proc_init(void)
171 {
172         jffs2_proc_root = proc_mkdir("jffs2", proc_root_fs);
173
174         /* create entry for 'compr_stat' file */
175         if ((jffs2_proc_compr_stat = create_proc_entry ("compr_stat", 0, jffs2_proc_root))) {
176                 jffs2_proc_compr_stat->read_proc = jffs2_proc_stat_read;
177         }
178         else {
179                 return -ENOMEM;
180         }
181         /* create entry for 'compr_mode' file */
182         if ((jffs2_proc_compr_mode = create_proc_entry ("compr_mode", 0, jffs2_proc_root))) {
183                 jffs2_proc_compr_mode->read_proc  = jffs2_proc_mode_read;
184                 jffs2_proc_compr_mode->write_proc = jffs2_proc_mode_write;
185         }
186         else {
187                 return -ENOMEM;
188         }
189         /* create entry for 'compr_list' file */
190         if ((jffs2_proc_compr_mode = create_proc_entry ("compr_list", 0, jffs2_proc_root))) {
191                 jffs2_proc_compr_mode->read_proc  = jffs2_proc_list_read;
192                 jffs2_proc_compr_mode->write_proc = jffs2_proc_list_write;
193         }
194         else {
195                 return -ENOMEM;
196         }
197         return 0;
198 }
199
200
201 /* Unregister a JFFS2 proc directory */
202
203 int jffs2_proc_exit(void)
204 {
205 #if LINUX_VERSION_CODE < 0x020300
206         remove_proc_entry ("compr_stat", &jffs2_proc_root);
207         remove_proc_entry ("compr_mode", &jffs2_proc_root);
208         remove_proc_entry ("compr_list", &jffs2_proc_root);
209         remove_proc_entry ("jffs2", &proc_root_fs);
210 #else
211         remove_proc_entry ("compr_stat", jffs2_proc_root);
212         remove_proc_entry ("compr_mode", jffs2_proc_root);
213         remove_proc_entry ("compr_list", jffs2_proc_root);
214         remove_proc_entry ("jffs2", proc_root_fs);
215 #endif
216         return 0;
217 }