diff -rp -U 5 linux-2.6.15-orig/fs/Kconfig linux-2.6.15-jffs2-mountoptions-v2-pending/fs/Kconfig --- linux-2.6.15-orig/fs/Kconfig 2006-01-03 07:33:53.000000000 +0100 +++ linux-2.6.15-jffs2-mountoptions-v2-pending/fs/Kconfig 2006-05-19 00:29:40.000000000 +0200 @@ -1130,10 +1130,18 @@ config JFFS2_CMODE_SIZE Tries all compressors and chooses the one which has the smallest result. endchoice +config JFFS2_PROC + bool "JFFS2 /proc support" if JFFS2_COMPRESSION_OPTIONS + depends on JFFS2_FS + default n + help + Enables runtime configuration of each mounted JFFS2 filesystem. + Say 'N' if unsure. + config CRAMFS tristate "Compressed ROM file system support (cramfs)" select ZLIB_INFLATE help Saying Y here includes support for CramFs (Compressed ROM File diff -rp -U 5 linux-2.6.15-orig/fs/jffs2/compr.c linux-2.6.15-jffs2-mountoptions-v2-pending/fs/jffs2/compr.c --- linux-2.6.15-orig/fs/jffs2/compr.c 2006-01-04 07:12:40.000000000 +0100 +++ linux-2.6.15-jffs2-mountoptions-v2-pending/fs/jffs2/compr.c 2006-05-18 23:22:29.000000000 +0200 @@ -18,16 +18,19 @@ static DEFINE_SPINLOCK(jffs2_compressor_list_lock); /* Available compressors are on this list */ static LIST_HEAD(jffs2_compressor_list); -/* Actual compression mode */ -static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; - /* Statistics for blocks stored without compression */ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0; +/* Common strings */ +static const char NAME_NONE[] = "none"; +static const char NAME_PRIO[] = "priority"; +static const char NAME_SIZE[] = "size"; + + /* jffs2_compress: * @data: Pointer to uncompressed data * @cdata: Pointer to returned pointer to buffer for compressed data * @datalen: On entry, holds the amount of data available for compression. * On exit, expected to hold the amount of data actually compressed. @@ -53,11 +56,11 @@ uint16_t jffs2_compress(struct jffs2_sb_ struct jffs2_compressor *this, *best=NULL; unsigned char *output_buf = NULL, *tmp_buf; uint32_t orig_slen, orig_dlen; uint32_t best_slen=0, best_dlen=0; - switch (jffs2_compression_mode) { + switch (c->compression_mode) { case JFFS2_COMPR_MODE_NONE: break; case JFFS2_COMPR_MODE_PRIORITY: output_buf = kmalloc(*cdatalen,GFP_KERNEL); if (!output_buf) { @@ -295,11 +298,11 @@ char *jffs2_stats(void) char *buf, *act_buf; act_buf = buf = kmalloc(JFFS2_STAT_BUF_SIZE,GFP_KERNEL); act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); - act_buf += sprintf(act_buf,"%10s ","none"); + act_buf += sprintf(act_buf,"%10s ", NAME_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); spin_lock(&jffs2_compressor_list_lock); list_for_each_entry(this, &jffs2_compressor_list, list) { act_buf += sprintf(act_buf,"%10s ",this->name); @@ -315,35 +318,35 @@ char *jffs2_stats(void) spin_unlock(&jffs2_compressor_list_lock); return buf; } -char *jffs2_get_compression_mode_name(void) +const char *jffs2_get_compression_mode_name(const struct jffs2_sb_info *c) { - switch (jffs2_compression_mode) { + switch (c->compression_mode) { case JFFS2_COMPR_MODE_NONE: - return "none"; + return NAME_NONE; case JFFS2_COMPR_MODE_PRIORITY: - return "priority"; + return NAME_PRIO; case JFFS2_COMPR_MODE_SIZE: - return "size"; + return NAME_SIZE; } - return "unkown"; + return "unknown"; } -int jffs2_set_compression_mode_name(const char *name) +int jffs2_set_compression_mode_name(struct jffs2_sb_info *c, const char *name) { - if (!strcmp("none",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; + if (!strcmp(NAME_NONE, name)) { + c->compression_mode = JFFS2_COMPR_MODE_NONE; return 0; } - if (!strcmp("priority",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY; + if (!strcmp(NAME_PRIO, name)) { + c->compression_mode = JFFS2_COMPR_MODE_PRIORITY; return 0; } - if (!strcmp("size",name)) { - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; + if (!strcmp(NAME_SIZE, name)) { + c->compression_mode = JFFS2_COMPR_MODE_SIZE; return 0; } return 1; } @@ -423,23 +426,27 @@ int jffs2_compressors_init(void) #endif #ifdef CONFIG_JFFS2_RUBIN jffs2_rubinmips_init(); jffs2_dynrubin_init(); #endif -/* Setting default compression mode */ + return 0; +} + +int jffs2_get_dflt_compression_mode(void) +{ #ifdef CONFIG_JFFS2_CMODE_NONE - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; - D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");) + D1(printk(KERN_INFO "JFFS2: default compression mode: %s\n", NAME_NONE);) + return JFFS2_COMPR_MODE_NONE; #else #ifdef CONFIG_JFFS2_CMODE_SIZE - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE; - D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");) + D1(printk(KERN_INFO "JFFS2: default compression mode: %s\n", NAME_SIZE);) + return JFFS2_COMPR_MODE_SIZE; #else - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");) + D1(printk(KERN_INFO "JFFS2: default compression mode: %s\n", NAME_PRIO);) + return JFFS2_COMPR_MODE_PRIORITY; #endif #endif - return 0; } int jffs2_compressors_exit(void) { /* Unregistering compressors */ diff -rp -U 5 linux-2.6.15-orig/fs/jffs2/compr.h linux-2.6.15-jffs2-mountoptions-v2-pending/fs/jffs2/compr.h --- linux-2.6.15-orig/fs/jffs2/compr.h 2006-01-03 07:33:54.000000000 +0100 +++ linux-2.6.15-jffs2-mountoptions-v2-pending/fs/jffs2/compr.h 2006-05-18 23:24:05.000000000 +0200 @@ -60,11 +60,11 @@ struct jffs2_compressor { uint32_t stat_decompr_blocks; }; int jffs2_register_compressor(struct jffs2_compressor *comp); int jffs2_unregister_compressor(struct jffs2_compressor *comp); - +int jffs2_get_dflt_compression_mode(void); int jffs2_compressors_init(void); int jffs2_compressors_exit(void); uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, unsigned char *data_in, unsigned char **cpage_out, @@ -77,12 +77,12 @@ int jffs2_decompress(struct jffs2_sb_inf 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_compression_mode_name(struct jffs2_sb_info *c, const char *mode_name); +const char *jffs2_get_compression_mode_name(const struct jffs2_sb_info *c); int jffs2_set_compressor_priority(const char *mode_name, int priority); char *jffs2_list_compressors(void); char *jffs2_stats(void); #endif diff -rp -U 5 linux-2.6.15-orig/fs/jffs2/fs.c linux-2.6.15-jffs2-mountoptions-v2-pending/fs/jffs2/fs.c --- linux-2.6.15-orig/fs/jffs2/fs.c 2006-01-03 07:33:54.000000000 +0100 +++ linux-2.6.15-jffs2-mountoptions-v2-pending/fs/jffs2/fs.c 2006-05-23 11:16:15.000000000 +0200 @@ -20,11 +20,13 @@ #include #include #include #include #include +#include #include "nodelist.h" +#include "compr.h" static int jffs2_flash_setup(struct jffs2_sb_info *c); static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) { @@ -337,10 +339,52 @@ void jffs2_dirty_inode(struct inode *ino iattr.ia_ctime = inode->i_ctime; jffs2_do_setattr(inode, &iattr); } + +#ifdef CONFIG_JFFS2_PROC +enum { + OPT_COMPRESSOR, + OPT_ERR +}; + +static match_table_t tokens = { + { OPT_COMPRESSOR, "compressor=%s" }, + { OPT_ERR, NULL } +}; +#endif + +static int parse_options(struct jffs2_sb_info *c, char *data) { +#ifdef CONFIG_JFFS2_PROC + substring_t args[MAX_OPT_ARGS]; + int token; + char *p, *arg; + + while (data && strlen(data) && (p = strsep(&data, ","))) { + if (!*p) continue; + + token = match_token(p, tokens, args); + switch (token) { + case OPT_COMPRESSOR: + arg = match_strdup(&args[0]); + if (arg && !jffs2_set_compression_mode_name(c, arg)) { + D1(printk(KERN_DEBUG "jffs2 parse_options() " + "compressor=%d\n", c->compression_mode)); + } + kfree(arg); + break; + + default: + break; + } + } +#endif + return 0; +} + + int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) { struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); if (c->flags & JFFS2_SB_FLAG_RO && !(sb->s_flags & MS_RDONLY)) @@ -359,10 +403,11 @@ int jffs2_remount_fs (struct super_block if (!(*flags & MS_RDONLY)) jffs2_start_garbage_collect_thread(c); *flags |= MS_NOATIME; + parse_options(c, data); return 0; } void jffs2_write_super (struct super_block *sb) @@ -489,10 +534,14 @@ int jffs2_do_fill_super(struct super_blo ret = -ENOMEM; goto out_wbuf; } memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); + /* Parse mount options */ + c->compression_mode = jffs2_get_dflt_compression_mode(); + parse_options(c, data); + if ((ret = jffs2_do_mount_fs(c))) goto out_inohash; ret = -EINVAL; diff -rp -U 5 linux-2.6.15-orig/include/linux/jffs2_fs_sb.h linux-2.6.15-jffs2-mountoptions-v2-pending/include/linux/jffs2_fs_sb.h --- linux-2.6.15-orig/include/linux/jffs2_fs_sb.h 2006-01-04 07:13:46.000000000 +0100 +++ linux-2.6.15-jffs2-mountoptions-v2-pending/include/linux/jffs2_fs_sb.h 2006-05-18 22:43:58.000000000 +0200 @@ -28,10 +28,11 @@ struct jffs2_sb_info { uint32_t highest_ino; uint32_t checked_ino; unsigned int flags; + int compression_mode; struct task_struct *gc_task; /* GC task struct */ struct completion gc_thread_start; /* GC thread start completion */ struct completion gc_thread_exit; /* GC thread exit completion port */