Blame view

fs/jfs/super.c 21 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   *   Copyright (C) International Business Machines Corp., 2000-2004
   *   Portions Copyright (C) Christoph Hellwig, 2001-2002
   *
   *   This program is free software;  you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License as published by
63f83c9fc   Dave Kleikamp   JFS: White space ...
7
   *   the Free Software Foundation; either version 2 of the License, or
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
   *   (at your option) any later version.
63f83c9fc   Dave Kleikamp   JFS: White space ...
9
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
   *   This program is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   *   the GNU General Public License for more details.
   *
   *   You should have received a copy of the GNU General Public License
63f83c9fc   Dave Kleikamp   JFS: White space ...
16
   *   along with this program;  if not, write to the Free Software
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   */
  
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
  #include <linux/module.h>
  #include <linux/parser.h>
  #include <linux/completion.h>
  #include <linux/vfs.h>
74abb9890   Jan Kara   quota: move funct...
25
  #include <linux/quotaops.h>
8fc2751be   Mark Bellon   [PATCH] disk quot...
26
  #include <linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <linux/moduleparam.h>
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
28
  #include <linux/kthread.h>
9a59f452a   Christoph Hellwig   [PATCH] remove <l...
29
  #include <linux/posix_acl.h>
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
30
  #include <linux/buffer_head.h>
a56942551   Christoph Hellwig   knfsd: exportfs: ...
31
  #include <linux/exportfs.h>
b5c816a4f   Coly Li   jfs: return f_fsi...
32
  #include <linux/crc32.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
33
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <asm/uaccess.h>
8fc2751be   Mark Bellon   [PATCH] disk quot...
35
  #include <linux/seq_file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
  
  #include "jfs_incore.h"
  #include "jfs_filsys.h"
1868f4aa5   Dave Kleikamp   JFS: fix sparse w...
39
  #include "jfs_inode.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
  #include "jfs_metapage.h"
  #include "jfs_superblock.h"
  #include "jfs_dmap.h"
  #include "jfs_imap.h"
  #include "jfs_acl.h"
  #include "jfs_debug.h"
  
  MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
  MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM");
  MODULE_LICENSE("GPL");
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
50
  static struct kmem_cache * jfs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51

ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
52
  static const struct super_operations jfs_super_operations;
396551644   Christoph Hellwig   exportfs: make st...
53
  static const struct export_operations jfs_export_operations;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
  static struct file_system_type jfs_fs_type;
  
  #define MAX_COMMIT_THREADS 64
  static int commit_threads = 0;
  module_param(commit_threads, int, 0);
  MODULE_PARM_DESC(commit_threads, "Number of commit threads");
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
60
61
62
  static struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS];
  struct task_struct *jfsIOthread;
  struct task_struct *jfsSyncThread;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
68
  
  #ifdef CONFIG_JFS_DEBUG
  int jfsloglevel = JFS_LOGLEVEL_WARN;
  module_param(jfsloglevel, int, 0644);
  MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  static void jfs_handle_error(struct super_block *sb)
  {
  	struct jfs_sb_info *sbi = JFS_SBI(sb);
  
  	if (sb->s_flags & MS_RDONLY)
  		return;
  
  	updateSuper(sb, FM_DIRTY);
  
  	if (sbi->flag & JFS_ERR_PANIC)
  		panic("JFS (device %s): panic forced after error
  ",
  			sb->s_id);
  	else if (sbi->flag & JFS_ERR_REMOUNT_RO) {
  		jfs_err("ERROR: (device %s): remounting filesystem "
  			"as read-only
  ",
  			sb->s_id);
  		sb->s_flags |= MS_RDONLY;
63f83c9fc   Dave Kleikamp   JFS: White space ...
88
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
91
92
93
94
95
96
97
98
  
  	/* nothing is done for continue beyond marking the superblock dirty */
  }
  
  void jfs_error(struct super_block *sb, const char * function, ...)
  {
  	static char error_buf[256];
  	va_list args;
  
  	va_start(args, function);
4a6e617a4   Alexey Dobriyan   [PATCH] fs/*: tri...
99
  	vsnprintf(error_buf, sizeof(error_buf), function, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  	va_end(args);
  
  	printk(KERN_ERR "ERROR: (device %s): %s
  ", sb->s_id, error_buf);
  
  	jfs_handle_error(sb);
  }
  
  static struct inode *jfs_alloc_inode(struct super_block *sb)
  {
  	struct jfs_inode_info *jfs_inode;
  
  	jfs_inode = kmem_cache_alloc(jfs_inode_cachep, GFP_NOFS);
  	if (!jfs_inode)
  		return NULL;
  	return &jfs_inode->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
117
118
119
120
121
122
123
  static void jfs_i_callback(struct rcu_head *head)
  {
  	struct inode *inode = container_of(head, struct inode, i_rcu);
  	struct jfs_inode_info *ji = JFS_IP(inode);
  	INIT_LIST_HEAD(&inode->i_dentry);
  	kmem_cache_free(jfs_inode_cachep, ji);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
  static void jfs_destroy_inode(struct inode *inode)
  {
  	struct jfs_inode_info *ji = JFS_IP(inode);
8a9cd6d67   Dave Kleikamp   JFS: Fix race in ...
127
  	BUG_ON(!list_empty(&ji->anon_inode_list));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
  	spin_lock_irq(&ji->ag_lock);
  	if (ji->active_ag != -1) {
  		struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
  		atomic_dec(&bmap->db_active[ji->active_ag]);
  		ji->active_ag = -1;
  	}
  	spin_unlock_irq(&ji->ag_lock);
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
135
  	call_rcu(&inode->i_rcu, jfs_i_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  }
726c33422   David Howells   [PATCH] VFS: Perm...
137
  static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  {
726c33422   David Howells   [PATCH] VFS: Perm...
139
  	struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	s64 maxinodes;
  	struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
  
  	jfs_info("In jfs_statfs");
  	buf->f_type = JFS_SUPER_MAGIC;
  	buf->f_bsize = sbi->bsize;
  	buf->f_blocks = sbi->bmap->db_mapsize;
  	buf->f_bfree = sbi->bmap->db_nfree;
  	buf->f_bavail = sbi->bmap->db_nfree;
  	/*
  	 * If we really return the number of allocated & free inodes, some
  	 * applications will fail because they won't see enough free inodes.
  	 * We'll try to calculate some guess as to how may inodes we can
  	 * really allocate
  	 *
  	 * buf->f_files = atomic_read(&imap->im_numinos);
  	 * buf->f_ffree = atomic_read(&imap->im_numfree);
  	 */
  	maxinodes = min((s64) atomic_read(&imap->im_numinos) +
  			((sbi->bmap->db_nfree >> imap->im_l2nbperiext)
  			 << L2INOSPEREXT), (s64) 0xffffffffLL);
  	buf->f_files = maxinodes;
  	buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) -
  				    atomic_read(&imap->im_numfree));
b5c816a4f   Coly Li   jfs: return f_fsi...
164
165
166
  	buf->f_fsid.val[0] = (u32)crc32_le(0, sbi->uuid, sizeof(sbi->uuid)/2);
  	buf->f_fsid.val[1] = (u32)crc32_le(0, sbi->uuid + sizeof(sbi->uuid)/2,
  					sizeof(sbi->uuid)/2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
171
172
173
174
175
176
177
  
  	buf->f_namelen = JFS_NAME_MAX;
  	return 0;
  }
  
  static void jfs_put_super(struct super_block *sb)
  {
  	struct jfs_sb_info *sbi = JFS_SBI(sb);
  	int rc;
  
  	jfs_info("In jfs_put_super");
6cfd01484   Christoph Hellwig   push BKL down int...
178

e0ccfd959   Christoph Hellwig   quota: move unmou...
179
  	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
  	rc = jfs_umount(sb);
  	if (rc)
  		jfs_err("jfs_umount failed with return code %d", rc);
6d729e44a   Thomas Gleixner   fs: Make unload_n...
183
184
  
  	unload_nls(sbi->nls_tab);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185

7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
186
187
  	truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
  	iput(sbi->direct_inode);
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
188

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
  	kfree(sbi);
  }
  
  enum {
  	Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
8fc2751be   Mark Bellon   [PATCH] disk quot...
194
  	Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
69eb66d7d   Dave Kleikamp   JFS: add uid, gid...
195
  	Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
197
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
201
202
203
204
205
  	{Opt_integrity, "integrity"},
  	{Opt_nointegrity, "nointegrity"},
  	{Opt_iocharset, "iocharset=%s"},
  	{Opt_resize, "resize=%u"},
  	{Opt_resize_nosize, "resize"},
  	{Opt_errors, "errors=%s"},
  	{Opt_ignore, "noquota"},
  	{Opt_ignore, "quota"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
206
207
  	{Opt_usrquota, "usrquota"},
  	{Opt_grpquota, "grpquota"},
69eb66d7d   Dave Kleikamp   JFS: add uid, gid...
208
209
210
  	{Opt_uid, "uid=%u"},
  	{Opt_gid, "gid=%u"},
  	{Opt_umask, "umask=%u"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  	{Opt_err, NULL}
  };
  
  static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
  			 int *flag)
  {
  	void *nls_map = (void *)-1;	/* -1: no change;  NULL: none */
  	char *p;
  	struct jfs_sb_info *sbi = JFS_SBI(sb);
  
  	*newLVSize = 0;
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		substring_t args[MAX_OPT_ARGS];
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_integrity:
  			*flag &= ~JFS_NOINTEGRITY;
  			break;
  		case Opt_nointegrity:
  			*flag |= JFS_NOINTEGRITY;
  			break;
  		case Opt_ignore:
  			/* Silently ignore the quota options */
  			/* Don't do anything ;-) */
  			break;
  		case Opt_iocharset:
  			if (nls_map && nls_map != (void *) -1)
  				unload_nls(nls_map);
  			if (!strcmp(args[0].from, "none"))
  				nls_map = NULL;
  			else {
  				nls_map = load_nls(args[0].from);
  				if (!nls_map) {
  					printk(KERN_ERR
  					       "JFS: charset not found
  ");
  					goto cleanup;
  				}
  			}
  			break;
  		case Opt_resize:
  		{
  			char *resize = args[0].from;
  			*newLVSize = simple_strtoull(resize, &resize, 0);
  			break;
  		}
  		case Opt_resize_nosize:
  		{
  			*newLVSize = sb->s_bdev->bd_inode->i_size >>
  				sb->s_blocksize_bits;
  			if (*newLVSize == 0)
  				printk(KERN_ERR
  				       "JFS: Cannot determine volume size
  ");
  			break;
  		}
  		case Opt_errors:
  		{
  			char *errors = args[0].from;
  			if (!errors || !*errors)
  				goto cleanup;
  			if (!strcmp(errors, "continue")) {
  				*flag &= ~JFS_ERR_REMOUNT_RO;
  				*flag &= ~JFS_ERR_PANIC;
  				*flag |= JFS_ERR_CONTINUE;
  			} else if (!strcmp(errors, "remount-ro")) {
  				*flag &= ~JFS_ERR_CONTINUE;
  				*flag &= ~JFS_ERR_PANIC;
  				*flag |= JFS_ERR_REMOUNT_RO;
  			} else if (!strcmp(errors, "panic")) {
  				*flag &= ~JFS_ERR_CONTINUE;
  				*flag &= ~JFS_ERR_REMOUNT_RO;
  				*flag |= JFS_ERR_PANIC;
  			} else {
  				printk(KERN_ERR
  				       "JFS: %s is an invalid error handler
  ",
  				       errors);
  				goto cleanup;
  			}
  			break;
  		}
8fc2751be   Mark Bellon   [PATCH] disk quot...
301

115ff50ba   Dave Kleikamp   JFS: Quota suppor...
302
  #ifdef CONFIG_QUOTA
8fc2751be   Mark Bellon   [PATCH] disk quot...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
  		case Opt_quota:
  		case Opt_usrquota:
  			*flag |= JFS_USRQUOTA;
  			break;
  		case Opt_grpquota:
  			*flag |= JFS_GRPQUOTA;
  			break;
  #else
  		case Opt_usrquota:
  		case Opt_grpquota:
  		case Opt_quota:
  			printk(KERN_ERR
  			       "JFS: quota operations not supported
  ");
  			break;
  #endif
69eb66d7d   Dave Kleikamp   JFS: add uid, gid...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  		case Opt_uid:
  		{
  			char *uid = args[0].from;
  			sbi->uid = simple_strtoul(uid, &uid, 0);
  			break;
  		}
  		case Opt_gid:
  		{
  			char *gid = args[0].from;
  			sbi->gid = simple_strtoul(gid, &gid, 0);
  			break;
  		}
  		case Opt_umask:
  		{
  			char *umask = args[0].from;
  			sbi->umask = simple_strtoul(umask, &umask, 8);
  			if (sbi->umask & ~0777) {
  				printk(KERN_ERR
  				       "JFS: Invalid value of umask
  ");
  				goto cleanup;
  			}
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
348
349
350
351
352
  		default:
  			printk("jfs: Unrecognized mount option \"%s\" "
  					" or missing value
  ", p);
  			goto cleanup;
  		}
  	}
  
  	if (nls_map != (void *) -1) {
  		/* Discard old (if remount) */
6d729e44a   Thomas Gleixner   fs: Make unload_n...
353
  		unload_nls(sbi->nls_tab);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  		sbi->nls_tab = nls_map;
  	}
  	return 1;
  
  cleanup:
  	if (nls_map && nls_map != (void *) -1)
  		unload_nls(nls_map);
  	return 0;
  }
  
  static int jfs_remount(struct super_block *sb, int *flags, char *data)
  {
  	s64 newLVSize = 0;
  	int rc = 0;
  	int flag = JFS_SBI(sb)->flag;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
369
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
  
  	if (!parse_options(data, sb, &newLVSize, &flag)) {
  		return -EINVAL;
  	}
22b26db6f   Jan Blunck   BKL: Remove BKL f...
374

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
382
  	if (newLVSize) {
  		if (sb->s_flags & MS_RDONLY) {
  			printk(KERN_ERR
  		  "JFS: resize requires volume to be mounted read-write
  ");
  			return -EROFS;
  		}
  		rc = jfs_extendfs(sb, newLVSize, 0);
22b26db6f   Jan Blunck   BKL: Remove BKL f...
383
  		if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
  			return rc;
  	}
  
  	if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
388
389
390
391
392
  		/*
  		 * Invalidate any previously read metadata.  fsck may have
  		 * changed the on-disk data since we mounted r/o
  		 */
  		truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  		JFS_SBI(sb)->flag = flag;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
394
  		ret = jfs_mount_rw(sb, 1);
c79d967de   Christoph Hellwig   quota: move remou...
395
396
397
  
  		/* mark the fs r/w for quota activity */
  		sb->s_flags &= ~MS_RDONLY;
0f0dd62fd   Christoph Hellwig   quota: kill the v...
398
  		dquot_resume(sb, -1);
337eb00a2   Alessio Igor Bogani   Push BKL down int...
399
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
  	}
  	if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) {
0f0dd62fd   Christoph Hellwig   quota: kill the v...
402
403
  		rc = dquot_suspend(sb, -1);
  		if (rc < 0) {
0f0dd62fd   Christoph Hellwig   quota: kill the v...
404
  			return rc;
c79d967de   Christoph Hellwig   quota: move remou...
405
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
410
411
412
  		rc = jfs_umount_rw(sb);
  		JFS_SBI(sb)->flag = flag;
  		return rc;
  	}
  	if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY))
  		if (!(sb->s_flags & MS_RDONLY)) {
  			rc = jfs_umount_rw(sb);
22b26db6f   Jan Blunck   BKL: Remove BKL f...
413
  			if (rc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  				return rc;
22b26db6f   Jan Blunck   BKL: Remove BKL f...
415

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  			JFS_SBI(sb)->flag = flag;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
417
  			ret = jfs_mount_rw(sb, 1);
337eb00a2   Alessio Igor Bogani   Push BKL down int...
418
  			return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
421
422
423
424
425
426
427
428
429
430
  		}
  	JFS_SBI(sb)->flag = flag;
  
  	return 0;
  }
  
  static int jfs_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct jfs_sb_info *sbi;
  	struct inode *inode;
  	int rc;
  	s64 newLVSize = 0;
eab1df71a   David Howells   iget: stop JFS fr...
431
  	int flag, ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
  
  	jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags);
22b26db6f   Jan Blunck   BKL: Remove BKL f...
434
  	if (!new_valid_dev(sb->s_bdev->bd_dev))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  		return -EOVERFLOW;
5b3030e39   Eric Sesterhenn   JFS: kzalloc conv...
436
  	sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL);
22b26db6f   Jan Blunck   BKL: Remove BKL f...
437
  	if (!sbi)
087387f90   Akinobu Mita   [PATCH] JFS: retu...
438
  		return -ENOMEM;
22b26db6f   Jan Blunck   BKL: Remove BKL f...
439

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
  	sb->s_fs_info = sbi;
  	sbi->sb = sb;
69eb66d7d   Dave Kleikamp   JFS: add uid, gid...
442
  	sbi->uid = sbi->gid = sbi->umask = -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
445
  
  	/* initialize the mount flag and determine the default error handler */
  	flag = JFS_ERR_REMOUNT_RO;
684bdc7ff   Jan Blunck   JFS: Free sbi mem...
446
447
  	if (!parse_options((char *) data, sb, &newLVSize, &flag))
  		goto out_kfree;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
455
456
  	sbi->flag = flag;
  
  #ifdef CONFIG_JFS_POSIX_ACL
  	sb->s_flags |= MS_POSIXACL;
  #endif
  
  	if (newLVSize) {
  		printk(KERN_ERR "resize option for remount only
  ");
684bdc7ff   Jan Blunck   JFS: Free sbi mem...
457
  		goto out_kfree;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
465
466
467
468
469
  	}
  
  	/*
  	 * Initialize blocksize to 4K.
  	 */
  	sb_set_blocksize(sb, PSIZE);
  
  	/*
  	 * Set method vectors.
  	 */
  	sb->s_op = &jfs_super_operations;
  	sb->s_export_op = &jfs_export_operations;
123e9caf1   Christoph Hellwig   quota: explicitly...
470
471
  #ifdef CONFIG_QUOTA
  	sb->dq_op = &dquot_operations;
287a80958   Christoph Hellwig   quota: rename def...
472
  	sb->s_qcop = &dquot_quotactl_ops;
123e9caf1   Christoph Hellwig   quota: explicitly...
473
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474

7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
475
476
477
478
  	/*
  	 * Initialize direct-mapping inode/address-space
  	 */
  	inode = new_inode(sb);
eab1df71a   David Howells   iget: stop JFS fr...
479
480
  	if (inode == NULL) {
  		ret = -ENOMEM;
684bdc7ff   Jan Blunck   JFS: Free sbi mem...
481
  		goto out_unload;
eab1df71a   David Howells   iget: stop JFS fr...
482
  	}
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
483
  	inode->i_ino = 0;
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
484
485
  	inode->i_size = sb->s_bdev->bd_inode->i_size;
  	inode->i_mapping->a_ops = &jfs_metapage_aops;
ac17b8b57   Dave Kleikamp   JFS: make special...
486
  	insert_inode_hash(inode);
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
487
488
489
  	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
  
  	sbi->direct_inode = inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
492
493
494
  	rc = jfs_mount(sb);
  	if (rc) {
  		if (!silent) {
  			jfs_err("jfs_mount failed w/return code = %d", rc);
  		}
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
495
  		goto out_mount_failed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  	}
  	if (sb->s_flags & MS_RDONLY)
  		sbi->log = NULL;
  	else {
  		rc = jfs_mount_rw(sb, 0);
  		if (rc) {
  			if (!silent) {
  				jfs_err("jfs_mount_rw failed, return code = %d",
  					rc);
  			}
  			goto out_no_rw;
  		}
  	}
  
  	sb->s_magic = JFS_SUPER_MAGIC;
94b77bd86   Al Viro   switch jfs to ->s...
511
512
  	if (sbi->mntflag & JFS_OS2)
  		sb->s_d_op = &jfs_ci_dentry_operations;
eab1df71a   David Howells   iget: stop JFS fr...
513
514
515
  	inode = jfs_iget(sb, ROOT_I);
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
6536d2891   Dave Kleikamp   JFS: skip bad ipu...
516
  		goto out_no_rw;
eab1df71a   David Howells   iget: stop JFS fr...
517
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
  	sb->s_root = d_alloc_root(inode);
  	if (!sb->s_root)
  		goto out_no_root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
526
527
  	/* logical blocks are represented by 40 bits in pxd_t, etc. */
  	sb->s_maxbytes = ((u64) sb->s_blocksize) << 40;
  #if BITS_PER_LONG == 32
  	/*
  	 * Page cache is indexed by long.
  	 * I would use MAX_LFS_FILESIZE, but it's only half as big
  	 */
28ba0ec64   Alan Cox   jfs: Fix 32bit bu...
528
  	sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, (u64)sb->s_maxbytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
  #endif
  	sb->s_time_gran = 1;
  	return 0;
  
  out_no_root:
6536d2891   Dave Kleikamp   JFS: skip bad ipu...
534
535
  	jfs_err("jfs_read_super: get root dentry failed");
  	iput(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
540
541
  
  out_no_rw:
  	rc = jfs_umount(sb);
  	if (rc) {
  		jfs_err("jfs_umount failed with return code %d", rc);
  	}
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
542
  out_mount_failed:
28fd12982   OGAWA Hirofumi   [PATCH] Fix and a...
543
  	filemap_write_and_wait(sbi->direct_inode->i_mapping);
7fab479be   Dave Kleikamp   [PATCH] JFS: Supp...
544
545
546
547
  	truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
  	make_bad_inode(sbi->direct_inode);
  	iput(sbi->direct_inode);
  	sbi->direct_inode = NULL;
684bdc7ff   Jan Blunck   JFS: Free sbi mem...
548
  out_unload:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
550
  	if (sbi->nls_tab)
  		unload_nls(sbi->nls_tab);
684bdc7ff   Jan Blunck   JFS: Free sbi mem...
551
  out_kfree:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
  	kfree(sbi);
eab1df71a   David Howells   iget: stop JFS fr...
553
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  }
c4be0c1dc   Takashi Sato   filesystem freeze...
555
  static int jfs_freeze(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
560
561
562
563
564
  {
  	struct jfs_sb_info *sbi = JFS_SBI(sb);
  	struct jfs_log *log = sbi->log;
  
  	if (!(sb->s_flags & MS_RDONLY)) {
  		txQuiesce(sb);
  		lmLogShutdown(log);
  		updateSuper(sb, FM_CLEAN);
  	}
c4be0c1dc   Takashi Sato   filesystem freeze...
565
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
  }
c4be0c1dc   Takashi Sato   filesystem freeze...
567
  static int jfs_unfreeze(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
572
573
574
575
576
577
578
579
  {
  	struct jfs_sb_info *sbi = JFS_SBI(sb);
  	struct jfs_log *log = sbi->log;
  	int rc = 0;
  
  	if (!(sb->s_flags & MS_RDONLY)) {
  		updateSuper(sb, FM_MOUNT);
  		if ((rc = lmLogInit(log)))
  			jfs_err("jfs_unlock failed with return code %d", rc);
  		else
  			txResume(sb);
  	}
c4be0c1dc   Takashi Sato   filesystem freeze...
580
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
  }
152a08366   Al Viro   new helper: mount...
582
583
  static struct dentry *jfs_do_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  {
152a08366   Al Viro   new helper: mount...
585
  	return mount_bdev(fs_type, flags, dev_name, data, jfs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
589
590
591
592
  }
  
  static int jfs_sync_fs(struct super_block *sb, int wait)
  {
  	struct jfs_log *log = JFS_SBI(sb)->log;
  
  	/* log == NULL indicates read-only mount */
1c6278295   Dave Kleikamp   [PATCH] JFS: Writ...
593
  	if (log) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  		jfs_flush_journal(log, wait);
cbc3d65eb   Dave Kleikamp   JFS: Improve sync...
595
  		jfs_syncpt(log, 0);
1c6278295   Dave Kleikamp   [PATCH] JFS: Writ...
596
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
  
  	return 0;
  }
8fc2751be   Mark Bellon   [PATCH] disk quot...
600
601
602
  static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
  {
  	struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);
69eb66d7d   Dave Kleikamp   JFS: add uid, gid...
603
604
605
606
607
608
  	if (sbi->uid != -1)
  		seq_printf(seq, ",uid=%d", sbi->uid);
  	if (sbi->gid != -1)
  		seq_printf(seq, ",gid=%d", sbi->gid);
  	if (sbi->umask != -1)
  		seq_printf(seq, ",umask=%03o", sbi->umask);
8fc2751be   Mark Bellon   [PATCH] disk quot...
609
610
  	if (sbi->flag & JFS_NOINTEGRITY)
  		seq_puts(seq, ",nointegrity");
5c5e32cee   Miklos Szeredi   mount options: fi...
611
612
613
614
615
616
  	if (sbi->nls_tab)
  		seq_printf(seq, ",iocharset=%s", sbi->nls_tab->charset);
  	if (sbi->flag & JFS_ERR_CONTINUE)
  		seq_printf(seq, ",errors=continue");
  	if (sbi->flag & JFS_ERR_PANIC)
  		seq_printf(seq, ",errors=panic");
8fc2751be   Mark Bellon   [PATCH] disk quot...
617

115ff50ba   Dave Kleikamp   JFS: Quota suppor...
618
  #ifdef CONFIG_QUOTA
8fc2751be   Mark Bellon   [PATCH] disk quot...
619
620
621
622
623
624
625
626
627
  	if (sbi->flag & JFS_USRQUOTA)
  		seq_puts(seq, ",usrquota");
  
  	if (sbi->flag & JFS_GRPQUOTA)
  		seq_puts(seq, ",grpquota");
  #endif
  
  	return 0;
  }
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
628
629
630
631
  #ifdef CONFIG_QUOTA
  
  /* Read data from quotafile - avoid pagecache and such because we cannot afford
   * acquiring the locks... As quota files are never truncated and quota code
25985edce   Lucas De Marchi   Fix common misspe...
632
   * itself serializes the operations (and no one else should touch the files)
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
   * we don't have to be afraid of races */
  static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data,
  			      size_t len, loff_t off)
  {
  	struct inode *inode = sb_dqopt(sb)->files[type];
  	sector_t blk = off >> sb->s_blocksize_bits;
  	int err = 0;
  	int offset = off & (sb->s_blocksize - 1);
  	int tocopy;
  	size_t toread;
  	struct buffer_head tmp_bh;
  	struct buffer_head *bh;
  	loff_t i_size = i_size_read(inode);
  
  	if (off > i_size)
  		return 0;
  	if (off+len > i_size)
  		len = i_size-off;
  	toread = len;
  	while (toread > 0) {
  		tocopy = sb->s_blocksize - offset < toread ?
  				sb->s_blocksize - offset : toread;
  
  		tmp_bh.b_state = 0;
  		tmp_bh.b_size = 1 << inode->i_blkbits;
  		err = jfs_get_block(inode, blk, &tmp_bh, 0);
  		if (err)
  			return err;
  		if (!buffer_mapped(&tmp_bh))	/* A hole? */
  			memset(data, 0, tocopy);
  		else {
  			bh = sb_bread(sb, tmp_bh.b_blocknr);
  			if (!bh)
  				return -EIO;
  			memcpy(data, bh->b_data+offset, tocopy);
  			brelse(bh);
  		}
  		offset = 0;
  		toread -= tocopy;
  		data += tocopy;
  		blk++;
  	}
  	return len;
  }
  
  /* Write to quotafile */
  static ssize_t jfs_quota_write(struct super_block *sb, int type,
  			       const char *data, size_t len, loff_t off)
  {
  	struct inode *inode = sb_dqopt(sb)->files[type];
  	sector_t blk = off >> sb->s_blocksize_bits;
  	int err = 0;
  	int offset = off & (sb->s_blocksize - 1);
  	int tocopy;
  	size_t towrite = len;
  	struct buffer_head tmp_bh;
  	struct buffer_head *bh;
  
  	mutex_lock(&inode->i_mutex);
  	while (towrite > 0) {
  		tocopy = sb->s_blocksize - offset < towrite ?
  				sb->s_blocksize - offset : towrite;
  
  		tmp_bh.b_state = 0;
8bcb2839b   Dave Kleikamp   JFS: Fix bug in q...
697
  		tmp_bh.b_size = 1 << inode->i_blkbits;
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
  		err = jfs_get_block(inode, blk, &tmp_bh, 1);
  		if (err)
  			goto out;
  		if (offset || tocopy != sb->s_blocksize)
  			bh = sb_bread(sb, tmp_bh.b_blocknr);
  		else
  			bh = sb_getblk(sb, tmp_bh.b_blocknr);
  		if (!bh) {
  			err = -EIO;
  			goto out;
  		}
  		lock_buffer(bh);
  		memcpy(bh->b_data+offset, data, tocopy);
  		flush_dcache_page(bh->b_page);
  		set_buffer_uptodate(bh);
  		mark_buffer_dirty(bh);
  		unlock_buffer(bh);
  		brelse(bh);
  		offset = 0;
  		towrite -= tocopy;
  		data += tocopy;
  		blk++;
  	}
  out:
9c83633ad   Dan Carpenter   missing unlock in...
722
723
  	if (len == towrite) {
  		mutex_unlock(&inode->i_mutex);
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
724
  		return err;
9c83633ad   Dan Carpenter   missing unlock in...
725
  	}
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
726
727
728
729
730
731
732
733
734
735
  	if (inode->i_size < off+len-towrite)
  		i_size_write(inode, off+len-towrite);
  	inode->i_version++;
  	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  	mark_inode_dirty(inode);
  	mutex_unlock(&inode->i_mutex);
  	return len - towrite;
  }
  
  #endif
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
736
  static const struct super_operations jfs_super_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
738
  	.alloc_inode	= jfs_alloc_inode,
  	.destroy_inode	= jfs_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
740
  	.dirty_inode	= jfs_dirty_inode,
  	.write_inode	= jfs_write_inode,
62aff86fd   Al Viro   switch jfs to ->e...
741
  	.evict_inode	= jfs_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
  	.put_super	= jfs_put_super,
  	.sync_fs	= jfs_sync_fs,
c4be0c1dc   Takashi Sato   filesystem freeze...
744
745
  	.freeze_fs	= jfs_freeze,
  	.unfreeze_fs	= jfs_unfreeze,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
  	.statfs		= jfs_statfs,
  	.remount_fs	= jfs_remount,
115ff50ba   Dave Kleikamp   JFS: Quota suppor...
748
749
750
751
752
  	.show_options	= jfs_show_options,
  #ifdef CONFIG_QUOTA
  	.quota_read	= jfs_quota_read,
  	.quota_write	= jfs_quota_write,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
  };
396551644   Christoph Hellwig   exportfs: make st...
754
  static const struct export_operations jfs_export_operations = {
d425de704   Christoph Hellwig   jfs: new export ops
755
756
  	.fh_to_dentry	= jfs_fh_to_dentry,
  	.fh_to_parent	= jfs_fh_to_parent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
760
761
762
  	.get_parent	= jfs_get_parent,
  };
  
  static struct file_system_type jfs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "jfs",
152a08366   Al Viro   new helper: mount...
763
  	.mount		= jfs_do_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
766
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
767
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
769
  {
  	struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
770
771
772
773
774
775
776
  	memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
  	INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
  	init_rwsem(&jfs_ip->rdwrlock);
  	mutex_init(&jfs_ip->commit_mutex);
  	init_rwsem(&jfs_ip->xattr_sem);
  	spin_lock_init(&jfs_ip->ag_lock);
  	jfs_ip->active_ag = -1;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
777
  	inode_init_once(&jfs_ip->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
781
782
783
784
785
  }
  
  static int __init init_jfs_fs(void)
  {
  	int i;
  	int rc;
  
  	jfs_inode_cachep =
63f83c9fc   Dave Kleikamp   JFS: White space ...
786
  	    kmem_cache_create("jfs_ip", sizeof(struct jfs_inode_info), 0,
fffb60f93   Paul Jackson   [PATCH] cpuset me...
787
  			    SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD,
20c2df83d   Paul Mundt   mm: Remove slab d...
788
  			    init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  	if (jfs_inode_cachep == NULL)
  		return -ENOMEM;
  
  	/*
  	 * Metapage initialization
  	 */
  	rc = metapage_init();
  	if (rc) {
  		jfs_err("metapage_init failed w/rc = %d", rc);
  		goto free_slab;
  	}
  
  	/*
  	 * Transaction Manager initialization
  	 */
  	rc = txInit();
  	if (rc) {
  		jfs_err("txInit failed w/rc = %d", rc);
  		goto free_metapage;
  	}
  
  	/*
  	 * I/O completion thread (endio)
  	 */
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
813
814
815
816
  	jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO");
  	if (IS_ERR(jfsIOthread)) {
  		rc = PTR_ERR(jfsIOthread);
  		jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  		goto end_txmngr;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
821
822
823
824
825
  
  	if (commit_threads < 1)
  		commit_threads = num_online_cpus();
  	if (commit_threads > MAX_COMMIT_THREADS)
  		commit_threads = MAX_COMMIT_THREADS;
  
  	for (i = 0; i < commit_threads; i++) {
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
826
827
828
829
  		jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL, "jfsCommit");
  		if (IS_ERR(jfsCommitThread[i])) {
  			rc = PTR_ERR(jfsCommitThread[i]);
  			jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
  			commit_threads = i;
  			goto kill_committask;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
833
  	}
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
834
835
836
837
  	jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync");
  	if (IS_ERR(jfsSyncThread)) {
  		rc = PTR_ERR(jfsSyncThread);
  		jfs_err("init_jfs_fs: fork failed w/rc = %d", rc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
  		goto kill_committask;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
842
843
844
845
846
847
  
  #ifdef PROC_FS_JFS
  	jfs_proc_init();
  #endif
  
  	return register_filesystem(&jfs_fs_type);
  
  kill_committask:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
  	for (i = 0; i < commit_threads; i++)
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
849
850
  		kthread_stop(jfsCommitThread[i]);
  	kthread_stop(jfsIOthread);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
854
855
856
857
858
859
860
861
862
863
864
  end_txmngr:
  	txExit();
  free_metapage:
  	metapage_exit();
  free_slab:
  	kmem_cache_destroy(jfs_inode_cachep);
  	return rc;
  }
  
  static void __exit exit_jfs_fs(void)
  {
  	int i;
  
  	jfs_info("exit_jfs_fs called");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
866
  	txExit();
  	metapage_exit();
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
867
868
  
  	kthread_stop(jfsIOthread);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
  	for (i = 0; i < commit_threads; i++)
91dbb4deb   Christoph Hellwig   JFS: Use the kthr...
870
871
  		kthread_stop(jfsCommitThread[i]);
  	kthread_stop(jfsSyncThread);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
874
875
876
877
878
879
880
  #ifdef PROC_FS_JFS
  	jfs_proc_clean();
  #endif
  	unregister_filesystem(&jfs_fs_type);
  	kmem_cache_destroy(jfs_inode_cachep);
  }
  
  module_init(init_jfs_fs)
  module_exit(exit_jfs_fs)