Blame view

fs/jffs2/super.c 10.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * JFFS2 -- Journalling Flash File System, Version 2.
   *
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
4
   * Copyright © 2001-2007 Red Hat, Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
   *
   * Created by David Woodhouse <dwmw2@infradead.org>
   *
   * For licensing information, see the file 'LICENCE' in this directory.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
   */
5a528957e   Joe Perches   jffs2: Use pr_fmt...
11
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/list.h>
  #include <linux/fs.h>
9c74034f8   Artem Bityutskiy   [MTD] return erro...
18
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/mount.h>
92abc475d   Andres Salomon   jffs2: implement ...
20
  #include <linux/parser.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
  #include <linux/jffs2.h>
  #include <linux/pagemap.h>
acaebfd8a   David Howells   [MTD] generalise ...
23
  #include <linux/mtd/super.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #include <linux/ctype.h>
  #include <linux/namei.h>
92abc475d   Andres Salomon   jffs2: implement ...
26
  #include <linux/seq_file.h>
5f556aab9   David Woodhouse   [JFFS2] Reinstate...
27
  #include <linux/exportfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
30
31
  #include "compr.h"
  #include "nodelist.h"
  
  static void jffs2_put_super(struct super_block *);
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
32
  static struct kmem_cache *jffs2_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
  
  static struct inode *jffs2_alloc_inode(struct super_block *sb)
  {
4e571aba7   David Woodhouse   [JFFS2] Clean up ...
36
37
38
39
  	struct jffs2_inode_info *f;
  
  	f = kmem_cache_alloc(jffs2_inode_cachep, GFP_KERNEL);
  	if (!f)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  		return NULL;
4e571aba7   David Woodhouse   [JFFS2] Clean up ...
41
  	return &f->vfs_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
43
  static void jffs2_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
45
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
  	kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
48
49
50
51
  static void jffs2_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, jffs2_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
52
  static void jffs2_i_init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  {
4e571aba7   David Woodhouse   [JFFS2] Clean up ...
54
  	struct jffs2_inode_info *f = foo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

4e571aba7   David Woodhouse   [JFFS2] Clean up ...
56
57
  	mutex_init(&f->sem);
  	inode_init_once(&f->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  }
92abc475d   Andres Salomon   jffs2: implement ...
59
60
61
62
63
  static const char *jffs2_compr_name(unsigned int compr)
  {
  	switch (compr) {
  	case JFFS2_COMPR_MODE_NONE:
  		return "none";
123005f3c   Andres Salomon   jffs2: add compr=...
64
65
66
67
68
69
70
71
  #ifdef CONFIG_JFFS2_LZO
  	case JFFS2_COMPR_MODE_FORCELZO:
  		return "lzo";
  #endif
  #ifdef CONFIG_JFFS2_ZLIB
  	case JFFS2_COMPR_MODE_FORCEZLIB:
  		return "zlib";
  #endif
92abc475d   Andres Salomon   jffs2: implement ...
72
73
74
75
76
77
  	default:
  		/* should never happen; programmer error */
  		WARN_ON(1);
  		return "";
  	}
  }
34c80b1d9   Al Viro   vfs: switch ->sho...
78
  static int jffs2_show_options(struct seq_file *s, struct dentry *root)
92abc475d   Andres Salomon   jffs2: implement ...
79
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
80
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(root->d_sb);
92abc475d   Andres Salomon   jffs2: implement ...
81
82
83
84
  	struct jffs2_mount_opts *opts = &c->mount_opts;
  
  	if (opts->override_compr)
  		seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr));
8da8ba2ea   Daniel Drake   JFFS2: Add parame...
85
86
  	if (opts->rp_size)
  		seq_printf(s, ",rp_size=%u", opts->rp_size / 1024);
92abc475d   Andres Salomon   jffs2: implement ...
87
88
89
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
  static int jffs2_sync_fs(struct super_block *sb, int wait)
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
a445f784a   Artem Bityutskiy   JFFS2: fix unmoun...
93
94
95
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
  	cancel_delayed_work_sync(&c->wbuf_dwork);
  #endif
ced220703   David Woodhouse   [JFFS2] semaphore...
96
  	mutex_lock(&c->alloc_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  	jffs2_flush_wbuf_pad(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
98
  	mutex_unlock(&c->alloc_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
  	return 0;
  }
5f556aab9   David Woodhouse   [JFFS2] Reinstate...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  static struct inode *jffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
  					 uint32_t generation)
  {
  	/* We don't care about i_generation. We'll destroy the flash
  	   before we start re-using inode numbers anyway. And even
  	   if that wasn't true, we'd have other problems...*/
  	return jffs2_iget(sb, ino);
  }
  
  static struct dentry *jffs2_fh_to_dentry(struct super_block *sb, struct fid *fid,
  					 int fh_len, int fh_type)
  {
          return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
                                      jffs2_nfs_get_inode);
  }
  
  static struct dentry *jffs2_fh_to_parent(struct super_block *sb, struct fid *fid,
  					 int fh_len, int fh_type)
  {
          return generic_fh_to_parent(sb, fid, fh_len, fh_type,
                                      jffs2_nfs_get_inode);
  }
  
  static struct dentry *jffs2_get_parent(struct dentry *child)
  {
  	struct jffs2_inode_info *f;
  	uint32_t pino;
  
  	BUG_ON(!S_ISDIR(child->d_inode->i_mode));
  
  	f = JFFS2_INODE_INFO(child->d_inode);
  
  	pino = f->inocache->pino_nlink;
  
  	JFFS2_DEBUG("Parent of directory ino #%u is #%u
  ",
  		    f->inocache->ino, pino);
  
  	return d_obtain_alias(jffs2_iget(child->d_inode->i_sb, pino));
  }
ac4cfdd6d   Alexey Dobriyan   const: mark remai...
141
  static const struct export_operations jffs2_export_ops = {
5f556aab9   David Woodhouse   [JFFS2] Reinstate...
142
143
144
145
  	.get_parent = jffs2_get_parent,
  	.fh_to_dentry = jffs2_fh_to_dentry,
  	.fh_to_parent = jffs2_fh_to_parent,
  };
92abc475d   Andres Salomon   jffs2: implement ...
146
147
148
149
  /*
   * JFFS2 mount options.
   *
   * Opt_override_compr: override default compressor
8da8ba2ea   Daniel Drake   JFFS2: Add parame...
150
   * Opt_rp_size: size of reserved pool in KiB
92abc475d   Andres Salomon   jffs2: implement ...
151
152
153
154
   * Opt_err: just end of array marker
   */
  enum {
  	Opt_override_compr,
8da8ba2ea   Daniel Drake   JFFS2: Add parame...
155
  	Opt_rp_size,
92abc475d   Andres Salomon   jffs2: implement ...
156
157
158
159
160
  	Opt_err,
  };
  
  static const match_table_t tokens = {
  	{Opt_override_compr, "compr=%s"},
8da8ba2ea   Daniel Drake   JFFS2: Add parame...
161
  	{Opt_rp_size, "rp_size=%u"},
92abc475d   Andres Salomon   jffs2: implement ...
162
163
164
165
166
167
168
  	{Opt_err, NULL},
  };
  
  static int jffs2_parse_options(struct jffs2_sb_info *c, char *data)
  {
  	substring_t args[MAX_OPT_ARGS];
  	char *p, *name;
8da8ba2ea   Daniel Drake   JFFS2: Add parame...
169
  	unsigned int opt;
92abc475d   Andres Salomon   jffs2: implement ...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  
  	if (!data)
  		return 0;
  
  	while ((p = strsep(&data, ","))) {
  		int token;
  
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_override_compr:
  			name = match_strdup(&args[0]);
  
  			if (!name)
  				return -ENOMEM;
123005f3c   Andres Salomon   jffs2: add compr=...
187
  			if (!strcmp(name, "none"))
92abc475d   Andres Salomon   jffs2: implement ...
188
  				c->mount_opts.compr = JFFS2_COMPR_MODE_NONE;
123005f3c   Andres Salomon   jffs2: add compr=...
189
190
191
192
193
194
195
196
197
198
  #ifdef CONFIG_JFFS2_LZO
  			else if (!strcmp(name, "lzo"))
  				c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO;
  #endif
  #ifdef CONFIG_JFFS2_ZLIB
  			else if (!strcmp(name, "zlib"))
  				c->mount_opts.compr =
  						JFFS2_COMPR_MODE_FORCEZLIB;
  #endif
  			else {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
199
200
  				pr_err("Error: unknown compressor \"%s\"
  ",
da320f055   Joe Perches   jffs2: Convert pr...
201
  				       name);
123005f3c   Andres Salomon   jffs2: add compr=...
202
203
  				kfree(name);
  				return -EINVAL;
92abc475d   Andres Salomon   jffs2: implement ...
204
205
  			}
  			kfree(name);
123005f3c   Andres Salomon   jffs2: add compr=...
206
  			c->mount_opts.override_compr = true;
92abc475d   Andres Salomon   jffs2: implement ...
207
  			break;
8da8ba2ea   Daniel Drake   JFFS2: Add parame...
208
209
210
211
212
213
214
215
216
217
218
219
  		case Opt_rp_size:
  			if (match_int(&args[0], &opt))
  				return -EINVAL;
  			opt *= 1024;
  			if (opt > c->mtd->size) {
  				pr_warn("Too large reserve pool specified, max "
  					"is %llu KB
  ", c->mtd->size / 1024);
  				return -EINVAL;
  			}
  			c->mount_opts.rp_size = opt;
  			break;
92abc475d   Andres Salomon   jffs2: implement ...
220
  		default:
5a528957e   Joe Perches   jffs2: Use pr_fmt...
221
222
  			pr_err("Error: unrecognized mount option '%s' or missing value
  ",
da320f055   Joe Perches   jffs2: Convert pr...
223
  			       p);
92abc475d   Andres Salomon   jffs2: implement ...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  			return -EINVAL;
  		}
  	}
  
  	return 0;
  }
  
  static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data)
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
  	int err;
  
  	err = jffs2_parse_options(c, data);
  	if (err)
  		return -EINVAL;
  
  	return jffs2_do_remount_fs(sb, flags, data);
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
242
  static const struct super_operations jffs2_super_operations =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
  {
  	.alloc_inode =	jffs2_alloc_inode,
  	.destroy_inode =jffs2_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  	.put_super =	jffs2_put_super,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
  	.statfs =	jffs2_statfs,
  	.remount_fs =	jffs2_remount_fs,
b57922d97   Al Viro   convert remaining...
249
  	.evict_inode =	jffs2_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	.dirty_inode =	jffs2_dirty_inode,
92abc475d   Andres Salomon   jffs2: implement ...
251
  	.show_options =	jffs2_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
  	.sync_fs =	jffs2_sync_fs,
  };
acaebfd8a   David Howells   [MTD] generalise ...
254
255
256
257
  /*
   * fill in the superblock
   */
  static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  	struct jffs2_sb_info *c;
db7192221   Jan Blunck   BKL: Explicitly a...
260
  	int ret;
9c261b33a   Joe Perches   jffs2: Convert mo...
261
  	jffs2_dbg(1, "jffs2_get_sb_mtd():"
acaebfd8a   David Howells   [MTD] generalise ...
262
263
  		  " New superblock for device %d (\"%s\")
  ",
9c261b33a   Joe Perches   jffs2: Convert mo...
264
  		  sb->s_mtd->index, sb->s_mtd->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
266
  	c = kzalloc(sizeof(*c), GFP_KERNEL);
1a028dd2d   Arnd Bergmann   BKL: Remove BKL f...
267
  	if (!c)
454e2398b   David Howells   [PATCH] VFS: Perm...
268
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269

acaebfd8a   David Howells   [MTD] generalise ...
270
271
272
  	c->mtd = sb->s_mtd;
  	c->os_priv = sb;
  	sb->s_fs_info = c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

92abc475d   Andres Salomon   jffs2: implement ...
274
275
276
277
278
  	ret = jffs2_parse_options(c, data);
  	if (ret) {
  		kfree(c);
  		return -EINVAL;
  	}
acaebfd8a   David Howells   [MTD] generalise ...
279
280
  	/* Initialize JFFS2 superblock locks, the further initialization will
  	 * be done later */
ced220703   David Woodhouse   [JFFS2] semaphore...
281
282
  	mutex_init(&c->alloc_sem);
  	mutex_init(&c->erase_free_sem);
b62205986   Artem B. Bityuckiy   [JFFS2] Init lock...
283
284
285
286
  	init_waitqueue_head(&c->erase_wait);
  	init_waitqueue_head(&c->inocache_wq);
  	spin_lock_init(&c->erase_completion_lock);
  	spin_lock_init(&c->inocache_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	sb->s_op = &jffs2_super_operations;
5f556aab9   David Woodhouse   [JFFS2] Reinstate...
288
  	sb->s_export_op = &jffs2_export_ops;
acaebfd8a   David Howells   [MTD] generalise ...
289
  	sb->s_flags = sb->s_flags | MS_NOATIME;
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
290
291
292
293
  	sb->s_xattr = jffs2_xattr_handlers;
  #ifdef CONFIG_JFFS2_FS_POSIX_ACL
  	sb->s_flags |= MS_POSIXACL;
  #endif
db7192221   Jan Blunck   BKL: Explicitly a...
294
  	ret = jffs2_do_fill_super(sb, data, silent);
db7192221   Jan Blunck   BKL: Explicitly a...
295
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  }
848b83a59   Al Viro   convert get_sb_mt...
297
  static struct dentry *jffs2_mount(struct file_system_type *fs_type,
454e2398b   David Howells   [PATCH] VFS: Perm...
298
  			int flags, const char *dev_name,
848b83a59   Al Viro   convert get_sb_mt...
299
  			void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
  {
848b83a59   Al Viro   convert get_sb_mt...
301
  	return mount_mtd(fs_type, flags, dev_name, data, jffs2_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
305
306
  }
  
  static void jffs2_put_super (struct super_block *sb)
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
9c261b33a   Joe Perches   jffs2: Convert mo...
307
308
  	jffs2_dbg(2, "%s()
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309

ced220703   David Woodhouse   [JFFS2] semaphore...
310
  	mutex_lock(&c->alloc_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  	jffs2_flush_wbuf_pad(c);
ced220703   David Woodhouse   [JFFS2] semaphore...
312
  	mutex_unlock(&c->alloc_sem);
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
313
314
  
  	jffs2_sum_exit(c);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
  	jffs2_free_ino_caches(c);
  	jffs2_free_raw_node_refs(c);
4ce1f5621   Ferenc Havasi   [JFFS2] Remove su...
317
  	if (jffs2_blocks_use_vmalloc(c))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
322
  		vfree(c->blocks);
  	else
  		kfree(c->blocks);
  	jffs2_flash_cleanup(c);
  	kfree(c->inocache_list);
aa98d7cf5   KaiGai Kohei   [JFFS2][XATTR] XA...
323
  	jffs2_clear_xattr_subsystem(c);
327cf2922   Artem Bityutskiy   mtd: do not use m...
324
  	mtd_sync(c->mtd);
9c261b33a   Joe Perches   jffs2: Convert mo...
325
326
  	jffs2_dbg(1, "%s(): returning
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
  }
  
  static void jffs2_kill_sb(struct super_block *sb)
  {
  	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
a69dde91e   Artem B. Bityuckiy   [JFFS2] Kill GC t...
332
333
  	if (!(sb->s_flags & MS_RDONLY))
  		jffs2_stop_garbage_collect_thread(c);
acaebfd8a   David Howells   [MTD] generalise ...
334
  	kill_mtd_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
339
340
  	kfree(c);
  }
  
  static struct file_system_type jffs2_fs_type = {
  	.owner =	THIS_MODULE,
  	.name =		"jffs2",
848b83a59   Al Viro   convert get_sb_mt...
341
  	.mount =	jffs2_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
344
345
346
347
  	.kill_sb =	jffs2_kill_sb,
  };
  
  static int __init init_jffs2_fs(void)
  {
  	int ret;
3e68fbb59   David Woodhouse   [JFFS2] Don't pac...
348
349
350
351
352
353
354
  	/* Paranoia checks for on-medium structures. If we ask GCC
  	   to pack them with __attribute__((packed)) then it _also_
  	   assumes that they're not aligned -- so it emits crappy
  	   code on some architectures. Ideally we want an attribute
  	   which means just 'no padding', without the alignment
  	   thing. But GCC doesn't have that -- we have to just
  	   hope the structs are the right sizes, instead. */
2ecd05ae6   Alexey Dobriyan   [PATCH] fs/*: use...
355
356
357
358
  	BUILD_BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
  	BUILD_BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
  	BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
  	BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
3e68fbb59   David Woodhouse   [JFFS2] Don't pac...
359

5a528957e   Joe Perches   jffs2: Use pr_fmt...
360
  	pr_info("version 2.2."
2f82ce1eb   Andrew Victor   [JFFS2] Use a sin...
361
  #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
  	       " (NAND)"
  #endif
e631ddba5   Ferenc Havasi   [JFFS2] Add erase...
364
365
366
  #ifdef CONFIG_JFFS2_SUMMARY
  	       " (SUMMARY) "
  #endif
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
367
368
  	       " © 2001-2006 Red Hat, Inc.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
371
  
  	jffs2_inode_cachep = kmem_cache_create("jffs2_i",
  					     sizeof(struct jffs2_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
372
373
  					     0, (SLAB_RECLAIM_ACCOUNT|
  						SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
374
  					     jffs2_i_init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  	if (!jffs2_inode_cachep) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
376
377
  		pr_err("error: Failed to initialise inode cache
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
  		return -ENOMEM;
  	}
  	ret = jffs2_compressors_init();
  	if (ret) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
382
383
  		pr_err("error: Failed to initialise compressors
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
  		goto out;
  	}
  	ret = jffs2_create_slab_caches();
  	if (ret) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
388
389
  		pr_err("error: Failed to initialise slab caches
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
393
  		goto out_compressors;
  	}
  	ret = register_filesystem(&jffs2_fs_type);
  	if (ret) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
394
395
  		pr_err("error: Failed to register filesystem
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  		goto out_slab;
  	}
  	return 0;
  
   out_slab:
  	jffs2_destroy_slab_caches();
   out_compressors:
  	jffs2_compressors_exit();
   out:
  	kmem_cache_destroy(jffs2_inode_cachep);
  	return ret;
  }
  
  static void __exit exit_jffs2_fs(void)
  {
  	unregister_filesystem(&jffs2_fs_type);
  	jffs2_destroy_slab_caches();
  	jffs2_compressors_exit();
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
414
415
416
417
418
419
  
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
425
426
427
  	kmem_cache_destroy(jffs2_inode_cachep);
  }
  
  module_init(init_jffs2_fs);
  module_exit(exit_jffs2_fs);
  
  MODULE_DESCRIPTION("The Journalling Flash File System, v2");
  MODULE_AUTHOR("Red Hat, Inc.");
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
428
  MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  		       // the sake of this tag. It's Free Software.