Branch data Line data Source code
1 : : /*
2 : : * JFFS2 -- Journalling Flash File System, Version 2.
3 : : *
4 : : * Copyright © 2001-2007 Red Hat, Inc.
5 : : *
6 : : * Created by David Woodhouse <dwmw2@infradead.org>
7 : : *
8 : : * For licensing information, see the file 'LICENCE' in this directory.
9 : : *
10 : : */
11 : :
12 : : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 : :
14 : : #include <linux/kernel.h>
15 : : #include <linux/module.h>
16 : : #include <linux/slab.h>
17 : : #include <linux/init.h>
18 : : #include <linux/list.h>
19 : : #include <linux/fs.h>
20 : : #include <linux/err.h>
21 : : #include <linux/mount.h>
22 : : #include <linux/parser.h>
23 : : #include <linux/jffs2.h>
24 : : #include <linux/pagemap.h>
25 : : #include <linux/mtd/super.h>
26 : : #include <linux/ctype.h>
27 : : #include <linux/namei.h>
28 : : #include <linux/seq_file.h>
29 : : #include <linux/exportfs.h>
30 : : #include "compr.h"
31 : : #include "nodelist.h"
32 : :
33 : : static void jffs2_put_super(struct super_block *);
34 : :
35 : : static struct kmem_cache *jffs2_inode_cachep;
36 : :
37 : 0 : static struct inode *jffs2_alloc_inode(struct super_block *sb)
38 : : {
39 : : struct jffs2_inode_info *f;
40 : :
41 : 0 : f = kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
42 [ # # ]: 0 : if (!f)
43 : : return NULL;
44 : 0 : return &f->vfs_inode;
45 : : }
46 : :
47 : 0 : static void jffs2_i_callback(struct rcu_head *head)
48 : : {
49 : : struct inode *inode = container_of(head, struct inode, i_rcu);
50 : 0 : kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
51 : 0 : }
52 : :
53 : 0 : static void jffs2_destroy_inode(struct inode *inode)
54 : : {
55 : 0 : call_rcu(&inode->i_rcu, jffs2_i_callback);
56 : 0 : }
57 : :
58 : 0 : static void jffs2_i_init_once(void *foo)
59 : : {
60 : : struct jffs2_inode_info *f = foo;
61 : :
62 : 0 : mutex_init(&f->sem);
63 : 0 : inode_init_once(&f->vfs_inode);
64 : 0 : }
65 : :
66 : 0 : static const char *jffs2_compr_name(unsigned int compr)
67 : : {
68 [ # # # # ]: 0 : switch (compr) {
69 : : case JFFS2_COMPR_MODE_NONE:
70 : : return "none";
71 : : #ifdef CONFIG_JFFS2_LZO
72 : : case JFFS2_COMPR_MODE_FORCELZO:
73 : 0 : return "lzo";
74 : : #endif
75 : : #ifdef CONFIG_JFFS2_ZLIB
76 : : case JFFS2_COMPR_MODE_FORCEZLIB:
77 : 0 : return "zlib";
78 : : #endif
79 : : default:
80 : : /* should never happen; programmer error */
81 : 0 : WARN_ON(1);
82 : 0 : return "";
83 : : }
84 : : }
85 : :
86 : 0 : static int jffs2_show_options(struct seq_file *s, struct dentry *root)
87 : : {
88 : 0 : struct jffs2_sb_info *c = JFFS2_SB_INFO(root->d_sb);
89 : : struct jffs2_mount_opts *opts = &c->mount_opts;
90 : :
91 [ # # ]: 0 : if (opts->override_compr)
92 : 0 : seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr));
93 [ # # ]: 0 : if (opts->rp_size)
94 : 0 : seq_printf(s, ",rp_size=%u", opts->rp_size / 1024);
95 : :
96 : 0 : return 0;
97 : : }
98 : :
99 : 0 : static int jffs2_sync_fs(struct super_block *sb, int wait)
100 : : {
101 : 0 : struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
102 : :
103 : : #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
104 : 0 : cancel_delayed_work_sync(&c->wbuf_dwork);
105 : : #endif
106 : :
107 : 0 : mutex_lock(&c->alloc_sem);
108 : 0 : jffs2_flush_wbuf_pad(c);
109 : 0 : mutex_unlock(&c->alloc_sem);
110 : 0 : return 0;
111 : : }
112 : :
113 : 0 : static struct inode *jffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
114 : : uint32_t generation)
115 : : {
116 : : /* We don't care about i_generation. We'll destroy the flash
117 : : before we start re-using inode numbers anyway. And even
118 : : if that wasn't true, we'd have other problems...*/
119 : 0 : return jffs2_iget(sb, ino);
120 : : }
121 : :
122 : 0 : static struct dentry *jffs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
123 : : int fh_len, int fh_type)
124 : : {
125 : 0 : return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
126 : : jffs2_nfs_get_inode);
127 : : }
128 : :
129 : 0 : static struct dentry *jffs2_fh_to_parent(struct super_block *sb, struct fid *fid,
130 : : int fh_len, int fh_type)
131 : : {
132 : 0 : return generic_fh_to_parent(sb, fid, fh_len, fh_type,
133 : : jffs2_nfs_get_inode);
134 : : }
135 : :
136 : 0 : static struct dentry *jffs2_get_parent(struct dentry *child)
137 : : {
138 : : struct jffs2_inode_info *f;
139 : : uint32_t pino;
140 : :
141 [ # # ]: 0 : BUG_ON(!S_ISDIR(child->d_inode->i_mode));
142 : :
143 : : f = JFFS2_INODE_INFO(child->d_inode);
144 : :
145 : 0 : pino = f->inocache->pino_nlink;
146 : :
147 : 0 : JFFS2_DEBUG("Parent of directory ino #%u is #%u\n",
148 : : f->inocache->ino, pino);
149 : :
150 : 0 : return d_obtain_alias(jffs2_iget(child->d_inode->i_sb, pino));
151 : : }
152 : :
153 : : static const struct export_operations jffs2_export_ops = {
154 : : .get_parent = jffs2_get_parent,
155 : : .fh_to_dentry = jffs2_fh_to_dentry,
156 : : .fh_to_parent = jffs2_fh_to_parent,
157 : : };
158 : :
159 : : /*
160 : : * JFFS2 mount options.
161 : : *
162 : : * Opt_override_compr: override default compressor
163 : : * Opt_rp_size: size of reserved pool in KiB
164 : : * Opt_err: just end of array marker
165 : : */
166 : : enum {
167 : : Opt_override_compr,
168 : : Opt_rp_size,
169 : : Opt_err,
170 : : };
171 : :
172 : : static const match_table_t tokens = {
173 : : {Opt_override_compr, "compr=%s"},
174 : : {Opt_rp_size, "rp_size=%u"},
175 : : {Opt_err, NULL},
176 : : };
177 : :
178 : 0 : static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
179 : : {
180 : : substring_t args[MAX_OPT_ARGS];
181 : : char *p, *name;
182 : : unsigned int opt;
183 : :
184 [ # # ]: 0 : if (!data)
185 : : return 0;
186 : :
187 [ # # ]: 0 : while ((p = strsep(&data, ","))) {
188 : : int token;
189 : :
190 [ # # ]: 0 : if (!*p)
191 : 0 : continue;
192 : :
193 : 0 : token = match_token(p, tokens, args);
194 [ # # # ]: 0 : switch (token) {
195 : : case Opt_override_compr:
196 : 0 : name = match_strdup(&args[0]);
197 : :
198 [ # # ]: 0 : if (!name)
199 : : return -ENOMEM;
200 [ # # ]: 0 : if (!strcmp(name, "none"))
201 : 0 : c->mount_opts.compr = JFFS2_COMPR_MODE_NONE;
202 : : #ifdef CONFIG_JFFS2_LZO
203 [ # # ]: 0 : else if (!strcmp(name, "lzo"))
204 : 0 : c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO;
205 : : #endif
206 : : #ifdef CONFIG_JFFS2_ZLIB
207 [ # # ]: 0 : else if (!strcmp(name, "zlib"))
208 : 0 : c->mount_opts.compr =
209 : : JFFS2_COMPR_MODE_FORCEZLIB;
210 : : #endif
211 : : else {
212 : 0 : pr_err("Error: unknown compressor \"%s\"\n",
213 : : name);
214 : 0 : kfree(name);
215 : 0 : return -EINVAL;
216 : : }
217 : 0 : kfree(name);
218 : 0 : c->mount_opts.override_compr = true;
219 : 0 : break;
220 : : case Opt_rp_size:
221 [ # # ]: 0 : if (match_int(&args[0], &opt))
222 : : return -EINVAL;
223 : 0 : opt *= 1024;
224 [ # # ]: 0 : if (opt > c->mtd->size) {
225 : 0 : pr_warn("Too large reserve pool specified, max "
226 : : "is %llu KB\n", c->mtd->size / 1024);
227 : 0 : return -EINVAL;
228 : : }
229 : 0 : c->mount_opts.rp_size = opt;
230 : 0 : break;
231 : : default:
232 : 0 : pr_err("Error: unrecognized mount option '%s' or missing value\n",
233 : : p);
234 : 0 : return -EINVAL;
235 : : }
236 : : }
237 : :
238 : : return 0;
239 : : }
240 : :
241 : 0 : static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data)
242 : : {
243 : 0 : struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
244 : : int err;
245 : :
246 : 0 : err = jffs2_parse_options(c, data);
247 [ # # ]: 0 : if (err)
248 : : return -EINVAL;
249 : :
250 : 0 : return jffs2_do_remount_fs(sb, flags, data);
251 : : }
252 : :
253 : : static const struct super_operations jffs2_super_operations =
254 : : {
255 : : .alloc_inode = jffs2_alloc_inode,
256 : : .destroy_inode =jffs2_destroy_inode,
257 : : .put_super = jffs2_put_super,
258 : : .statfs = jffs2_statfs,
259 : : .remount_fs = jffs2_remount_fs,
260 : : .evict_inode = jffs2_evict_inode,
261 : : .dirty_inode = jffs2_dirty_inode,
262 : : .show_options = jffs2_show_options,
263 : : .sync_fs = jffs2_sync_fs,
264 : : };
265 : :
266 : : /*
267 : : * fill in the superblock
268 : : */
269 : 0 : static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
270 : : {
271 : : struct jffs2_sb_info *c;
272 : : int ret;
273 : :
274 : : jffs2_dbg(1, "jffs2_get_sb_mtd():"
275 : : " New superblock for device %d (\"%s\")\n",
276 : : sb->s_mtd->index, sb->s_mtd->name);
277 : :
278 : : c = kzalloc(sizeof(*c), GFP_KERNEL);
279 [ # # ]: 0 : if (!c)
280 : : return -ENOMEM;
281 : :
282 : 0 : c->mtd = sb->s_mtd;
283 : 0 : c->os_priv = sb;
284 : 0 : sb->s_fs_info = c;
285 : :
286 : 0 : ret = jffs2_parse_options(c, data);
287 [ # # ]: 0 : if (ret) {
288 : 0 : kfree(c);
289 : 0 : return -EINVAL;
290 : : }
291 : :
292 : : /* Initialize JFFS2 superblock locks, the further initialization will
293 : : * be done later */
294 : 0 : mutex_init(&c->alloc_sem);
295 : 0 : mutex_init(&c->erase_free_sem);
296 : 0 : init_waitqueue_head(&c->erase_wait);
297 : 0 : init_waitqueue_head(&c->inocache_wq);
298 : 0 : spin_lock_init(&c->erase_completion_lock);
299 : 0 : spin_lock_init(&c->inocache_lock);
300 : :
301 : 0 : sb->s_op = &jffs2_super_operations;
302 : 0 : sb->s_export_op = &jffs2_export_ops;
303 : 0 : sb->s_flags = sb->s_flags | MS_NOATIME;
304 : 0 : sb->s_xattr = jffs2_xattr_handlers;
305 : : #ifdef CONFIG_JFFS2_FS_POSIX_ACL
306 : 0 : sb->s_flags |= MS_POSIXACL;
307 : : #endif
308 : 0 : ret = jffs2_do_fill_super(sb, data, silent);
309 : 0 : return ret;
310 : : }
311 : :
312 : 0 : static struct dentry *jffs2_mount(struct file_system_type *fs_type,
313 : : int flags, const char *dev_name,
314 : : void *data)
315 : : {
316 : 0 : return mount_mtd(fs_type, flags, dev_name, data, jffs2_fill_super);
317 : : }
318 : :
319 : 0 : static void jffs2_put_super (struct super_block *sb)
320 : : {
321 : 0 : struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
322 : :
323 : : jffs2_dbg(2, "%s()\n", __func__);
324 : :
325 : 0 : mutex_lock(&c->alloc_sem);
326 : 0 : jffs2_flush_wbuf_pad(c);
327 : 0 : mutex_unlock(&c->alloc_sem);
328 : :
329 : 0 : jffs2_sum_exit(c);
330 : :
331 : 0 : jffs2_free_ino_caches(c);
332 : 0 : jffs2_free_raw_node_refs(c);
333 [ # # ]: 0 : if (jffs2_blocks_use_vmalloc(c))
334 : 0 : vfree(c->blocks);
335 : : else
336 : 0 : kfree(c->blocks);
337 : 0 : jffs2_flash_cleanup(c);
338 : 0 : kfree(c->inocache_list);
339 : 0 : jffs2_clear_xattr_subsystem(c);
340 : 0 : mtd_sync(c->mtd);
341 : : jffs2_dbg(1, "%s(): returning\n", __func__);
342 : 0 : }
343 : :
344 : 0 : static void jffs2_kill_sb(struct super_block *sb)
345 : : {
346 : 0 : struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
347 [ # # ]: 0 : if (!(sb->s_flags & MS_RDONLY))
348 : 0 : jffs2_stop_garbage_collect_thread(c);
349 : 0 : kill_mtd_super(sb);
350 : 0 : kfree(c);
351 : 0 : }
352 : :
353 : : static struct file_system_type jffs2_fs_type = {
354 : : .owner = THIS_MODULE,
355 : : .name = "jffs2",
356 : : .mount = jffs2_mount,
357 : : .kill_sb = jffs2_kill_sb,
358 : : };
359 : : MODULE_ALIAS_FS("jffs2");
360 : :
361 : 0 : static int __init init_jffs2_fs(void)
362 : : {
363 : : int ret;
364 : :
365 : : /* Paranoia checks for on-medium structures. If we ask GCC
366 : : to pack them with __attribute__((packed)) then it _also_
367 : : assumes that they're not aligned -- so it emits crappy
368 : : code on some architectures. Ideally we want an attribute
369 : : which means just 'no padding', without the alignment
370 : : thing. But GCC doesn't have that -- we have to just
371 : : hope the structs are the right sizes, instead. */
372 : : BUILD_BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
373 : : BUILD_BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
374 : : BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
375 : : BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
376 : :
377 : 0 : pr_info("version 2.2."
378 : : #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
379 : : " (NAND)"
380 : : #endif
381 : : #ifdef CONFIG_JFFS2_SUMMARY
382 : : " (SUMMARY) "
383 : : #endif
384 : : " © 2001-2006 Red Hat, Inc.\n");
385 : :
386 : 0 : jffs2_inode_cachep = kmem_cache_create("jffs2_i",
387 : : sizeof(struct jffs2_inode_info),
388 : : 0, (SLAB_RECLAIM_ACCOUNT|
389 : : SLAB_MEM_SPREAD),
390 : : jffs2_i_init_once);
391 [ # # ]: 0 : if (!jffs2_inode_cachep) {
392 : 0 : pr_err("error: Failed to initialise inode cache\n");
393 : 0 : return -ENOMEM;
394 : : }
395 : 0 : ret = jffs2_compressors_init();
396 [ # # ]: 0 : if (ret) {
397 : 0 : pr_err("error: Failed to initialise compressors\n");
398 : 0 : goto out;
399 : : }
400 : 0 : ret = jffs2_create_slab_caches();
401 [ # # ]: 0 : if (ret) {
402 : 0 : pr_err("error: Failed to initialise slab caches\n");
403 : 0 : goto out_compressors;
404 : : }
405 : 0 : ret = register_filesystem(&jffs2_fs_type);
406 [ # # ]: 0 : if (ret) {
407 : 0 : pr_err("error: Failed to register filesystem\n");
408 : : goto out_slab;
409 : : }
410 : : return 0;
411 : :
412 : : out_slab:
413 : 0 : jffs2_destroy_slab_caches();
414 : : out_compressors:
415 : 0 : jffs2_compressors_exit();
416 : : out:
417 : 0 : kmem_cache_destroy(jffs2_inode_cachep);
418 : 0 : return ret;
419 : : }
420 : :
421 : 0 : static void __exit exit_jffs2_fs(void)
422 : : {
423 : 0 : unregister_filesystem(&jffs2_fs_type);
424 : 0 : jffs2_destroy_slab_caches();
425 : 0 : jffs2_compressors_exit();
426 : :
427 : : /*
428 : : * Make sure all delayed rcu free inodes are flushed before we
429 : : * destroy cache.
430 : : */
431 : 0 : rcu_barrier();
432 : 0 : kmem_cache_destroy(jffs2_inode_cachep);
433 : 0 : }
434 : :
435 : : module_init(init_jffs2_fs);
436 : : module_exit(exit_jffs2_fs);
437 : :
438 : : MODULE_DESCRIPTION("The Journalling Flash File System, v2");
439 : : MODULE_AUTHOR("Red Hat, Inc.");
440 : : MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for
441 : : // the sake of this tag. It's Free Software.
|