diff options
-rw-r--r-- | fs/jffs2/compr.c | 9 | ||||
-rw-r--r-- | fs/jffs2/fs.c | 2 | ||||
-rw-r--r-- | fs/jffs2/jffs2_fs_sb.h | 6 | ||||
-rw-r--r-- | fs/jffs2/os-linux.h | 2 | ||||
-rw-r--r-- | fs/jffs2/super.c | 97 |
5 files changed, 112 insertions, 4 deletions
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index de4247021d25..97bc74db2c96 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c | |||
@@ -76,13 +76,18 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
76 | uint32_t *datalen, uint32_t *cdatalen) | 76 | uint32_t *datalen, uint32_t *cdatalen) |
77 | { | 77 | { |
78 | int ret = JFFS2_COMPR_NONE; | 78 | int ret = JFFS2_COMPR_NONE; |
79 | int compr_ret; | 79 | int mode, compr_ret; |
80 | struct jffs2_compressor *this, *best=NULL; | 80 | struct jffs2_compressor *this, *best=NULL; |
81 | unsigned char *output_buf = NULL, *tmp_buf; | 81 | unsigned char *output_buf = NULL, *tmp_buf; |
82 | uint32_t orig_slen, orig_dlen; | 82 | uint32_t orig_slen, orig_dlen; |
83 | uint32_t best_slen=0, best_dlen=0; | 83 | uint32_t best_slen=0, best_dlen=0; |
84 | 84 | ||
85 | switch (jffs2_compression_mode) { | 85 | if (c->mount_opts.override_compr) |
86 | mode = c->mount_opts.compr; | ||
87 | else | ||
88 | mode = jffs2_compression_mode; | ||
89 | |||
90 | switch (mode) { | ||
86 | case JFFS2_COMPR_MODE_NONE: | 91 | case JFFS2_COMPR_MODE_NONE: |
87 | break; | 92 | break; |
88 | case JFFS2_COMPR_MODE_PRIORITY: | 93 | case JFFS2_COMPR_MODE_PRIORITY: |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index bbcb9755dd2b..5d54b4ed1b6c 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -379,7 +379,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags) | |||
379 | jffs2_do_setattr(inode, &iattr); | 379 | jffs2_do_setattr(inode, &iattr); |
380 | } | 380 | } |
381 | 381 | ||
382 | int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) | 382 | int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data) |
383 | { | 383 | { |
384 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 384 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
385 | 385 | ||
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 0bc6a6c80a56..55a0c1dceadf 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -29,6 +29,11 @@ | |||
29 | 29 | ||
30 | struct jffs2_inodirty; | 30 | struct jffs2_inodirty; |
31 | 31 | ||
32 | struct jffs2_mount_opts { | ||
33 | bool override_compr; | ||
34 | unsigned int compr; | ||
35 | }; | ||
36 | |||
32 | /* A struct for the overall file system control. Pointers to | 37 | /* A struct for the overall file system control. Pointers to |
33 | jffs2_sb_info structs are named `c' in the source code. | 38 | jffs2_sb_info structs are named `c' in the source code. |
34 | Nee jffs_control | 39 | Nee jffs_control |
@@ -126,6 +131,7 @@ struct jffs2_sb_info { | |||
126 | #endif | 131 | #endif |
127 | 132 | ||
128 | struct jffs2_summary *summary; /* Summary information */ | 133 | struct jffs2_summary *summary; /* Summary information */ |
134 | struct jffs2_mount_opts mount_opts; | ||
129 | 135 | ||
130 | #ifdef CONFIG_JFFS2_FS_XATTR | 136 | #ifdef CONFIG_JFFS2_FS_XATTR |
131 | #define XATTRINDEX_HASHSIZE (57) | 137 | #define XATTRINDEX_HASHSIZE (57) |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 6c1755c59c0f..ab65ee3ec858 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -176,7 +176,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags); | |||
176 | struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, | 176 | struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, |
177 | struct jffs2_raw_inode *ri); | 177 | struct jffs2_raw_inode *ri); |
178 | int jffs2_statfs (struct dentry *, struct kstatfs *); | 178 | int jffs2_statfs (struct dentry *, struct kstatfs *); |
179 | int jffs2_remount_fs (struct super_block *, int *, char *); | 179 | int jffs2_do_remount_fs(struct super_block *, int *, char *); |
180 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); | 180 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); |
181 | void jffs2_gc_release_inode(struct jffs2_sb_info *c, | 181 | void jffs2_gc_release_inode(struct jffs2_sb_info *c, |
182 | struct jffs2_inode_info *f); | 182 | struct jffs2_inode_info *f); |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 853b8e300084..40f6e6385fd1 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -17,11 +17,13 @@ | |||
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/parser.h> | ||
20 | #include <linux/jffs2.h> | 21 | #include <linux/jffs2.h> |
21 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
22 | #include <linux/mtd/super.h> | 23 | #include <linux/mtd/super.h> |
23 | #include <linux/ctype.h> | 24 | #include <linux/ctype.h> |
24 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
26 | #include <linux/seq_file.h> | ||
25 | #include <linux/exportfs.h> | 27 | #include <linux/exportfs.h> |
26 | #include "compr.h" | 28 | #include "compr.h" |
27 | #include "nodelist.h" | 29 | #include "nodelist.h" |
@@ -75,6 +77,29 @@ static void jffs2_write_super(struct super_block *sb) | |||
75 | unlock_super(sb); | 77 | unlock_super(sb); |
76 | } | 78 | } |
77 | 79 | ||
80 | static const char *jffs2_compr_name(unsigned int compr) | ||
81 | { | ||
82 | switch (compr) { | ||
83 | case JFFS2_COMPR_MODE_NONE: | ||
84 | return "none"; | ||
85 | default: | ||
86 | /* should never happen; programmer error */ | ||
87 | WARN_ON(1); | ||
88 | return ""; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static int jffs2_show_options(struct seq_file *s, struct vfsmount *mnt) | ||
93 | { | ||
94 | struct jffs2_sb_info *c = JFFS2_SB_INFO(mnt->mnt_sb); | ||
95 | struct jffs2_mount_opts *opts = &c->mount_opts; | ||
96 | |||
97 | if (opts->override_compr) | ||
98 | seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
78 | static int jffs2_sync_fs(struct super_block *sb, int wait) | 103 | static int jffs2_sync_fs(struct super_block *sb, int wait) |
79 | { | 104 | { |
80 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 105 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
@@ -133,6 +158,71 @@ static const struct export_operations jffs2_export_ops = { | |||
133 | .fh_to_parent = jffs2_fh_to_parent, | 158 | .fh_to_parent = jffs2_fh_to_parent, |
134 | }; | 159 | }; |
135 | 160 | ||
161 | /* | ||
162 | * JFFS2 mount options. | ||
163 | * | ||
164 | * Opt_override_compr: override default compressor | ||
165 | * Opt_err: just end of array marker | ||
166 | */ | ||
167 | enum { | ||
168 | Opt_override_compr, | ||
169 | Opt_err, | ||
170 | }; | ||
171 | |||
172 | static const match_table_t tokens = { | ||
173 | {Opt_override_compr, "compr=%s"}, | ||
174 | {Opt_err, NULL}, | ||
175 | }; | ||
176 | |||
177 | static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) | ||
178 | { | ||
179 | substring_t args[MAX_OPT_ARGS]; | ||
180 | char *p, *name; | ||
181 | |||
182 | if (!data) | ||
183 | return 0; | ||
184 | |||
185 | while ((p = strsep(&data, ","))) { | ||
186 | int token; | ||
187 | |||
188 | if (!*p) | ||
189 | continue; | ||
190 | |||
191 | token = match_token(p, tokens, args); | ||
192 | switch (token) { | ||
193 | case Opt_override_compr: | ||
194 | name = match_strdup(&args[0]); | ||
195 | |||
196 | if (!name) | ||
197 | return -ENOMEM; | ||
198 | if (!strcmp(name, "none")) { | ||
199 | c->mount_opts.compr = JFFS2_COMPR_MODE_NONE; | ||
200 | c->mount_opts.override_compr = true; | ||
201 | } | ||
202 | kfree(name); | ||
203 | break; | ||
204 | default: | ||
205 | printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n", | ||
206 | p); | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data) | ||
215 | { | ||
216 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | ||
217 | int err; | ||
218 | |||
219 | err = jffs2_parse_options(c, data); | ||
220 | if (err) | ||
221 | return -EINVAL; | ||
222 | |||
223 | return jffs2_do_remount_fs(sb, flags, data); | ||
224 | } | ||
225 | |||
136 | static const struct super_operations jffs2_super_operations = | 226 | static const struct super_operations jffs2_super_operations = |
137 | { | 227 | { |
138 | .alloc_inode = jffs2_alloc_inode, | 228 | .alloc_inode = jffs2_alloc_inode, |
@@ -143,6 +233,7 @@ static const struct super_operations jffs2_super_operations = | |||
143 | .remount_fs = jffs2_remount_fs, | 233 | .remount_fs = jffs2_remount_fs, |
144 | .evict_inode = jffs2_evict_inode, | 234 | .evict_inode = jffs2_evict_inode, |
145 | .dirty_inode = jffs2_dirty_inode, | 235 | .dirty_inode = jffs2_dirty_inode, |
236 | .show_options = jffs2_show_options, | ||
146 | .sync_fs = jffs2_sync_fs, | 237 | .sync_fs = jffs2_sync_fs, |
147 | }; | 238 | }; |
148 | 239 | ||
@@ -166,6 +257,12 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) | |||
166 | c->os_priv = sb; | 257 | c->os_priv = sb; |
167 | sb->s_fs_info = c; | 258 | sb->s_fs_info = c; |
168 | 259 | ||
260 | ret = jffs2_parse_options(c, data); | ||
261 | if (ret) { | ||
262 | kfree(c); | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | |||
169 | /* Initialize JFFS2 superblock locks, the further initialization will | 266 | /* Initialize JFFS2 superblock locks, the further initialization will |
170 | * be done later */ | 267 | * be done later */ |
171 | mutex_init(&c->alloc_sem); | 268 | mutex_init(&c->alloc_sem); |