Blame view

fs/hfs/super.c 11.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   *  linux/fs/hfs/super.c
   *
   * Copyright (C) 1995-1997  Paul H. Hargrove
   * (C) 2003 Ardis Technologies <roman@ardistech.com>
   * This file may be distributed under the terms of the GNU General Public License.
   *
   * This file contains hfs_read_super(), some of the super_ops and
   * init_module() and cleanup_module().	The remaining super_ops are in
   * inode.c since they deal with inodes.
   *
   * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  #include <linux/module.h>
  #include <linux/blkdev.h>
717dd80e9   Roman Zippel   [PATCH] hfs: show...
16
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/init.h>
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
18
  #include <linux/nls.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
  #include <linux/parser.h>
717dd80e9   Roman Zippel   [PATCH] hfs: show...
20
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
  #include <linux/vfs.h>
  
  #include "hfs_fs.h"
  #include "btree.h"
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
25
  static struct kmem_cache *hfs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  
  MODULE_LICENSE("GPL");
  
  /*
   * hfs_write_super()
   *
   * Description:
   *   This function is called by the VFS only. When the filesystem
   *   is mounted r/w it updates the MDB on disk.
   * Input Variable(s):
   *   struct super_block *sb: Pointer to the hfs superblock
   * Output Variable(s):
   *   NONE
   * Returns:
   *   void
   * Preconditions:
   *   'sb' points to a "valid" (struct super_block).
   * Postconditions:
   *   The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
   *   (hfs_put_super() must set this flag!). Some MDB fields are updated
   *   and the MDB buffer is written to disk by calling hfs_mdb_commit().
   */
  static void hfs_write_super(struct super_block *sb)
  {
  	sb->s_dirt = 0;
  	if (sb->s_flags & MS_RDONLY)
  		return;
  	/* sync everything to the buffers */
  	hfs_mdb_commit(sb);
  }
  
  /*
   * hfs_put_super()
   *
   * This is the put_super() entry in the super_operations structure for
   * HFS filesystems.  The purpose is to release the resources
   * associated with the superblock sb.
   */
  static void hfs_put_super(struct super_block *sb)
  {
  	hfs_mdb_close(sb);
  	/* release the MDB's resources */
  	hfs_mdb_put(sb);
  }
  
  /*
   * hfs_statfs()
   *
   * This is the statfs() entry in the super_operations structure for
   * HFS filesystems.  The purpose is to return various data about the
   * filesystem.
   *
   * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
   */
726c33422   David Howells   [PATCH] VFS: Perm...
80
  static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  {
726c33422   David Howells   [PATCH] VFS: Perm...
82
  	struct super_block *sb = dentry->d_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  	buf->f_type = HFS_SUPER_MAGIC;
  	buf->f_bsize = sb->s_blocksize;
  	buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div;
  	buf->f_bfree = (u32)HFS_SB(sb)->free_ablocks * HFS_SB(sb)->fs_div;
  	buf->f_bavail = buf->f_bfree;
  	buf->f_files = HFS_SB(sb)->fs_ablocks;
  	buf->f_ffree = HFS_SB(sb)->free_ablocks;
  	buf->f_namelen = HFS_NAMELEN;
  
  	return 0;
  }
  
  static int hfs_remount(struct super_block *sb, int *flags, char *data)
  {
  	*flags |= MS_NODIRATIME;
  	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
  		return 0;
  	if (!(*flags & MS_RDONLY)) {
  		if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
102
  			printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
  			       "running fsck.hfs is recommended.  leaving read-only.
  ");
  			sb->s_flags |= MS_RDONLY;
  			*flags |= MS_RDONLY;
  		} else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
108
109
  			printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
  			sb->s_flags |= MS_RDONLY;
  			*flags |= MS_RDONLY;
  		}
  	}
  	return 0;
  }
717dd80e9   Roman Zippel   [PATCH] hfs: show...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  static int hfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
  {
  	struct hfs_sb_info *sbi = HFS_SB(mnt->mnt_sb);
  
  	if (sbi->s_creator != cpu_to_be32(0x3f3f3f3f))
  		seq_printf(seq, ",creator=%.4s", (char *)&sbi->s_creator);
  	if (sbi->s_type != cpu_to_be32(0x3f3f3f3f))
  		seq_printf(seq, ",type=%.4s", (char *)&sbi->s_type);
  	seq_printf(seq, ",uid=%u,gid=%u", sbi->s_uid, sbi->s_gid);
  	if (sbi->s_file_umask != 0133)
  		seq_printf(seq, ",file_umask=%o", sbi->s_file_umask);
  	if (sbi->s_dir_umask != 0022)
  		seq_printf(seq, ",dir_umask=%o", sbi->s_dir_umask);
  	if (sbi->part >= 0)
  		seq_printf(seq, ",part=%u", sbi->part);
  	if (sbi->session >= 0)
  		seq_printf(seq, ",session=%u", sbi->session);
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
133
134
135
136
  	if (sbi->nls_disk)
  		seq_printf(seq, ",codepage=%s", sbi->nls_disk->charset);
  	if (sbi->nls_io)
  		seq_printf(seq, ",iocharset=%s", sbi->nls_io->charset);
717dd80e9   Roman Zippel   [PATCH] hfs: show...
137
138
139
140
  	if (sbi->s_quiet)
  		seq_printf(seq, ",quiet");
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
  static struct inode *hfs_alloc_inode(struct super_block *sb)
  {
  	struct hfs_inode_info *i;
e94b17660   Christoph Lameter   [PATCH] slab: rem...
144
  	i = kmem_cache_alloc(hfs_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
151
  	return i ? &i->vfs_inode : NULL;
  }
  
  static void hfs_destroy_inode(struct inode *inode)
  {
  	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
152
  static const struct super_operations hfs_super_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
  	.alloc_inode	= hfs_alloc_inode,
  	.destroy_inode	= hfs_destroy_inode,
  	.write_inode	= hfs_write_inode,
  	.clear_inode	= hfs_clear_inode,
  	.put_super	= hfs_put_super,
  	.write_super	= hfs_write_super,
  	.statfs		= hfs_statfs,
  	.remount_fs     = hfs_remount,
717dd80e9   Roman Zippel   [PATCH] hfs: show...
161
  	.show_options	= hfs_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
  };
  
  enum {
  	opt_uid, opt_gid, opt_umask, opt_file_umask, opt_dir_umask,
  	opt_part, opt_session, opt_type, opt_creator, opt_quiet,
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
167
  	opt_codepage, opt_iocharset,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  	opt_err
  };
  
  static match_table_t tokens = {
  	{ opt_uid, "uid=%u" },
  	{ opt_gid, "gid=%u" },
  	{ opt_umask, "umask=%o" },
  	{ opt_file_umask, "file_umask=%o" },
  	{ opt_dir_umask, "dir_umask=%o" },
  	{ opt_part, "part=%u" },
  	{ opt_session, "session=%u" },
  	{ opt_type, "type=%s" },
  	{ opt_creator, "creator=%s" },
  	{ opt_quiet, "quiet" },
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
182
183
  	{ opt_codepage, "codepage=%s" },
  	{ opt_iocharset, "iocharset=%s" },
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  	{ opt_err, NULL }
  };
  
  static inline int match_fourchar(substring_t *arg, u32 *result)
  {
  	if (arg->to - arg->from != 4)
  		return -EINVAL;
  	memcpy(result, arg->from, 4);
  	return 0;
  }
  
  /*
   * parse_options()
   *
   * adapted from linux/fs/msdos/inode.c written 1992,93 by Werner Almesberger
   * This function is called by hfs_read_super() to parse the mount options.
   */
  static int parse_options(char *options, struct hfs_sb_info *hsb)
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int tmp, token;
  
  	/* initialize the sb with defaults */
  	hsb->s_uid = current->uid;
  	hsb->s_gid = current->gid;
  	hsb->s_file_umask = 0133;
  	hsb->s_dir_umask = 0022;
  	hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f);	/* == '????' */
  	hsb->s_quiet = 0;
  	hsb->part = -1;
  	hsb->session = -1;
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case opt_uid:
  			if (match_int(&args[0], &tmp)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
228
229
  				printk(KERN_ERR "hfs: uid requires an argument
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
  				return 0;
  			}
  			hsb->s_uid = (uid_t)tmp;
  			break;
  		case opt_gid:
  			if (match_int(&args[0], &tmp)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
236
237
  				printk(KERN_ERR "hfs: gid requires an argument
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
  				return 0;
  			}
  			hsb->s_gid = (gid_t)tmp;
  			break;
  		case opt_umask:
  			if (match_octal(&args[0], &tmp)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
244
245
  				printk(KERN_ERR "hfs: umask requires a value
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
248
249
250
251
252
  				return 0;
  			}
  			hsb->s_file_umask = (umode_t)tmp;
  			hsb->s_dir_umask = (umode_t)tmp;
  			break;
  		case opt_file_umask:
  			if (match_octal(&args[0], &tmp)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
253
254
  				printk(KERN_ERR "hfs: file_umask requires a value
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
258
259
260
  				return 0;
  			}
  			hsb->s_file_umask = (umode_t)tmp;
  			break;
  		case opt_dir_umask:
  			if (match_octal(&args[0], &tmp)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
261
262
  				printk(KERN_ERR "hfs: dir_umask requires a value
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
266
267
268
  				return 0;
  			}
  			hsb->s_dir_umask = (umode_t)tmp;
  			break;
  		case opt_part:
  			if (match_int(&args[0], &hsb->part)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
269
270
  				printk(KERN_ERR "hfs: part requires an argument
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
275
  				return 0;
  			}
  			break;
  		case opt_session:
  			if (match_int(&args[0], &hsb->session)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
276
277
  				printk(KERN_ERR "hfs: session requires an argument
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
282
  				return 0;
  			}
  			break;
  		case opt_type:
  			if (match_fourchar(&args[0], &hsb->s_type)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
283
284
  				printk(KERN_ERR "hfs: type requires a 4 character value
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
  				return 0;
  			}
  			break;
  		case opt_creator:
  			if (match_fourchar(&args[0], &hsb->s_creator)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
290
291
  				printk(KERN_ERR "hfs: creator requires a 4 character value
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
294
295
296
297
  				return 0;
  			}
  			break;
  		case opt_quiet:
  			hsb->s_quiet = 1;
  			break;
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
298
299
  		case opt_codepage:
  			if (hsb->nls_disk) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
300
301
  				printk(KERN_ERR "hfs: unable to change codepage
  ");
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
302
303
304
305
306
  				return 0;
  			}
  			p = match_strdup(&args[0]);
  			hsb->nls_disk = load_nls(p);
  			if (!hsb->nls_disk) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
307
308
  				printk(KERN_ERR "hfs: unable to load codepage \"%s\"
  ", p);
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
309
310
311
312
313
314
315
  				kfree(p);
  				return 0;
  			}
  			kfree(p);
  			break;
  		case opt_iocharset:
  			if (hsb->nls_io) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
316
317
  				printk(KERN_ERR "hfs: unable to change iocharset
  ");
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
318
319
320
321
322
  				return 0;
  			}
  			p = match_strdup(&args[0]);
  			hsb->nls_io = load_nls(p);
  			if (!hsb->nls_io) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
323
324
  				printk(KERN_ERR "hfs: unable to load iocharset \"%s\"
  ", p);
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
325
326
327
328
329
  				kfree(p);
  				return 0;
  			}
  			kfree(p);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
  		default:
  			return 0;
  		}
  	}
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
334
335
336
  	if (hsb->nls_disk && !hsb->nls_io) {
  		hsb->nls_io = load_nls_default();
  		if (!hsb->nls_io) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
337
338
  			printk(KERN_ERR "hfs: unable to load default iocharset
  ");
328b92278   Roman Zippel   [PATCH] hfs: NLS ...
339
340
341
  			return 0;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
  	hsb->s_dir_umask &= 0777;
  	hsb->s_file_umask &= 0577;
  
  	return 1;
  }
  
  /*
   * hfs_read_super()
   *
   * This is the function that is responsible for mounting an HFS
   * filesystem.	It performs all the tasks necessary to get enough data
   * from the disk to read the root inode.  This includes parsing the
   * mount options, dealing with Macintosh partitions, reading the
   * superblock and the allocation bitmap blocks, calling
   * hfs_btree_init() to get the necessary data about the extents and
   * catalog B-trees and, finally, reading the root inode into memory.
   */
  static int hfs_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct hfs_sb_info *sbi;
  	struct hfs_find_data fd;
  	hfs_cat_rec rec;
  	struct inode *root_inode;
  	int res;
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
366
  	sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
  	if (!sbi)
  		return -ENOMEM;
  	sb->s_fs_info = sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
  	INIT_HLIST_HEAD(&sbi->rsrc_inodes);
  
  	res = -EINVAL;
  	if (!parse_options((char *)data, sbi)) {
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
374
375
  		printk(KERN_ERR "hfs: unable to parse mount options.
  ");
945b09201   Colin Leroy   [PATCH] hfs, hfsp...
376
  		goto bail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
378
379
380
381
382
383
384
385
  	}
  
  	sb->s_op = &hfs_super_operations;
  	sb->s_flags |= MS_NODIRATIME;
  	init_MUTEX(&sbi->bitmap_lock);
  
  	res = hfs_mdb_get(sb);
  	if (res) {
  		if (!silent)
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
386
387
  			printk(KERN_WARNING "hfs: can't find a HFS filesystem on dev %s.
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
  				hfs_mdb_name(sb));
  		res = -EINVAL;
945b09201   Colin Leroy   [PATCH] hfs, hfsp...
390
  		goto bail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
393
394
395
396
397
398
399
400
401
  	}
  
  	/* try to get the root inode */
  	hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
  	res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd);
  	if (!res)
  		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
  	if (res) {
  		hfs_find_exit(&fd);
  		goto bail_no_root;
  	}
d6ddf5544   Eric Sandeen   [PATCH] hfs_fill_...
402
  	res = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
  	root_inode = hfs_iget(sb, &fd.search_key->cat, &rec);
  	hfs_find_exit(&fd);
  	if (!root_inode)
  		goto bail_no_root;
d6ddf5544   Eric Sandeen   [PATCH] hfs_fill_...
407
  	res = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
411
412
413
414
415
416
417
418
419
  	sb->s_root = d_alloc_root(root_inode);
  	if (!sb->s_root)
  		goto bail_iput;
  
  	sb->s_root->d_op = &hfs_dentry_operations;
  
  	/* everything's okay */
  	return 0;
  
  bail_iput:
  	iput(root_inode);
  bail_no_root:
7cf3cc303   Roman Zippel   [PATCH] hfs: clea...
420
421
  	printk(KERN_ERR "hfs: get root inode failed.
  ");
945b09201   Colin Leroy   [PATCH] hfs, hfsp...
422
  bail:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  	hfs_mdb_put(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
  	return res;
  }
454e2398b   David Howells   [PATCH] VFS: Perm...
426
427
428
  static int hfs_get_sb(struct file_system_type *fs_type,
  		      int flags, const char *dev_name, void *data,
  		      struct vfsmount *mnt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  {
454e2398b   David Howells   [PATCH] VFS: Perm...
430
  	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super, mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
434
435
436
437
438
439
  }
  
  static struct file_system_type hfs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "hfs",
  	.get_sb		= hfs_get_sb,
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
440
  static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
  {
  	struct hfs_inode_info *i = p;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
443
  	inode_init_once(&i->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
449
450
451
  }
  
  static int __init init_hfs_fs(void)
  {
  	int err;
  
  	hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
  		sizeof(struct hfs_inode_info), 0, SLAB_HWCACHE_ALIGN,
20c2df83d   Paul Mundt   mm: Remove slab d...
452
  		hfs_init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
461
462
463
  	if (!hfs_inode_cachep)
  		return -ENOMEM;
  	err = register_filesystem(&hfs_fs_type);
  	if (err)
  		kmem_cache_destroy(hfs_inode_cachep);
  	return err;
  }
  
  static void __exit exit_hfs_fs(void)
  {
  	unregister_filesystem(&hfs_fs_type);
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
464
  	kmem_cache_destroy(hfs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
  }
  
  module_init(init_hfs_fs)
  module_exit(exit_hfs_fs)