diff options
Diffstat (limited to 'fs/jffs2/super.c')
-rw-r--r-- | fs/jffs2/super.c | 97 |
1 files changed, 97 insertions, 0 deletions
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); |