Re: BBC patch
Ferenc Havasi <[email protected]> Wed, 12 May 2004 17:58:30 +0200
| Newsgroups | gmane.linux.file-systems.jffs |
|---|---|
| Message-ID | <[email protected]> |
Hi, Here is a new patch: an (certainly optional) proc file system interface for JFFS2 to show the user the actual compressor configuration and allow him to set the compression mode, enable/disable compressors and to modify their priority. It should be applied after my last patches (jffs2-bbc-core-r2.patch). BR, Ferenc
jffs2-bbc-proc.patch
(text/x-patch, 19.9 KB)
diff --unified --recursive --new-file mtd/fs/Config.in mtd-new-9/fs/Config.in
--- mtd/fs/Config.in 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/Config.in 2004-05-12 11:57:09.000000000 +0200
@@ -7,12 +7,14 @@
if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then
int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
bool 'JFFS2 support for NAND chips' CONFIG_JFFS2_FS_NAND
- bool 'ZLIB compression support (recommended)' CONFIG_JFFS2_ZLIB
- bool 'RTIME compression support (recommended)' CONFIG_JFFS2_RTIME
- bool 'RUBIN compression support' CONFIG_JFFS2_RUBIN
+ bool 'JFFS2 ZLIB compression support (recommended)' CONFIG_JFFS2_ZLIB
+ bool 'JFFS2 RTIME compression support (recommended)' CONFIG_JFFS2_RTIME
+ bool 'JFFS2 RUBIN compression support' CONFIG_JFFS2_RUBIN
- choice 'Default JFFS2 compression mode' \
+ choice 'JFFS2 default compression mode' \
"none CONFIG_JFFS2_CMODE_NONE \
priority CONFIG_JFFS2_CMODE_PRIORITY \
size CONFIG_JFFS2_CMODE_SIZE" priority
+
+ bool 'JFFS2 proc interface support' CONFIG_JFFS2_PROC
fi
diff --unified --recursive --new-file mtd/fs/Kconfig mtd-new-9/fs/Kconfig
--- mtd/fs/Kconfig 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/Kconfig 2004-05-12 17:45:30.000000000 +0200
@@ -68,7 +68,7 @@
develop JFFS2 support for it.
config JFFS2_ZLIB
- bool "ZLIB compression support"
+ bool "JFFS2 ZLIB compression support"
depends on JFFS2_FS
default y
help
@@ -80,21 +80,21 @@
Say 'Y' if unsure.
config JFFS2_RTIME
- bool "RTIME compression support"
+ bool "JFFS2 RTIME compression support"
depends on JFFS2_FS
default y
help
Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
config JFFS2_RUBIN
- bool "RUBIN compression support"
+ bool "JFFS2 RUBIN compression support"
depends on JFFS2_FS
default n
help
RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
choice
- prompt "Default compression mode"
+ prompt "JFFS2 default compression mode"
default JFFS2_CMODE_PRIORITY
depends on JFFS2_FS
help
@@ -119,3 +119,12 @@
result.
endchoice
+
+config JFFS2_PROC
+ bool "JFFS2 proc interface support"
+ depends on JFFS2_FS
+ default y
+ help
+ You can read some statistics and set the compression mode and
+ compressor priorities with this interface.
+
diff --unified --recursive --new-file mtd/fs/jffs2/Makefile.common mtd-new-9/fs/jffs2/Makefile.common
--- mtd/fs/jffs2/Makefile.common 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/jffs2/Makefile.common 2004-05-12 10:58:46.000000000 +0200
@@ -15,6 +15,7 @@
JRUBIN_OBJS-$(CONFIG_JFFS2_RUBIN) := compr_rubin.o
JRTIME_OBJS-$(CONFIG_JFFS2_RTIME) := compr_rtime.o
JZLIB_OBJS-$(CONFIG_JFFS2_ZLIB) := compr_zlib.o
+PROC_OBJS-$(CONFIG_JFFS2_PROC) := proc.o
JFFS2_OBJS := compr.o dir.o file.o ioctl.o nodelist.o malloc.o \
read.o nodemgmt.o readinode.o write.o scan.o gc.o \
symlink.o build.o erase.o background.o fs.o writev.o
@@ -30,7 +31,8 @@
NAND_OBJS-$(CONFIG_JFFS2_FS_NAND) := wbuf.o
jffs2-objs := $(COMPR_OBJS) $(JFFS2_OBJS) $(VERS_OBJS) $(NAND_OBJS-y) \
- $(LINUX_OBJS) $(JRUBIN_OBJS-y) $(JRTIME_OBJS-y) $(JZLIB_OBJS-y)
+ $(LINUX_OBJS) $(JRUBIN_OBJS-y) $(JRTIME_OBJS-y) $(JZLIB_OBJS-y) \
+ $(PROC_OBJS-y)
# 2.4 build compatibility
ifeq ($(BELOW25),y)
diff --unified --recursive --new-file mtd/fs/jffs2/compr.c mtd-new-9/fs/jffs2/compr.c
--- mtd/fs/jffs2/compr.c 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/jffs2/compr.c 2004-05-12 15:51:43.000000000 +0200
@@ -15,8 +15,6 @@
#include "compr.h"
-#define MALLOC(a) kmalloc(a,GFP_KERNEL)
-#define FREE(a) kfree(a)
#define COMPRESSOR_LIST_LOCK spin_lock(&jffs2_compressor_list_lock)
#define COMPRESSOR_LIST_UNLOCK spin_unlock(&jffs2_compressor_list_lock)
@@ -74,7 +72,7 @@
case JFFS2_COMPR_MODE_NONE:
break;
case JFFS2_COMPR_MODE_PRIORITY:
- output_buf = MALLOC(*cdatalen);
+ output_buf = JFFS2_MALLOC(*cdatalen);
if (!output_buf) {
printk("JFFS2: No memory for compressor allocation. Compression failed.\n");
goto out;
@@ -115,14 +113,14 @@
/* Allocating memory for output buffer if necessary */
if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
COMPRESSOR_LIST_UNLOCK;
- FREE(this->compr_buf);
+ JFFS2_FREE(this->compr_buf);
COMPRESSOR_LIST_LOCK;
this->compr_buf_size=0;
this->compr_buf=NULL;
}
if (!this->compr_buf) {
COMPRESSOR_LIST_UNLOCK;
- tmp_buf = MALLOC(orig_dlen);
+ tmp_buf = JFFS2_MALLOC(orig_dlen);
COMPRESSOR_LIST_LOCK;
if (!tmp_buf) {
printk("JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
@@ -288,7 +286,7 @@
struct jffs2_compressor *this;
char *buf, *act_buf;
- act_buf = buf = MALLOC(JFFS2_STAT_BUF_SIZE);
+ act_buf = buf = JFFS2_MALLOC(JFFS2_STAT_BUF_SIZE);
list_for_each_entry(this, &jffs2_compressor_list, list) {
act_buf += sprintf(act_buf, "%10s priority:%d ", this->name, this->priority);
if ((this->disabled)||(!this->compress))
@@ -305,30 +303,15 @@
struct jffs2_compressor *this;
char *buf, *act_buf;
- act_buf = buf = MALLOC(JFFS2_STAT_BUF_SIZE);
+ act_buf = buf = JFFS2_MALLOC(JFFS2_STAT_BUF_SIZE);
- act_buf += sprintf(act_buf,"Compression mode: ");
- switch (jffs2_compression_mode) {
- case JFFS2_COMPR_MODE_NONE:
- act_buf += sprintf(act_buf,"none");
- break;
- case JFFS2_COMPR_MODE_PRIORITY:
- act_buf += sprintf(act_buf,"priority");
- break;
- case JFFS2_COMPR_MODE_SIZE:
- act_buf += sprintf(act_buf,"size");
- break;
- default:
- act_buf += sprintf(act_buf,"unkown");
- break;
- }
- act_buf += sprintf(act_buf,"\nCompressors:\n");
- act_buf += sprintf(act_buf,"%10s ","none");
+ act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n");
+ act_buf += sprintf(act_buf,"%10s ","none");
act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks,
none_stat_compr_size, none_stat_decompr_blocks);
COMPRESSOR_LIST_LOCK;
list_for_each_entry(this, &jffs2_compressor_list, list) {
- act_buf += sprintf(act_buf,"%10s (prio:%d) ",this->name,this->priority);
+ act_buf += sprintf(act_buf,"%10s ",this->name);
if ((this->disabled)||(!this->compress))
act_buf += sprintf(act_buf,"- ");
else
@@ -339,9 +322,23 @@
act_buf += sprintf(act_buf,"\n");
}
COMPRESSOR_LIST_UNLOCK;
+
return buf;
}
+char *jffs2_get_compression_mode_name(void)
+{
+ switch (jffs2_compression_mode) {
+ case JFFS2_COMPR_MODE_NONE:
+ return "none";
+ case JFFS2_COMPR_MODE_PRIORITY:
+ return "priority";
+ case JFFS2_COMPR_MODE_SIZE:
+ return "size";
+ }
+ return "unkown";
+}
+
int jffs2_set_compression_mode_name(const char *name)
{
if (!strcmp("none",name)) {
@@ -384,12 +381,42 @@
return jffs2_compressor_Xable(name, 1);
}
+int jffs2_set_compressor_priority(const char *name, int priority)
+{
+ struct jffs2_compressor *this,*comp;
+ COMPRESSOR_LIST_LOCK;
+ list_for_each_entry(this, &jffs2_compressor_list, list) {
+ if (!strcmp(this->name, name)) {
+ this->priority = priority;
+ comp = this;
+ goto reinsert;
+ }
+ }
+ COMPRESSOR_LIST_UNLOCK;
+ return 1;
+reinsert:
+ /* list is sorted in the order of priority, so if
+ we change it we have to reinsert it into the
+ good place */
+ list_del(&comp->list);
+ list_for_each_entry(this, &jffs2_compressor_list, list) {
+ if (this->priority < comp->priority) {
+ list_add(&comp->list, this->list.prev);
+ COMPRESSOR_LIST_UNLOCK;
+ return 0;
+ }
+ }
+ list_add_tail(&comp->list, &jffs2_compressor_list);
+ COMPRESSOR_LIST_UNLOCK;
+ return 0;
+}
+
#endif
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
{
if (orig != comprbuf)
- FREE(comprbuf);
+ JFFS2_FREE(comprbuf);
}
int jffs2_compressors_init(void)
diff --unified --recursive --new-file mtd/fs/jffs2/compr.h mtd-new-9/fs/jffs2/compr.h
--- mtd/fs/jffs2/compr.h 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/jffs2/compr.h 2004-05-12 16:28:45.000000000 +0200
@@ -40,12 +40,11 @@
#define JFFS2_COMPR_MODE_PRIORITY 1
#define JFFS2_COMPR_MODE_SIZE 2
+#define JFFS2_MALLOC(a) kmalloc(a,GFP_KERNEL)
+#define JFFS2_FREE(a) kfree(a)
+
void jffs2_set_compression_mode(int mode);
int jffs2_get_compression_mode(void);
-int jffs2_set_compression_mode_name(const char *mode_name);
-
-int jffs2_enable_compressor_name(const char *name);
-int jffs2_disable_compressor_name(const char *name);
struct jffs2_compressor {
struct list_head list;
@@ -80,13 +79,17 @@
uint16_t comprtype, unsigned char *cdata_in,
unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
-/* If it is setted, a decompress will be called after every compress */
-void jffs2_compression_check_set(int yesno);
-
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
+#ifdef CONFIG_JFFS2_PROC
+int jffs2_enable_compressor_name(const char *name);
+int jffs2_disable_compressor_name(const char *name);
+int jffs2_set_compression_mode_name(const char *mode_name);
+char *jffs2_get_compression_mode_name(void);
+int jffs2_set_compressor_priority(const char *mode_name, int priority);
char *jffs2_list_compressors(void);
char *jffs2_stats(void);
+#endif
/* Compressor modules */
@@ -106,4 +109,8 @@
void jffs2_zlib_exit(void);
#endif
+/* Prototypes from proc.c */
+int jffs2_proc_init(void);
+int jffs2_proc_exit(void);
+
#endif /* __JFFS2_COMPR_H__ */
diff --unified --recursive --new-file mtd/fs/jffs2/proc.c mtd-new-9/fs/jffs2/proc.c
--- mtd/fs/jffs2/proc.c 1970-01-01 01:00:00.000000000 +0100
+++ mtd-new-9/fs/jffs2/proc.c 2004-05-12 17:18:46.000000000 +0200
@@ -0,0 +1,222 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2001, 2002 Red Hat, Inc.
+ *
+ * Created by Ferenc Havasi <[email protected]>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ * $Id$
+ *
+ * Files under /proc/fs/jffs2 directory:
+ * compr_list
+ * read: shows the list of the loaded compressors
+ * (name, priority, enadbled/disabled)
+ * write: compressors can be enabled/disabled and
+ * the priority of them can be changed,
+ * required formats:
+ * enable COMPRESSOR_NAME
+ * disble COMPRESSOR_NAME
+ * priority NEW_PRIORITY COMPRESSOR_NAME
+ * compr_mode
+ * read: shows the name of the actual compression mode
+ * write: sets the actual comperession mode
+ * compr_stat
+ * read: shows compression statistics
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/jffs.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include "compr.h"
+
+extern struct proc_dir_entry *jffs_proc_root;
+
+/* Structure for top-level entry in '/proc/fs' directory */
+static struct proc_dir_entry *jffs2_proc_root;
+
+/* Structure for files in /proc/fs/jffs2 directory */
+static struct proc_dir_entry *jffs2_proc_compr_stat;
+static struct proc_dir_entry *jffs2_proc_compr_mode;
+
+/* Read the JFFS2 'compr_stat' file */
+
+static int jffs2_proc_stat_read (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0,i;
+ char *stat = jffs2_stats();
+
+ if (strlen(stat)<off) {
+ *eof = 1;
+ JFFS2_FREE(stat);
+ return len;
+ }
+ for (i=off;((stat[i]!=0)&&(len<count));i++,len++) {
+ page[len]=stat[i];
+ }
+ if (off+len>=strlen(stat)) *eof = 1;
+ else *eof = 0;
+ JFFS2_FREE(stat);
+ return len;
+}
+
+
+/* Read the JFFS2 'compr_mode' file */
+
+static int jffs2_proc_mode_read (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+ if (strlen(jffs2_get_compression_mode_name())+1>count) {
+ /* it should not happen */
+ *eof = 1;
+ return 0;
+ }
+ len += sprintf(page, "%s\n",jffs2_get_compression_mode_name());
+ *eof = 1;
+ return len;
+}
+
+/* Write the JFFS2 'compr_mode' file
+ * sets the actual compression mode
+ */
+
+static int jffs2_proc_mode_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char *compr_name;
+
+ /* collect the name of the compression mode and set it */
+ compr_name = JFFS2_MALLOC(count+1);
+ if (sscanf(buffer,"%s",compr_name)>0) {
+ if (jffs2_set_compression_mode_name(compr_name)) {
+ printk("JFFS2: error switching compression mode. Invalid parameter (%s)?\n",compr_name);
+ }
+ }
+ else {
+ printk("JFFS2: error: parameter missing\n");
+ }
+ JFFS2_FREE(compr_name);
+ return count;
+}
+
+/* Read the JFFS2 'compr_list' file */
+
+static int jffs2_proc_list_read (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+ char *list = jffs2_list_compressors();
+ if (strlen(list)+1>count) {
+ /* it should not happen */
+ *eof = 1;
+ JFFS2_FREE(list);
+ return 0;
+ }
+ len += sprintf(page,"%s",list);
+ *eof = 1;
+ JFFS2_FREE(list);
+ return len;
+}
+
+/* Write the JFFS2 'compr_list' file
+ * enable/disable a compressor or set the priority of it
+ */
+
+static int jffs2_proc_list_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int prior;
+ char *compr_name;
+
+ compr_name = JFFS2_MALLOC(count+1);
+ if (!compr_name) {
+ printk("JFFS2: unable to allocate memory\n");
+ goto list_write_end;
+ }
+ compr_name[0] = 0;
+
+ if (sscanf(buffer,"priority %d %s",&prior,compr_name)>1) {
+ if (jffs2_set_compressor_priority(compr_name, prior)) {
+ printk("JFFS2: compressor name not found in list\n");
+ }
+ goto list_write_end;
+ }
+ if (sscanf(buffer,"enable %s",compr_name)>0) {
+ if (jffs2_enable_compressor_name(compr_name)) {
+ printk("JFFS2: compressor name not found in list\n");
+ }
+ goto list_write_end;
+ }
+ if (sscanf(buffer,"disable %s",compr_name)>0) {
+ if (jffs2_disable_compressor_name(compr_name)) {
+ printk("JFFS2: compressor name not found in list\n");
+ }
+ goto list_write_end;
+ }
+ printk("JFFS2: usage of /proc/fs/jffs2/compr_list:\n"
+ " echo \"enable COMPRESSOR_NAME\" >/proc/fs/jffs2/compr_list\n"
+ " echo \"disable COMPRESSOR_NAME\" >/proc/fs/jffs2/compr_list\n"
+ " echo \"priority NEW_PRIORITY COMPRESSOR_NAME\" >/proc/fs/jffs2/compr_list\n");
+list_write_end:
+ JFFS2_FREE(compr_name);
+ return count;
+}
+
+/* Register a JFFS2 proc directory */
+
+int jffs2_proc_init(void)
+{
+ jffs2_proc_root = proc_mkdir("jffs2", proc_root_fs);
+
+ /* create entry for 'compr_stat' file */
+ if ((jffs2_proc_compr_stat = create_proc_entry ("compr_stat", 0, jffs2_proc_root))) {
+ jffs2_proc_compr_stat->read_proc = jffs2_proc_stat_read;
+ }
+ else {
+ return -ENOMEM;
+ }
+ /* create entry for 'compr_mode' file */
+ if ((jffs2_proc_compr_mode = create_proc_entry ("compr_mode", 0, jffs2_proc_root))) {
+ jffs2_proc_compr_mode->read_proc = jffs2_proc_mode_read;
+ jffs2_proc_compr_mode->write_proc = jffs2_proc_mode_write;
+ }
+ else {
+ return -ENOMEM;
+ }
+ /* create entry for 'compr_list' file */
+ if ((jffs2_proc_compr_mode = create_proc_entry ("compr_list", 0, jffs2_proc_root))) {
+ jffs2_proc_compr_mode->read_proc = jffs2_proc_list_read;
+ jffs2_proc_compr_mode->write_proc = jffs2_proc_list_write;
+ }
+ else {
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+
+/* Unregister a JFFS2 proc directory */
+
+int jffs2_proc_exit(void)
+{
+#if LINUX_VERSION_CODE < 0x020300
+ remove_proc_entry ("compr_stat", &jffs2_proc_root);
+ remove_proc_entry ("compr_mode", &jffs2_proc_root);
+ remove_proc_entry ("compr_list", &jffs2_proc_root);
+ remove_proc_entry ("jffs2", &proc_root_fs);
+#else
+ remove_proc_entry ("compr_stat", jffs2_proc_root);
+ remove_proc_entry ("compr_mode", jffs2_proc_root);
+ remove_proc_entry ("compr_list", jffs2_proc_root);
+ remove_proc_entry ("jffs2", proc_root_fs);
+#endif
+ return 0;
+}
diff --unified --recursive --new-file mtd/fs/jffs2/super-v24.c mtd-new-9/fs/jffs2/super-v24.c
--- mtd/fs/jffs2/super-v24.c 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/jffs2/super-v24.c 2004-05-12 12:05:21.000000000 +0200
@@ -126,6 +126,13 @@
return -EIO;
}
#endif
+#ifdef CONFIG_JFFS2_PROC
+ ret = jffs2_proc_init();
+ if (ret) {
+ printk(KERN_ERR "JFFS2 error: Failed to initialise proc interface\n");
+ goto out;
+ }
+#endif
ret = jffs2_compressors_init();
if (ret) {
printk(KERN_ERR "JFFS2 error: Failed to initialise compressors\n");
@@ -147,8 +154,10 @@
jffs2_destroy_slab_caches();
out_compressors:
jffs2_compressors_exit();
+#ifdef CONFIG_JFFS2_PROC
+ jffs2_proc_exit();
+#endif
out:
-
return ret;
}
@@ -156,6 +165,9 @@
{
jffs2_destroy_slab_caches();
jffs2_compressors_exit();
+#ifdef CONFIG_JFFS2_PROC
+ jffs2_proc_exit();
+#endif
unregister_filesystem(&jffs2_fs_type);
}
diff --unified --recursive --new-file mtd/fs/jffs2/super.c mtd-new-9/fs/jffs2/super.c
--- mtd/fs/jffs2/super.c 2004-05-12 17:23:49.000000000 +0200
+++ mtd-new-9/fs/jffs2/super.c 2004-05-12 12:06:13.000000000 +0200
@@ -308,6 +308,13 @@
printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n");
return -ENOMEM;
}
+#ifdef CONFIG_JFFS2_PROC
+ ret = jffs2_proc_init();
+ if (ret) {
+ printk(KERN_ERR "JFFS2 error: Failed to initialise proc interface\n");
+ goto out;
+ }
+#endif
ret = jffs2_compressors_init();
if (ret) {
printk(KERN_ERR "JFFS2 error: Failed to initialise compressors\n");
@@ -329,6 +336,9 @@
jffs2_destroy_slab_caches();
out_compressors:
jffs2_compressors_exit();
+#ifdef CONFIG_JFFS2_PROC
+ jffs2_proc_exit();
+#endif
out:
return ret;
}
@@ -338,6 +348,9 @@
unregister_filesystem(&jffs2_fs_type);
jffs2_destroy_slab_caches();
jffs2_compressors_exit();
+#ifdef CONFIG_JFFS2_PROC
+ jffs2_proc_exit();
+#endif
kmem_cache_destroy(jffs2_inode_cachep);
}