Blame view

fs/ext3/super.c 83.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   *  linux/fs/ext3/super.c
   *
   * Copyright (C) 1992, 1993, 1994, 1995
   * Remy Card (card@masi.ibp.fr)
   * Laboratoire MASI - Institut Blaise Pascal
   * Universite Pierre et Marie Curie (Paris VI)
   *
   *  from
   *
   *  linux/fs/minix/inode.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
   *  Big-endian to little-endian byte-swapping/bitmaps by
   *        David S. Miller (davem@caip.rutgers.edu), 1995
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
27
28
  #include <linux/module.h>
  #include <linux/string.h>
  #include <linux/fs.h>
  #include <linux/time.h>
  #include <linux/jbd.h>
  #include <linux/ext3_fs.h>
  #include <linux/ext3_jbd.h>
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/parser.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/buffer_head.h>
a56942551   Christoph Hellwig   knfsd: exportfs: ...
30
  #include <linux/exportfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
34
35
  #include <linux/vfs.h>
  #include <linux/random.h>
  #include <linux/mount.h>
  #include <linux/namei.h>
  #include <linux/quotaops.h>
8fc2751be   Mark Bellon   [PATCH] disk quot...
36
  #include <linux/seq_file.h>
3fc74269c   vignesh babu   is_power_of_2: ex...
37
  #include <linux/log2.h>
d71bc6db5   Dan Magenheimer   ext3: add cleanca...
38
  #include <linux/cleancache.h>
381be2545   Ben Dooks   [PATCH] ext3: spa...
39

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <asm/uaccess.h>
381be2545   Ben Dooks   [PATCH] ext3: spa...
41

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  #include "xattr.h"
  #include "acl.h"
381be2545   Ben Dooks   [PATCH] ext3: spa...
44
  #include "namei.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

785c4bcc0   Lukas Czerner   ext3: Add fixed t...
46
47
  #define CREATE_TRACE_POINTS
  #include <trace/events/ext3.h>
bbae8bcc4   Linus Torvalds   ext3: make defaul...
48
49
50
51
52
  #ifdef CONFIG_EXT3_DEFAULTS_TO_ORDERED
    #define EXT3_MOUNT_DEFAULT_DATA_MODE EXT3_MOUNT_ORDERED_DATA
  #else
    #define EXT3_MOUNT_DEFAULT_DATA_MODE EXT3_MOUNT_WRITEBACK_DATA
  #endif
71b962574   Johann Lombardi   [PATCH] ext3: ext...
53
54
  static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
  			     unsigned long journal_devnum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
56
  			       unsigned int);
c4be0c1dc   Takashi Sato   filesystem freeze...
57
58
  static int ext3_commit_super(struct super_block *sb,
  			       struct ext3_super_block *es,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
65
66
67
  			       int sync);
  static void ext3_mark_recovery_complete(struct super_block * sb,
  					struct ext3_super_block * es);
  static void ext3_clear_journal_err(struct super_block * sb,
  				   struct ext3_super_block * es);
  static int ext3_sync_fs(struct super_block *sb, int wait);
  static const char *ext3_decode_error(struct super_block * sb, int errno,
  				     char nbuf[16]);
  static int ext3_remount (struct super_block * sb, int * flags, char * data);
726c33422   David Howells   [PATCH] VFS: Perm...
68
  static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
c4be0c1dc   Takashi Sato   filesystem freeze...
69
  static int ext3_unfreeze(struct super_block *sb);
c4be0c1dc   Takashi Sato   filesystem freeze...
70
  static int ext3_freeze(struct super_block *sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71

ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
72
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
77
   * Wrappers for journal_start/end.
   *
   * The only special thing we need to do here is to make sure that all
   * journal_end calls result in the superblock being marked dirty, so
   * that sync() will call the filesystem's write_super callback if
ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
78
   * appropriate.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
86
87
88
89
90
91
   */
  handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
  {
  	journal_t *journal;
  
  	if (sb->s_flags & MS_RDONLY)
  		return ERR_PTR(-EROFS);
  
  	/* Special case here: if the journal has aborted behind our
  	 * backs (eg. EIO in the commit thread), then we still need to
  	 * take the FS itself readonly cleanly. */
  	journal = EXT3_SB(sb)->s_journal;
  	if (is_journal_aborted(journal)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
92
  		ext3_abort(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
98
  			   "Detected aborted journal");
  		return ERR_PTR(-EROFS);
  	}
  
  	return journal_start(journal, nblocks);
  }
ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
99
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
   * The only special thing we need to do here is to make sure that all
   * journal_stop calls result in the superblock being marked dirty, so
   * that sync() will call the filesystem's write_super callback if
ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
103
   * appropriate.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
   */
  int __ext3_journal_stop(const char *where, handle_t *handle)
  {
  	struct super_block *sb;
  	int err;
  	int rc;
  
  	sb = handle->h_transaction->t_journal->j_private;
  	err = handle->h_err;
  	rc = journal_stop(handle);
  
  	if (!err)
  		err = rc;
  	if (err)
  		__ext3_std_error(sb, where, err);
  	return err;
  }
  
  void ext3_journal_abort_handle(const char *caller, const char *err_fn,
  		struct buffer_head *bh, handle_t *handle, int err)
  {
  	char nbuf[16];
  	const char *errstr = ext3_decode_error(NULL, err, nbuf);
  
  	if (bh)
  		BUFFER_TRACE(bh, "abort");
  
  	if (!handle->h_err)
  		handle->h_err = err;
  
  	if (is_handle_aborted(handle))
  		return;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
136
137
138
  	printk(KERN_ERR "EXT3-fs: %s: aborting transaction: %s in %s
  ",
  		caller, errstr, err_fn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
  
  	journal_abort_handle(handle);
  }
4cf46b67e   Alexey Fisher   ext3: Unify log m...
142
143
144
  void ext3_msg(struct super_block *sb, const char *prefix,
  		const char *fmt, ...)
  {
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
145
  	struct va_format vaf;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
146
147
148
  	va_list args;
  
  	va_start(args, fmt);
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
149
150
151
152
153
154
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk("%sEXT3-fs (%s): %pV
  ", prefix, sb->s_id, &vaf);
4cf46b67e   Alexey Fisher   ext3: Unify log m...
155
156
  	va_end(args);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
159
160
161
162
163
164
165
166
167
  /* Deal with the reporting of failure conditions on a filesystem such as
   * inconsistencies detected or read IO failures.
   *
   * On ext2, we can store the error state of the filesystem in the
   * superblock.  That is not possible on ext3, because we may have other
   * write ordering constraints on the superblock which prevent us from
   * writing it out straight away; and given that the journal is about to
   * be aborted, we can't rely on the current, or future, transactions to
   * write out the superblock safely.
   *
   * We'll just use the journal_abort() error code to record an error in
d6b198bc8   Thadeu Lima de Souza Cascardo   fix ext3/ext4 com...
168
   * the journal instead.  On recovery, the journal will complain about
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
173
174
175
176
177
178
179
180
   * that error until we've noted it down and cleared it.
   */
  
  static void ext3_handle_error(struct super_block *sb)
  {
  	struct ext3_super_block *es = EXT3_SB(sb)->s_es;
  
  	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
  	es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
  
  	if (sb->s_flags & MS_RDONLY)
  		return;
7543fc7b3   Vasily Averin   [PATCH] ext3: wro...
181
  	if (!test_opt (sb, ERRORS_CONT)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  		journal_t *journal = EXT3_SB(sb)->s_journal;
e3c964359   Dmitry Monakhov   ext3: mount flags...
183
  		set_opt(EXT3_SB(sb)->s_mount_opt, ABORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
  		if (journal)
  			journal_abort(journal, -EIO);
  	}
7543fc7b3   Vasily Averin   [PATCH] ext3: wro...
187
  	if (test_opt (sb, ERRORS_RO)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
188
189
  		ext3_msg(sb, KERN_CRIT,
  			"error: remounting filesystem read-only");
7543fc7b3   Vasily Averin   [PATCH] ext3: wro...
190
191
192
  		sb->s_flags |= MS_RDONLY;
  	}
  	ext3_commit_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  	if (test_opt(sb, ERRORS_PANIC))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
194
195
  		panic("EXT3-fs (%s): panic forced after error
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  			sb->s_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  }
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
198
199
  void ext3_error(struct super_block *sb, const char *function,
  		const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  {
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
201
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
  	va_list args;
  
  	va_start(args, fmt);
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
205
206
207
208
209
210
211
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk(KERN_CRIT "EXT3-fs error (device %s): %s: %pV
  ",
  	       sb->s_id, function, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
  	va_end(args);
  
  	ext3_handle_error(sb);
  }
  
  static const char *ext3_decode_error(struct super_block * sb, int errno,
  				     char nbuf[16])
  {
  	char *errstr = NULL;
  
  	switch (errno) {
  	case -EIO:
  		errstr = "IO failure";
  		break;
  	case -ENOMEM:
  		errstr = "Out of memory";
  		break;
  	case -EROFS:
  		if (!sb || EXT3_SB(sb)->s_journal->j_flags & JFS_ABORT)
  			errstr = "Journal has aborted";
  		else
  			errstr = "Readonly filesystem";
  		break;
  	default:
  		/* If the caller passed in an extra buffer for unknown
  		 * errors, textualise them now.  Else we just return
  		 * NULL. */
  		if (nbuf) {
  			/* Check for truncated error codes... */
  			if (snprintf(nbuf, 16, "error %d", -errno) >= 0)
  				errstr = nbuf;
  		}
  		break;
  	}
  
  	return errstr;
  }
  
  /* __ext3_std_error decodes expected errors from journaling functions
   * automatically and invokes the appropriate error response.  */
  
  void __ext3_std_error (struct super_block * sb, const char * function,
  		       int errno)
  {
  	char nbuf[16];
301216244   Stephen Tweedie   [PATCH] Avoid con...
257
  	const char *errstr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258

301216244   Stephen Tweedie   [PATCH] Avoid con...
259
260
261
262
263
264
265
266
  	/* Special case: if the error is EROFS, and we're not already
  	 * inside a transaction, then there's really no point in logging
  	 * an error. */
  	if (errno == -EROFS && journal_current_handle() == NULL &&
  	    (sb->s_flags & MS_RDONLY))
  		return;
  
  	errstr = ext3_decode_error(sb, errno, nbuf);
4cf46b67e   Alexey Fisher   ext3: Unify log m...
267
  	ext3_msg(sb, KERN_CRIT, "error in %s: %s", function, errstr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
272
273
274
275
276
277
278
279
280
  
  	ext3_handle_error(sb);
  }
  
  /*
   * ext3_abort is a much stronger failure handler than ext3_error.  The
   * abort function may be used to deal with unrecoverable failures such
   * as journal IO errors or ENOMEM at a critical moment in log management.
   *
   * We unconditionally force the filesystem into an ABORT|READONLY state,
   * unless the error response on the fs has been set to panic in which
   * case we take the easy way out and panic immediately.
   */
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
281
282
  void ext3_abort(struct super_block *sb, const char *function,
  		 const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
  {
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
284
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  	va_list args;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  	va_start(args, fmt);
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
287
288
289
290
291
292
293
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk(KERN_CRIT "EXT3-fs (%s): error: %s: %pV
  ",
  	       sb->s_id, function, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
  	va_end(args);
  
  	if (test_opt(sb, ERRORS_PANIC))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
297
298
  		panic("EXT3-fs: panic from previous error
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
  
  	if (sb->s_flags & MS_RDONLY)
  		return;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
302
303
  	ext3_msg(sb, KERN_CRIT,
  		"error: remounting filesystem read-only");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
  	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
  	sb->s_flags |= MS_RDONLY;
e3c964359   Dmitry Monakhov   ext3: mount flags...
306
  	set_opt(EXT3_SB(sb)->s_mount_opt, ABORT);
44d6f7875   Hidehiro Kawai   ext3: fix a bug a...
307
308
  	if (EXT3_SB(sb)->s_journal)
  		journal_abort(EXT3_SB(sb)->s_journal, -EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  }
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
310
311
  void ext3_warning(struct super_block *sb, const char *function,
  		  const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  {
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
313
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
316
  	va_list args;
  
  	va_start(args, fmt);
99fbb1e2a   Joe Perches   fs/ext3/super.c: ...
317
318
319
320
321
322
323
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk(KERN_WARNING "EXT3-fs (%s): warning: %s: %pV
  ",
  	       sb->s_id, function, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
327
328
329
330
331
332
  	va_end(args);
  }
  
  void ext3_update_dynamic_rev(struct super_block *sb)
  {
  	struct ext3_super_block *es = EXT3_SB(sb)->s_es;
  
  	if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV)
  		return;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
333
334
335
336
  	ext3_msg(sb, KERN_WARNING,
  		"warning: updating to rev %d because of "
  		"new feature flag, running e2fsck is recommended",
  		EXT3_DYNAMIC_REV);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  
  	es->s_first_ino = cpu_to_le32(EXT3_GOOD_OLD_FIRST_INO);
  	es->s_inode_size = cpu_to_le16(EXT3_GOOD_OLD_INODE_SIZE);
  	es->s_rev_level = cpu_to_le32(EXT3_DYNAMIC_REV);
  	/* leave es->s_feature_*compat flags alone */
  	/* es->s_uuid will be set by e2fsck if empty */
  
  	/*
  	 * The rest of the superblock fields should be zero, and if not it
  	 * means they are likely already in use, so leave them alone.  We
  	 * can leave it up to e2fsck to clean up any inconsistencies there.
  	 */
  }
  
  /*
   * Open the external journal device
   */
4cf46b67e   Alexey Fisher   ext3: Unify log m...
354
  static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
  {
  	struct block_device *bdev;
  	char b[BDEVNAME_SIZE];
d4d776299   Tejun Heo   block: clean up b...
358
  	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
362
363
  	if (IS_ERR(bdev))
  		goto fail;
  	return bdev;
  
  fail:
4cf46b67e   Alexey Fisher   ext3: Unify log m...
364
365
  	ext3_msg(sb, "error: failed to open journal device %s: %ld",
  		__bdevname(dev, b), PTR_ERR(bdev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
368
369
370
371
372
373
  	return NULL;
  }
  
  /*
   * Release the journal device
   */
  static int ext3_blkdev_put(struct block_device *bdev)
  {
e525fd89d   Tejun Heo   block: make blkde...
374
  	return blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
  }
  
  static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
  {
  	struct block_device *bdev;
  	int ret = -ENODEV;
  
  	bdev = sbi->journal_bdev;
  	if (bdev) {
  		ret = ext3_blkdev_put(bdev);
  		sbi->journal_bdev = NULL;
  	}
  	return ret;
  }
  
  static inline struct inode *orphan_list_entry(struct list_head *l)
  {
  	return &list_entry(l, struct ext3_inode_info, i_orphan)->vfs_inode;
  }
  
  static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
  {
  	struct list_head *l;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
398
  	ext3_msg(sb, KERN_ERR, "error: sb orphan head is %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  	       le32_to_cpu(sbi->s_es->s_last_orphan));
4cf46b67e   Alexey Fisher   ext3: Unify log m...
400
  	ext3_msg(sb, KERN_ERR, "sb_info orphan list:");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
  	list_for_each(l, &sbi->s_orphan) {
  		struct inode *inode = orphan_list_entry(l);
4cf46b67e   Alexey Fisher   ext3: Unify log m...
403
  		ext3_msg(sb, KERN_ERR, "  "
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
404
405
  		       "inode %s:%lu at %p: mode %o, nlink %d, next %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  		       inode->i_sb->s_id, inode->i_ino, inode,
ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
407
  		       inode->i_mode, inode->i_nlink,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
411
412
413
414
415
  		       NEXT_ORPHAN(inode));
  	}
  }
  
  static void ext3_put_super (struct super_block * sb)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	struct ext3_super_block *es = sbi->s_es;
44d6f7875   Hidehiro Kawai   ext3: fix a bug a...
416
  	int i, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417

e0ccfd959   Christoph Hellwig   quota: move unmou...
418
  	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  	ext3_xattr_put_super(sb);
44d6f7875   Hidehiro Kawai   ext3: fix a bug a...
420
421
422
  	err = journal_destroy(sbi->s_journal);
  	sbi->s_journal = NULL;
  	if (err < 0)
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
423
  		ext3_abort(sb, __func__, "Couldn't clean up the journal");
44d6f7875   Hidehiro Kawai   ext3: fix a bug a...
424

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
  	if (!(sb->s_flags & MS_RDONLY)) {
  		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
  		es->s_state = cpu_to_le16(sbi->s_mount_state);
  		BUFFER_TRACE(sbi->s_sbh, "marking dirty");
  		mark_buffer_dirty(sbi->s_sbh);
  		ext3_commit_super(sb, es, 1);
  	}
  
  	for (i = 0; i < sbi->s_gdb_count; i++)
  		brelse(sbi->s_group_desc[i]);
  	kfree(sbi->s_group_desc);
  	percpu_counter_destroy(&sbi->s_freeblocks_counter);
  	percpu_counter_destroy(&sbi->s_freeinodes_counter);
  	percpu_counter_destroy(&sbi->s_dirs_counter);
  	brelse(sbi->s_sbh);
  #ifdef CONFIG_QUOTA
  	for (i = 0; i < MAXQUOTAS; i++)
  		kfree(sbi->s_qf_names[i]);
  #endif
  
  	/* Debugging code just in case the in-memory inode orphan list
  	 * isn't empty.  The on-disk one can be non-empty if we've
  	 * detected an error and taken the fs readonly, but the
  	 * in-memory list had better be clean by this point. */
  	if (!list_empty(&sbi->s_orphan))
  		dump_orphan_list(sb, sbi);
  	J_ASSERT(list_empty(&sbi->s_orphan));
f98393a64   Peter Zijlstra   mm: remove destro...
452
  	invalidate_bdev(sb->s_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
  	if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
  		/*
  		 * Invalidate the journal device's buffers.  We don't want them
  		 * floating about in memory - the physical journal device may
  		 * hotswapped, and it breaks the `ro-after' testing code.
  		 */
  		sync_blockdev(sbi->journal_bdev);
f98393a64   Peter Zijlstra   mm: remove destro...
460
  		invalidate_bdev(sbi->journal_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
  		ext3_blkdev_remove(sbi);
  	}
  	sb->s_fs_info = NULL;
5df096d67   Pekka Enberg   ext3: allocate ->...
464
  	kfree(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  	kfree(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
467
  static struct kmem_cache *ext3_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
473
474
  
  /*
   * Called inside transaction, so use GFP_NOFS
   */
  static struct inode *ext3_alloc_inode(struct super_block *sb)
  {
  	struct ext3_inode_info *ei;
e6b4f8da3   Christoph Lameter   [PATCH] slab: rem...
475
  	ei = kmem_cache_alloc(ext3_inode_cachep, GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
  	if (!ei)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
  	ei->i_block_alloc_info = NULL;
  	ei->vfs_inode.i_version = 1;
fe8bc91c4   Jan Kara   ext3: Wait for pr...
480
481
  	atomic_set(&ei->i_datasync_tid, 0);
  	atomic_set(&ei->i_sync_tid, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  	return &ei->vfs_inode;
  }
785c4bcc0   Lukas Czerner   ext3: Add fixed t...
484
485
486
487
488
489
490
  static int ext3_drop_inode(struct inode *inode)
  {
  	int drop = generic_drop_inode(inode);
  
  	trace_ext3_drop_inode(inode, drop);
  	return drop;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
491
492
493
  static void ext3_i_callback(struct rcu_head *head)
  {
  	struct inode *inode = container_of(head, struct inode, i_rcu);
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
494
495
  	kmem_cache_free(ext3_inode_cachep, EXT3_I(inode));
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
  static void ext3_destroy_inode(struct inode *inode)
  {
9f7dd93de   Vasily Averin   ext3/ext4: orphan...
498
499
500
501
502
503
504
505
506
  	if (!list_empty(&(EXT3_I(inode)->i_orphan))) {
  		printk("EXT3 Inode %p: orphan list check failed!
  ",
  			EXT3_I(inode));
  		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
  				EXT3_I(inode), sizeof(struct ext3_inode_info),
  				false);
  		dump_stack();
  	}
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
507
  	call_rcu(&inode->i_rcu, ext3_i_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
509
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
  {
  	struct ext3_inode_info *ei = (struct ext3_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
512
  	INIT_LIST_HEAD(&ei->i_orphan);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  #ifdef CONFIG_EXT3_FS_XATTR
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
514
  	init_rwsem(&ei->xattr_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  #endif
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
516
517
  	mutex_init(&ei->truncate_mutex);
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  }
ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
519

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
523
  static int init_inodecache(void)
  {
  	ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
  					     sizeof(struct ext3_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
524
525
  					     0, (SLAB_RECLAIM_ACCOUNT|
  						SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
526
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
531
532
533
  	if (ext3_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
534
  	kmem_cache_destroy(ext3_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  }
6cd37cda7   Peter Osterlund   [PATCH] Fix ext3 ...
536
  static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
8fc2751be   Mark Bellon   [PATCH] disk quot...
537
  {
6cd37cda7   Peter Osterlund   [PATCH] Fix ext3 ...
538
  #if defined(CONFIG_QUOTA)
275abf5b0   OGAWA Hirofumi   [PATCH] ext3: ext...
539
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
8fc2751be   Mark Bellon   [PATCH] disk quot...
540

1aeec4343   Jan Kara   ext3: Support for...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
  	if (sbi->s_jquota_fmt) {
  		char *fmtname = "";
  
  		switch (sbi->s_jquota_fmt) {
  		case QFMT_VFS_OLD:
  			fmtname = "vfsold";
  			break;
  		case QFMT_VFS_V0:
  			fmtname = "vfsv0";
  			break;
  		case QFMT_VFS_V1:
  			fmtname = "vfsv1";
  			break;
  		}
  		seq_printf(seq, ",jqfmt=%s", fmtname);
  	}
8fc2751be   Mark Bellon   [PATCH] disk quot...
557
558
559
560
561
562
  
  	if (sbi->s_qf_names[USRQUOTA])
  		seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
  
  	if (sbi->s_qf_names[GRPQUOTA])
  		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
e3c964359   Dmitry Monakhov   ext3: mount flags...
563
  	if (test_opt(sb, USRQUOTA))
8fc2751be   Mark Bellon   [PATCH] disk quot...
564
  		seq_puts(seq, ",usrquota");
e3c964359   Dmitry Monakhov   ext3: mount flags...
565
  	if (test_opt(sb, GRPQUOTA))
8fc2751be   Mark Bellon   [PATCH] disk quot...
566
567
  		seq_puts(seq, ",grpquota");
  #endif
6cd37cda7   Peter Osterlund   [PATCH] Fix ext3 ...
568
  }
3c4cec652   Jan Kara   ext3: Improve err...
569
570
571
572
573
574
575
576
577
578
579
580
  static char *data_mode_string(unsigned long mode)
  {
  	switch (mode) {
  	case EXT3_MOUNT_JOURNAL_DATA:
  		return "journal";
  	case EXT3_MOUNT_ORDERED_DATA:
  		return "ordered";
  	case EXT3_MOUNT_WRITEBACK_DATA:
  		return "writeback";
  	}
  	return "unknown";
  }
571beed8d   Miklos Szeredi   ext3: show all mo...
581
582
583
584
585
  /*
   * Show an option if
   *  - it's set to a non-default value OR
   *  - if the per-sb default is different from the global default
   */
34c80b1d9   Al Viro   vfs: switch ->sho...
586
  static int ext3_show_options(struct seq_file *seq, struct dentry *root)
6cd37cda7   Peter Osterlund   [PATCH] Fix ext3 ...
587
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
588
  	struct super_block *sb = root->d_sb;
571beed8d   Miklos Szeredi   ext3: show all mo...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	struct ext3_super_block *es = sbi->s_es;
  	unsigned long def_mount_opts;
  
  	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
  
  	if (sbi->s_sb_block != 1)
  		seq_printf(seq, ",sb=%lu", sbi->s_sb_block);
  	if (test_opt(sb, MINIX_DF))
  		seq_puts(seq, ",minixdf");
  	if (test_opt(sb, GRPID))
  		seq_puts(seq, ",grpid");
  	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT3_DEFM_BSDGROUPS))
  		seq_puts(seq, ",nogrpid");
  	if (sbi->s_resuid != EXT3_DEF_RESUID ||
  	    le16_to_cpu(es->s_def_resuid) != EXT3_DEF_RESUID) {
  		seq_printf(seq, ",resuid=%u", sbi->s_resuid);
  	}
  	if (sbi->s_resgid != EXT3_DEF_RESGID ||
  	    le16_to_cpu(es->s_def_resgid) != EXT3_DEF_RESGID) {
  		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
  	}
1eca93f9c   Aneesh Kumar K.V   ext3: change the ...
611
  	if (test_opt(sb, ERRORS_RO)) {
571beed8d   Miklos Szeredi   ext3: show all mo...
612
613
614
  		int def_errors = le16_to_cpu(es->s_errors);
  
  		if (def_errors == EXT3_ERRORS_PANIC ||
1eca93f9c   Aneesh Kumar K.V   ext3: change the ...
615
616
  		    def_errors == EXT3_ERRORS_CONTINUE) {
  			seq_puts(seq, ",errors=remount-ro");
571beed8d   Miklos Szeredi   ext3: show all mo...
617
618
  		}
  	}
1eca93f9c   Aneesh Kumar K.V   ext3: change the ...
619
620
  	if (test_opt(sb, ERRORS_CONT))
  		seq_puts(seq, ",errors=continue");
571beed8d   Miklos Szeredi   ext3: show all mo...
621
622
623
624
625
626
  	if (test_opt(sb, ERRORS_PANIC))
  		seq_puts(seq, ",errors=panic");
  	if (test_opt(sb, NO_UID32))
  		seq_puts(seq, ",nouid32");
  	if (test_opt(sb, DEBUG))
  		seq_puts(seq, ",debug");
571beed8d   Miklos Szeredi   ext3: show all mo...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  #ifdef CONFIG_EXT3_FS_XATTR
  	if (test_opt(sb, XATTR_USER))
  		seq_puts(seq, ",user_xattr");
  	if (!test_opt(sb, XATTR_USER) &&
  	    (def_mount_opts & EXT3_DEFM_XATTR_USER)) {
  		seq_puts(seq, ",nouser_xattr");
  	}
  #endif
  #ifdef CONFIG_EXT3_FS_POSIX_ACL
  	if (test_opt(sb, POSIX_ACL))
  		seq_puts(seq, ",acl");
  	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT3_DEFM_ACL))
  		seq_puts(seq, ",noacl");
  #endif
  	if (!test_opt(sb, RESERVATION))
  		seq_puts(seq, ",noreservation");
  	if (sbi->s_commit_interval) {
  		seq_printf(seq, ",commit=%u",
  			   (unsigned) (sbi->s_commit_interval / HZ));
  	}
0636c73ee   Eric Sandeen   ext3: make barrie...
647
648
649
650
651
652
  
  	/*
  	 * Always display barrier state so it's clear what the status is.
  	 */
  	seq_puts(seq, ",barrier=");
  	seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0");
e3c964359   Dmitry Monakhov   ext3: mount flags...
653
  	seq_printf(seq, ",data=%s", data_mode_string(test_opt(sb, DATA_FLAGS)));
0e4fb5e28   Hidehiro Kawai   ext3: add an opti...
654
655
  	if (test_opt(sb, DATA_ERR_ABORT))
  		seq_puts(seq, ",data_err=abort");
dee1d3b62   Eric Sandeen   ext3: make "norec...
656
657
  	if (test_opt(sb, NOLOAD))
  		seq_puts(seq, ",norecovery");
6cd37cda7   Peter Osterlund   [PATCH] Fix ext3 ...
658
  	ext3_show_quota_options(seq, sb);
8fc2751be   Mark Bellon   [PATCH] disk quot...
659
660
661
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662

fdb36673a   NeilBrown   [PATCH] knfsd: Ma...
663

74af0baad   Christoph Hellwig   ext3: new export ops
664
665
  static struct inode *ext3_nfs_get_inode(struct super_block *sb,
  		u64 ino, u32 generation)
fdb36673a   NeilBrown   [PATCH] knfsd: Ma...
666
  {
fdb36673a   NeilBrown   [PATCH] knfsd: Ma...
667
  	struct inode *inode;
fdb36673a   NeilBrown   [PATCH] knfsd: Ma...
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  
  	if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO)
  		return ERR_PTR(-ESTALE);
  	if (ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count))
  		return ERR_PTR(-ESTALE);
  
  	/* iget isn't really right if the inode is currently unallocated!!
  	 *
  	 * ext3_read_inode will return a bad_inode if the inode had been
  	 * deleted, so we should be safe.
  	 *
  	 * Currently we don't know the generation for parent directory, so
  	 * a generation of 0 means "accept any"
  	 */
473043dce   David Howells   iget: stop EXT3 f...
682
683
684
685
  	inode = ext3_iget(sb, ino);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
  	if (generation && inode->i_generation != generation) {
fdb36673a   NeilBrown   [PATCH] knfsd: Ma...
686
687
688
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
74af0baad   Christoph Hellwig   ext3: new export ops
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
  
  	return inode;
  }
  
  static struct dentry *ext3_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,
  				    ext3_nfs_get_inode);
  }
  
  static struct dentry *ext3_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,
  				    ext3_nfs_get_inode);
fdb36673a   NeilBrown   [PATCH] knfsd: Ma...
705
  }
6b082b531   Toshiyuki Okajima   ext3: provide fun...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
  /*
   * Try to release metadata pages (indirect blocks, directories) which are
   * mapped via the block device.  Since these pages could have journal heads
   * which would prevent try_to_free_buffers() from freeing them, we must use
   * jbd layer's try_to_free_buffers() function to release them.
   */
  static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
  				 gfp_t wait)
  {
  	journal_t *journal = EXT3_SB(sb)->s_journal;
  
  	WARN_ON(PageChecked(page));
  	if (!page_has_buffers(page))
  		return 0;
  	if (journal)
  		return journal_try_to_free_buffers(journal, page, 
  						   wait & ~__GFP_WAIT);
  	return try_to_free_buffers(page);
  }
8fc2751be   Mark Bellon   [PATCH] disk quot...
725
  #ifdef CONFIG_QUOTA
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
  #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
  #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
729
730
731
732
  static int ext3_write_dquot(struct dquot *dquot);
  static int ext3_acquire_dquot(struct dquot *dquot);
  static int ext3_release_dquot(struct dquot *dquot);
  static int ext3_mark_dquot_dirty(struct dquot *dquot);
  static int ext3_write_info(struct super_block *sb, int type);
2fd83a4f3   Jan Kara   quota: ext3: make...
733
  static int ext3_quota_on(struct super_block *sb, int type, int format_id,
f00c9e44a   Jan Kara   quota: Fix deadlo...
734
  			 struct path *path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
737
738
739
  static int ext3_quota_on_mount(struct super_block *sb, int type);
  static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
  			       size_t len, loff_t off);
  static ssize_t ext3_quota_write(struct super_block *sb, int type,
  				const char *data, size_t len, loff_t off);
61e225dc3   Alexey Dobriyan   const: make struc...
740
  static const struct dquot_operations ext3_quota_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
743
744
  	.write_dquot	= ext3_write_dquot,
  	.acquire_dquot	= ext3_acquire_dquot,
  	.release_dquot	= ext3_release_dquot,
  	.mark_dirty	= ext3_mark_dquot_dirty,
157091a2c   Jan Kara   ext3: Add default...
745
746
747
  	.write_info	= ext3_write_info,
  	.alloc_dquot	= dquot_alloc,
  	.destroy_dquot	= dquot_destroy,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  };
0d54b217a   Alexey Dobriyan   const: make struc...
749
  static const struct quotactl_ops ext3_qctl_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  	.quota_on	= ext3_quota_on,
287a80958   Christoph Hellwig   quota: rename def...
751
752
753
754
755
756
  	.quota_off	= dquot_quota_off,
  	.quota_sync	= dquot_quota_sync,
  	.get_info	= dquot_get_dqinfo,
  	.set_info	= dquot_set_dqinfo,
  	.get_dqblk	= dquot_get_dqblk,
  	.set_dqblk	= dquot_set_dqblk
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
  };
  #endif
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
759
  static const struct super_operations ext3_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
761
  	.alloc_inode	= ext3_alloc_inode,
  	.destroy_inode	= ext3_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
  	.write_inode	= ext3_write_inode,
  	.dirty_inode	= ext3_dirty_inode,
785c4bcc0   Lukas Czerner   ext3: Add fixed t...
764
  	.drop_inode	= ext3_drop_inode,
ac14a95b5   Al Viro   convert ext3 to -...
765
  	.evict_inode	= ext3_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
  	.put_super	= ext3_put_super,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  	.sync_fs	= ext3_sync_fs,
c4be0c1dc   Takashi Sato   filesystem freeze...
768
769
  	.freeze_fs	= ext3_freeze,
  	.unfreeze_fs	= ext3_unfreeze,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
  	.statfs		= ext3_statfs,
  	.remount_fs	= ext3_remount,
8fc2751be   Mark Bellon   [PATCH] disk quot...
772
  	.show_options	= ext3_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
774
775
776
  #ifdef CONFIG_QUOTA
  	.quota_read	= ext3_quota_read,
  	.quota_write	= ext3_quota_write,
  #endif
6b082b531   Toshiyuki Okajima   ext3: provide fun...
777
  	.bdev_try_to_free_page = bdev_try_to_free_page,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
  };
396551644   Christoph Hellwig   exportfs: make st...
779
  static const struct export_operations ext3_export_ops = {
74af0baad   Christoph Hellwig   ext3: new export ops
780
781
  	.fh_to_dentry = ext3_fh_to_dentry,
  	.fh_to_parent = ext3_fh_to_parent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
783
784
785
786
787
  	.get_parent = ext3_get_parent,
  };
  
  enum {
  	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
  	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
2860b733f   Adrian Bunk   [PATCH] remove CO...
788
  	Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
ade1a29e1   Badari Pulavarty   [PATCH] ext3: Add...
790
  	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
71b962574   Johann Lombardi   [PATCH] ext3: ext...
791
  	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
  	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
0e4fb5e28   Hidehiro Kawai   ext3: add an opti...
793
  	Opt_data_err_abort, Opt_data_err_ignore,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
  	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
1aeec4343   Jan Kara   ext3: Support for...
795
  	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
0636c73ee   Eric Sandeen   ext3: make barrie...
796
797
  	Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
  	Opt_resize, Opt_usrquota, Opt_grpquota
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
799
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
  	{Opt_bsd_df, "bsddf"},
  	{Opt_minix_df, "minixdf"},
  	{Opt_grpid, "grpid"},
  	{Opt_grpid, "bsdgroups"},
  	{Opt_nogrpid, "nogrpid"},
  	{Opt_nogrpid, "sysvgroups"},
  	{Opt_resgid, "resgid=%u"},
  	{Opt_resuid, "resuid=%u"},
  	{Opt_sb, "sb=%u"},
  	{Opt_err_cont, "errors=continue"},
  	{Opt_err_panic, "errors=panic"},
  	{Opt_err_ro, "errors=remount-ro"},
  	{Opt_nouid32, "nouid32"},
  	{Opt_nocheck, "nocheck"},
  	{Opt_nocheck, "check=none"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
817
818
819
820
821
822
823
824
  	{Opt_debug, "debug"},
  	{Opt_oldalloc, "oldalloc"},
  	{Opt_orlov, "orlov"},
  	{Opt_user_xattr, "user_xattr"},
  	{Opt_nouser_xattr, "nouser_xattr"},
  	{Opt_acl, "acl"},
  	{Opt_noacl, "noacl"},
  	{Opt_reservation, "reservation"},
  	{Opt_noreservation, "noreservation"},
  	{Opt_noload, "noload"},
dee1d3b62   Eric Sandeen   ext3: make "norec...
825
  	{Opt_noload, "norecovery"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
  	{Opt_nobh, "nobh"},
ade1a29e1   Badari Pulavarty   [PATCH] ext3: Add...
827
  	{Opt_bh, "bh"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
  	{Opt_commit, "commit=%u"},
  	{Opt_journal_update, "journal=update"},
  	{Opt_journal_inum, "journal=%u"},
71b962574   Johann Lombardi   [PATCH] ext3: ext...
831
  	{Opt_journal_dev, "journal_dev=%u"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
833
834
835
  	{Opt_abort, "abort"},
  	{Opt_data_journal, "data=journal"},
  	{Opt_data_ordered, "data=ordered"},
  	{Opt_data_writeback, "data=writeback"},
0e4fb5e28   Hidehiro Kawai   ext3: add an opti...
836
837
  	{Opt_data_err_abort, "data_err=abort"},
  	{Opt_data_err_ignore, "data_err=ignore"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
  	{Opt_offusrjquota, "usrjquota="},
  	{Opt_usrjquota, "usrjquota=%s"},
  	{Opt_offgrpjquota, "grpjquota="},
  	{Opt_grpjquota, "grpjquota=%s"},
  	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
  	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
1aeec4343   Jan Kara   ext3: Support for...
844
  	{Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
845
  	{Opt_grpquota, "grpquota"},
1f54587be   Jan Kara   [PATCH] quota: ex...
846
847
  	{Opt_noquota, "noquota"},
  	{Opt_quota, "quota"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
848
  	{Opt_usrquota, "usrquota"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  	{Opt_barrier, "barrier=%u"},
0636c73ee   Eric Sandeen   ext3: make barrie...
850
851
  	{Opt_barrier, "barrier"},
  	{Opt_nobarrier, "nobarrier"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  	{Opt_resize, "resize"},
92587216f   Josef Bacik   ext3: fix mount o...
853
  	{Opt_err, NULL},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854
  };
4cf46b67e   Alexey Fisher   ext3: Unify log m...
855
  static ext3_fsblk_t get_sb_block(void **data, struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
  {
e9ad5620b   Dave Kleikamp   [PATCH] ext3: Mor...
857
858
  	ext3_fsblk_t	sb_block;
  	char		*options = (char *) *data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
860
861
862
  
  	if (!options || strncmp(options, "sb=", 3) != 0)
  		return 1;	/* Default location */
  	options += 3;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
863
  	/*todo: use simple_strtoll with >32bit ext3 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
  	sb_block = simple_strtoul(options, &options, 0);
  	if (*options && *options != ',') {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
866
  		ext3_msg(sb, "error: invalid sb specification: %s",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
868
869
870
871
872
873
874
  		       (char *) *data);
  		return 1;
  	}
  	if (*options == ',')
  		options++;
  	*data = (void *) options;
  	return sb_block;
  }
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
  #ifdef CONFIG_QUOTA
  static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	char *qname;
  
  	if (sb_any_quota_loaded(sb) &&
  		!sbi->s_qf_names[qtype]) {
  		ext3_msg(sb, KERN_ERR,
  			"Cannot change journaled "
  			"quota options when quota turned on");
  		return 0;
  	}
  	qname = match_strdup(args);
  	if (!qname) {
  		ext3_msg(sb, KERN_ERR,
  			"Not enough memory for storing quotafile name");
  		return 0;
  	}
  	if (sbi->s_qf_names[qtype] &&
  		strcmp(sbi->s_qf_names[qtype], qname)) {
  		ext3_msg(sb, KERN_ERR,
  			"%s quota file already specified", QTYPE2NAME(qtype));
  		kfree(qname);
  		return 0;
  	}
  	sbi->s_qf_names[qtype] = qname;
  	if (strchr(sbi->s_qf_names[qtype], '/')) {
  		ext3_msg(sb, KERN_ERR,
  			"quotafile must be on filesystem root");
  		kfree(sbi->s_qf_names[qtype]);
  		sbi->s_qf_names[qtype] = NULL;
  		return 0;
  	}
  	set_opt(sbi->s_mount_opt, QUOTA);
  	return 1;
  }
  
  static int clear_qf_name(struct super_block *sb, int qtype) {
  
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  
  	if (sb_any_quota_loaded(sb) &&
  		sbi->s_qf_names[qtype]) {
  		ext3_msg(sb, KERN_ERR, "Cannot change journaled quota options"
  			" when quota turned on");
  		return 0;
  	}
  	/*
  	 * The space will be released later when all options are confirmed
  	 * to be correct
  	 */
  	sbi->s_qf_names[qtype] = NULL;
  	return 1;
  }
  #endif
71b962574   Johann Lombardi   [PATCH] ext3: ext...
931
  static int parse_options (char *options, struct super_block *sb,
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
932
  			  unsigned int *inum, unsigned long *journal_devnum,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
933
  			  ext3_fsblk_t *n_blocks_count, int is_remount)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
938
939
940
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	char * p;
  	substring_t args[MAX_OPT_ARGS];
  	int data_opt = 0;
  	int option;
  #ifdef CONFIG_QUOTA
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
941
  	int qfmt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
943
944
945
946
947
948
949
950
  #endif
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep (&options, ",")) != NULL) {
  		int token;
  		if (!*p)
  			continue;
0636c73ee   Eric Sandeen   ext3: make barrie...
951
952
953
954
955
  		/*
  		 * Initialize args struct so we know whether arg was
  		 * found; some options take optional arguments.
  		 */
  		args[0].to = args[0].from = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
  		token = match_token(p, tokens, args);
  		switch (token) {
  		case Opt_bsd_df:
  			clear_opt (sbi->s_mount_opt, MINIX_DF);
  			break;
  		case Opt_minix_df:
  			set_opt (sbi->s_mount_opt, MINIX_DF);
  			break;
  		case Opt_grpid:
  			set_opt (sbi->s_mount_opt, GRPID);
  			break;
  		case Opt_nogrpid:
  			clear_opt (sbi->s_mount_opt, GRPID);
  			break;
  		case Opt_resuid:
  			if (match_int(&args[0], &option))
  				return 0;
  			sbi->s_resuid = option;
  			break;
  		case Opt_resgid:
  			if (match_int(&args[0], &option))
  				return 0;
  			sbi->s_resgid = option;
  			break;
  		case Opt_sb:
  			/* handled by get_sb_block() instead of here */
  			/* *sb_block = match_int(&args[0]); */
  			break;
  		case Opt_err_panic:
  			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
  			clear_opt (sbi->s_mount_opt, ERRORS_RO);
  			set_opt (sbi->s_mount_opt, ERRORS_PANIC);
  			break;
  		case Opt_err_ro:
  			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
  			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
  			set_opt (sbi->s_mount_opt, ERRORS_RO);
  			break;
  		case Opt_err_cont:
  			clear_opt (sbi->s_mount_opt, ERRORS_RO);
  			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
  			set_opt (sbi->s_mount_opt, ERRORS_CONT);
  			break;
  		case Opt_nouid32:
  			set_opt (sbi->s_mount_opt, NO_UID32);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
1003
1004
1005
1006
1007
1008
  		case Opt_nocheck:
  			clear_opt (sbi->s_mount_opt, CHECK);
  			break;
  		case Opt_debug:
  			set_opt (sbi->s_mount_opt, DEBUG);
  			break;
  		case Opt_oldalloc:
fbc854027   Lukas Czerner   ext3: remove depr...
1009
1010
  			ext3_msg(sb, KERN_WARNING,
  				"Ignoring deprecated oldalloc option");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011
1012
  			break;
  		case Opt_orlov:
fbc854027   Lukas Czerner   ext3: remove depr...
1013
1014
  			ext3_msg(sb, KERN_WARNING,
  				"Ignoring deprecated orlov option");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
  			break;
  #ifdef CONFIG_EXT3_FS_XATTR
  		case Opt_user_xattr:
  			set_opt (sbi->s_mount_opt, XATTR_USER);
  			break;
  		case Opt_nouser_xattr:
  			clear_opt (sbi->s_mount_opt, XATTR_USER);
  			break;
  #else
  		case Opt_user_xattr:
  		case Opt_nouser_xattr:
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1026
1027
  			ext3_msg(sb, KERN_INFO,
  				"(no)user_xattr options not supported");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
  			break;
  #endif
  #ifdef CONFIG_EXT3_FS_POSIX_ACL
  		case Opt_acl:
  			set_opt(sbi->s_mount_opt, POSIX_ACL);
  			break;
  		case Opt_noacl:
  			clear_opt(sbi->s_mount_opt, POSIX_ACL);
  			break;
  #else
  		case Opt_acl:
  		case Opt_noacl:
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1040
1041
  			ext3_msg(sb, KERN_INFO,
  				"(no)acl options not supported");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  			break;
  #endif
  		case Opt_reservation:
  			set_opt(sbi->s_mount_opt, RESERVATION);
  			break;
  		case Opt_noreservation:
  			clear_opt(sbi->s_mount_opt, RESERVATION);
  			break;
  		case Opt_journal_update:
  			/* @@@ FIXME */
  			/* Eventually we will want to be able to create
  			   a journal file here.  For now, only allow the
  			   user to specify an existing inode to be the
  			   journal file. */
  			if (is_remount) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1057
1058
  				ext3_msg(sb, KERN_ERR, "error: cannot specify "
  					"journal on remount");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
1060
1061
1062
1063
1064
  				return 0;
  			}
  			set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
  			break;
  		case Opt_journal_inum:
  			if (is_remount) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1065
1066
  				ext3_msg(sb, KERN_ERR, "error: cannot specify "
  				       "journal on remount");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
1069
1070
1071
1072
  				return 0;
  			}
  			if (match_int(&args[0], &option))
  				return 0;
  			*inum = option;
  			break;
71b962574   Johann Lombardi   [PATCH] ext3: ext...
1073
1074
  		case Opt_journal_dev:
  			if (is_remount) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1075
1076
  				ext3_msg(sb, KERN_ERR, "error: cannot specify "
  				       "journal on remount");
71b962574   Johann Lombardi   [PATCH] ext3: ext...
1077
1078
1079
1080
1081
1082
  				return 0;
  			}
  			if (match_int(&args[0], &option))
  				return 0;
  			*journal_devnum = option;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
  		case Opt_noload:
  			set_opt (sbi->s_mount_opt, NOLOAD);
  			break;
  		case Opt_commit:
  			if (match_int(&args[0], &option))
  				return 0;
  			if (option < 0)
  				return 0;
  			if (option == 0)
  				option = JBD_DEFAULT_MAX_COMMIT_AGE;
  			sbi->s_commit_interval = HZ * option;
  			break;
  		case Opt_data_journal:
  			data_opt = EXT3_MOUNT_JOURNAL_DATA;
  			goto datacheck;
  		case Opt_data_ordered:
  			data_opt = EXT3_MOUNT_ORDERED_DATA;
  			goto datacheck;
  		case Opt_data_writeback:
  			data_opt = EXT3_MOUNT_WRITEBACK_DATA;
  		datacheck:
  			if (is_remount) {
e3c964359   Dmitry Monakhov   ext3: mount flags...
1105
  				if (test_opt(sb, DATA_FLAGS) == data_opt)
3c4cec652   Jan Kara   ext3: Improve err...
1106
  					break;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1107
1108
  				ext3_msg(sb, KERN_ERR,
  					"error: cannot change "
3c4cec652   Jan Kara   ext3: Improve err...
1109
1110
  					"data mode on remount. The filesystem "
  					"is mounted in data=%s mode and you "
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1111
  					"try to remount it in data=%s mode.",
e3c964359   Dmitry Monakhov   ext3: mount flags...
1112
1113
  					data_mode_string(test_opt(sb,
  							DATA_FLAGS)),
3c4cec652   Jan Kara   ext3: Improve err...
1114
1115
  					data_mode_string(data_opt));
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
  			} else {
e3c964359   Dmitry Monakhov   ext3: mount flags...
1117
  				clear_opt(sbi->s_mount_opt, DATA_FLAGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1118
1119
1120
  				sbi->s_mount_opt |= data_opt;
  			}
  			break;
0e4fb5e28   Hidehiro Kawai   ext3: add an opti...
1121
1122
1123
1124
1125
1126
  		case Opt_data_err_abort:
  			set_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
  			break;
  		case Opt_data_err_ignore:
  			clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
  #ifdef CONFIG_QUOTA
  		case Opt_usrjquota:
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
1129
  			if (!set_qf_name(sb, USRQUOTA, &args[0]))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130
  				return 0;
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
1131
1132
1133
  			break;
  		case Opt_grpjquota:
  			if (!set_qf_name(sb, GRPQUOTA, &args[0]))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1134
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
1136
  			break;
  		case Opt_offusrjquota:
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
1137
1138
1139
  			if (!clear_qf_name(sb, USRQUOTA))
  				return 0;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1140
  		case Opt_offgrpjquota:
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
1141
  			if (!clear_qf_name(sb, GRPQUOTA))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
  			break;
  		case Opt_jqfmt_vfsold:
d06bf1d25   Jan Kara   ext3: correct mou...
1145
1146
  			qfmt = QFMT_VFS_OLD;
  			goto set_qf_format;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1147
  		case Opt_jqfmt_vfsv0:
d06bf1d25   Jan Kara   ext3: correct mou...
1148
  			qfmt = QFMT_VFS_V0;
1aeec4343   Jan Kara   ext3: Support for...
1149
1150
1151
  			goto set_qf_format;
  		case Opt_jqfmt_vfsv1:
  			qfmt = QFMT_VFS_V1;
d06bf1d25   Jan Kara   ext3: correct mou...
1152
  set_qf_format:
ee0d5ffe0   Jan Kara   ext3: Use sb_any_...
1153
  			if (sb_any_quota_loaded(sb) &&
d06bf1d25   Jan Kara   ext3: correct mou...
1154
  			    sbi->s_jquota_fmt != qfmt) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1155
  				ext3_msg(sb, KERN_ERR, "error: cannot change "
d06bf1d25   Jan Kara   ext3: correct mou...
1156
  					"journaled quota options when "
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1157
  					"quota turned on.");
d06bf1d25   Jan Kara   ext3: correct mou...
1158
1159
1160
  				return 0;
  			}
  			sbi->s_jquota_fmt = qfmt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
  			break;
1f54587be   Jan Kara   [PATCH] quota: ex...
1162
  		case Opt_quota:
8fc2751be   Mark Bellon   [PATCH] disk quot...
1163
1164
1165
1166
1167
  		case Opt_usrquota:
  			set_opt(sbi->s_mount_opt, QUOTA);
  			set_opt(sbi->s_mount_opt, USRQUOTA);
  			break;
  		case Opt_grpquota:
1f54587be   Jan Kara   [PATCH] quota: ex...
1168
  			set_opt(sbi->s_mount_opt, QUOTA);
8fc2751be   Mark Bellon   [PATCH] disk quot...
1169
  			set_opt(sbi->s_mount_opt, GRPQUOTA);
1f54587be   Jan Kara   [PATCH] quota: ex...
1170
1171
  			break;
  		case Opt_noquota:
ee0d5ffe0   Jan Kara   ext3: Use sb_any_...
1172
  			if (sb_any_quota_loaded(sb)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1173
1174
  				ext3_msg(sb, KERN_ERR, "error: cannot change "
  					"quota options when quota turned on.");
1f54587be   Jan Kara   [PATCH] quota: ex...
1175
1176
1177
  				return 0;
  			}
  			clear_opt(sbi->s_mount_opt, QUOTA);
8fc2751be   Mark Bellon   [PATCH] disk quot...
1178
1179
  			clear_opt(sbi->s_mount_opt, USRQUOTA);
  			clear_opt(sbi->s_mount_opt, GRPQUOTA);
1f54587be   Jan Kara   [PATCH] quota: ex...
1180
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1181
  #else
8fc2751be   Mark Bellon   [PATCH] disk quot...
1182
1183
1184
  		case Opt_quota:
  		case Opt_usrquota:
  		case Opt_grpquota:
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1185
1186
  			ext3_msg(sb, KERN_ERR,
  				"error: quota options not supported.");
fa1ff1e02   Jan Kara   ext3: fix mount m...
1187
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
1189
1190
1191
1192
1193
  		case Opt_usrjquota:
  		case Opt_grpjquota:
  		case Opt_offusrjquota:
  		case Opt_offgrpjquota:
  		case Opt_jqfmt_vfsold:
  		case Opt_jqfmt_vfsv0:
1aeec4343   Jan Kara   ext3: Support for...
1194
  		case Opt_jqfmt_vfsv1:
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1195
1196
1197
  			ext3_msg(sb, KERN_ERR,
  				"error: journaled quota options not "
  				"supported.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
  			break;
1f54587be   Jan Kara   [PATCH] quota: ex...
1199
1200
  		case Opt_noquota:
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
1202
1203
1204
  #endif
  		case Opt_abort:
  			set_opt(sbi->s_mount_opt, ABORT);
  			break;
0636c73ee   Eric Sandeen   ext3: make barrie...
1205
1206
1207
  		case Opt_nobarrier:
  			clear_opt(sbi->s_mount_opt, BARRIER);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  		case Opt_barrier:
0636c73ee   Eric Sandeen   ext3: make barrie...
1209
1210
1211
1212
1213
  			if (args[0].from) {
  				if (match_int(&args[0], &option))
  					return 0;
  			} else
  				option = 1;	/* No argument, default to 1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
1217
1218
1219
1220
1221
  			if (option)
  				set_opt(sbi->s_mount_opt, BARRIER);
  			else
  				clear_opt(sbi->s_mount_opt, BARRIER);
  			break;
  		case Opt_ignore:
  			break;
  		case Opt_resize:
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
1222
  			if (!is_remount) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1223
1224
1225
  				ext3_msg(sb, KERN_ERR,
  					"error: resize option only available "
  					"for remount");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
  				return 0;
  			}
c7f1721ef   KAMBAROV, ZAUR   [PATCH] coverity:...
1228
1229
  			if (match_int(&args[0], &option) != 0)
  				return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
1231
1232
  			*n_blocks_count = option;
  			break;
  		case Opt_nobh:
4c4d39012   Christoph Hellwig   ext3: remove vest...
1233
1234
  			ext3_msg(sb, KERN_WARNING,
  				"warning: ignoring deprecated nobh option");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
  			break;
ade1a29e1   Badari Pulavarty   [PATCH] ext3: Add...
1236
  		case Opt_bh:
4c4d39012   Christoph Hellwig   ext3: remove vest...
1237
1238
  			ext3_msg(sb, KERN_WARNING,
  				"warning: ignoring deprecated bh option");
ade1a29e1   Badari Pulavarty   [PATCH] ext3: Add...
1239
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
  		default:
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1241
1242
1243
  			ext3_msg(sb, KERN_ERR,
  				"error: unrecognized mount option \"%s\" "
  				"or missing value", p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
1246
1247
  			return 0;
  		}
  	}
  #ifdef CONFIG_QUOTA
8fc2751be   Mark Bellon   [PATCH] disk quot...
1248
  	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
e3c964359   Dmitry Monakhov   ext3: mount flags...
1249
  		if (test_opt(sb, USRQUOTA) && sbi->s_qf_names[USRQUOTA])
8fc2751be   Mark Bellon   [PATCH] disk quot...
1250
  			clear_opt(sbi->s_mount_opt, USRQUOTA);
e3c964359   Dmitry Monakhov   ext3: mount flags...
1251
  		if (test_opt(sb, GRPQUOTA) && sbi->s_qf_names[GRPQUOTA])
8fc2751be   Mark Bellon   [PATCH] disk quot...
1252
  			clear_opt(sbi->s_mount_opt, GRPQUOTA);
e1f5c67a1   Dmitry Monakhov   ext3: trivial quo...
1253
  		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1254
1255
  			ext3_msg(sb, KERN_ERR, "error: old and new quota "
  					"format mixing.");
8fc2751be   Mark Bellon   [PATCH] disk quot...
1256
1257
1258
1259
  			return 0;
  		}
  
  		if (!sbi->s_jquota_fmt) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1260
1261
  			ext3_msg(sb, KERN_ERR, "error: journaled quota format "
  					"not specified.");
8fc2751be   Mark Bellon   [PATCH] disk quot...
1262
1263
1264
1265
  			return 0;
  		}
  	} else {
  		if (sbi->s_jquota_fmt) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1266
  			ext3_msg(sb, KERN_ERR, "error: journaled quota format "
99aeaf639   Jan Kara   ext3: fix typos i...
1267
  					"specified with no journaling "
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1268
  					"enabled.");
8fc2751be   Mark Bellon   [PATCH] disk quot...
1269
1270
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
  	return 1;
  }
  
  static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
  			    int read_only)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	int res = 0;
  
  	if (le32_to_cpu(es->s_rev_level) > EXT3_MAX_SUPP_REV) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1283
1284
1285
  		ext3_msg(sb, KERN_ERR,
  			"error: revision level too high, "
  			"forcing read-only mode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
1287
1288
1289
1290
  		res = MS_RDONLY;
  	}
  	if (read_only)
  		return res;
  	if (!(sbi->s_mount_state & EXT3_VALID_FS))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1291
1292
1293
  		ext3_msg(sb, KERN_WARNING,
  			"warning: mounting unchecked fs, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
  	else if ((sbi->s_mount_state & EXT3_ERROR_FS))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1295
1296
1297
  		ext3_msg(sb, KERN_WARNING,
  			"warning: mounting fs with errors, "
  			"running e2fsck is recommended");
df0d6b8ff   Namhyung Kim   ext3: Cleanup ext...
1298
  	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
  		 le16_to_cpu(es->s_mnt_count) >=
df0d6b8ff   Namhyung Kim   ext3: Cleanup ext...
1300
  			le16_to_cpu(es->s_max_mnt_count))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1301
1302
1303
  		ext3_msg(sb, KERN_WARNING,
  			"warning: maximal mount count reached, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1304
1305
1306
  	else if (le32_to_cpu(es->s_checkinterval) &&
  		(le32_to_cpu(es->s_lastcheck) +
  			le32_to_cpu(es->s_checkinterval) <= get_seconds()))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1307
1308
1309
  		ext3_msg(sb, KERN_WARNING,
  			"warning: checktime reached, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
1312
1313
1314
  #if 0
  		/* @@@ We _will_ want to clear the valid bit if we find
                     inconsistencies, to force a fsck at reboot.  But for
                     a plain journaled filesystem we can keep it set as
                     valid forever! :) */
e7f23ebde   Marcin Slusarz   ext3: convert byt...
1315
  	es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
  #endif
df0d6b8ff   Namhyung Kim   ext3: Cleanup ext...
1317
  	if (!le16_to_cpu(es->s_max_mnt_count))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  		es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
50e8a2890   Marcin Slusarz   ext3: replace all...
1319
  	le16_add_cpu(&es->s_mnt_count, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
1321
1322
1323
1324
1325
  	es->s_mtime = cpu_to_le32(get_seconds());
  	ext3_update_dynamic_rev(sb);
  	EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
  
  	ext3_commit_super(sb, es, 1);
  	if (test_opt(sb, DEBUG))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1326
1327
  		ext3_msg(sb, KERN_INFO, "[bs=%lu, gc=%lu, "
  				"bpg=%lu, ipg=%lu, mo=%04lx]",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
1330
1331
1332
  			sb->s_blocksize,
  			sbi->s_groups_count,
  			EXT3_BLOCKS_PER_GROUP(sb),
  			EXT3_INODES_PER_GROUP(sb),
  			sbi->s_mount_opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
  	if (EXT3_SB(sb)->s_journal->j_inode == NULL) {
  		char b[BDEVNAME_SIZE];
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1335
  		ext3_msg(sb, KERN_INFO, "using external journal on %s",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
1337
  			bdevname(EXT3_SB(sb)->s_journal->j_dev, b));
  	} else {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1338
  		ext3_msg(sb, KERN_INFO, "using internal journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
  	}
d71bc6db5   Dan Magenheimer   ext3: add cleanca...
1340
  	cleancache_init_fs(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
1343
1344
  	return res;
  }
  
  /* Called at mount-time, super-block is locked */
197cd65ac   Akinobu Mita   ext[234]: use ext...
1345
  static int ext3_check_descriptors(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
1349
1350
  	int i;
  
  	ext3_debug ("Checking group descriptors");
197cd65ac   Akinobu Mita   ext[234]: use ext...
1351
1352
  	for (i = 0; i < sbi->s_groups_count; i++) {
  		struct ext3_group_desc *gdp = ext3_get_group_desc(sb, i, NULL);
1eaafeae4   Akinobu Mita   ext3: use ext3_gr...
1353
1354
  		ext3_fsblk_t first_block = ext3_group_first_block_no(sb, i);
  		ext3_fsblk_t last_block;
197cd65ac   Akinobu Mita   ext[234]: use ext...
1355

855565e81   Eric Sandeen   [PATCH] fix ext3 ...
1356
1357
1358
1359
1360
  		if (i == sbi->s_groups_count - 1)
  			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
  		else
  			last_block = first_block +
  				(EXT3_BLOCKS_PER_GROUP(sb) - 1);
855565e81   Eric Sandeen   [PATCH] fix ext3 ...
1361
1362
  		if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
  		    le32_to_cpu(gdp->bg_block_bitmap) > last_block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
1367
1368
1369
1370
  		{
  			ext3_error (sb, "ext3_check_descriptors",
  				    "Block bitmap for group %d"
  				    " not in group (block %lu)!",
  				    i, (unsigned long)
  					le32_to_cpu(gdp->bg_block_bitmap));
  			return 0;
  		}
855565e81   Eric Sandeen   [PATCH] fix ext3 ...
1371
1372
  		if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
  		    le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373
1374
1375
1376
1377
1378
1379
1380
  		{
  			ext3_error (sb, "ext3_check_descriptors",
  				    "Inode bitmap for group %d"
  				    " not in group (block %lu)!",
  				    i, (unsigned long)
  					le32_to_cpu(gdp->bg_inode_bitmap));
  			return 0;
  		}
855565e81   Eric Sandeen   [PATCH] fix ext3 ...
1381
  		if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
780dcdb21   Eric Sandeen   fix inode_table t...
1382
  		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group - 1 >
855565e81   Eric Sandeen   [PATCH] fix ext3 ...
1383
  		    last_block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
1385
1386
1387
1388
1389
1390
1391
  		{
  			ext3_error (sb, "ext3_check_descriptors",
  				    "Inode table for group %d"
  				    " not in group (block %lu)!",
  				    i, (unsigned long)
  					le32_to_cpu(gdp->bg_inode_table));
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
  	}
  
  	sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3_count_free_blocks(sb));
  	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext3_count_free_inodes(sb));
  	return 1;
  }
  
  
  /* ext3_orphan_cleanup() walks a singly-linked list of inodes (starting at
   * the superblock) which were deleted from all directories, but held open by
   * a process at the time of a crash.  We walk the list and try to delete these
   * inodes at recovery time (only with a read-write filesystem).
   *
   * In order to keep the orphan inode chain consistent during traversal (in
   * case of crash during recovery), we link each inode into the superblock
   * orphan list_head and handle it the same way as an inode deletion during
   * normal operation (which journals the operations for us).
   *
   * We only do an iget() and an iput() on each inode, which is very safe if we
   * accidentally point at an in-use or already deleted inode.  The worst that
   * can happen in this case is that we get a "bit already cleared" message from
   * ext3_free_inode().  The only reason we would point at a wrong inode is if
   * e2fsck was run on this filesystem, and it must have already done the orphan
   * inode cleanup for us, so we can safely abort without any further action.
   */
  static void ext3_orphan_cleanup (struct super_block * sb,
  				 struct ext3_super_block * es)
  {
  	unsigned int s_flags = sb->s_flags;
  	int nr_orphans = 0, nr_truncates = 0;
  #ifdef CONFIG_QUOTA
  	int i;
  #endif
  	if (!es->s_last_orphan) {
  		jbd_debug(4, "no orphan inodes to clean up
  ");
  		return;
  	}
a8f48a956   Eric Sandeen   [PATCH] ext3/4: d...
1430
  	if (bdev_read_only(sb->s_bdev)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1431
1432
  		ext3_msg(sb, KERN_ERR, "error: write access "
  			"unavailable, skipping orphan cleanup.");
a8f48a956   Eric Sandeen   [PATCH] ext3/4: d...
1433
1434
  		return;
  	}
ce654b37f   Amir Goldstein   ext3: skip orphan...
1435
1436
1437
1438
1439
  	/* Check if feature set allows readwrite operations */
  	if (EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) {
  		ext3_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
  			 "unknown ROCOMPAT features");
  		return;
a8f48a956   Eric Sandeen   [PATCH] ext3/4: d...
1440
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
  	if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
  		if (es->s_last_orphan)
  			jbd_debug(1, "Errors on filesystem, "
  				  "clearing orphan list.
  ");
  		es->s_last_orphan = 0;
  		jbd_debug(1, "Skipping orphan recovery on fs with errors.
  ");
  		return;
  	}
  
  	if (s_flags & MS_RDONLY) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1453
  		ext3_msg(sb, KERN_INFO, "orphan cleanup on readonly fs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
  		sb->s_flags &= ~MS_RDONLY;
  	}
  #ifdef CONFIG_QUOTA
  	/* Needed for iput() to work correctly and not trash data */
  	sb->s_flags |= MS_ACTIVE;
  	/* Turn on quotas so that they are updated correctly */
  	for (i = 0; i < MAXQUOTAS; i++) {
  		if (EXT3_SB(sb)->s_qf_names[i]) {
  			int ret = ext3_quota_on_mount(sb, i);
  			if (ret < 0)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1464
1465
1466
  				ext3_msg(sb, KERN_ERR,
  					"error: cannot turn on journaled "
  					"quota: %d", ret);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
1468
1469
1470
1471
1472
  		}
  	}
  #endif
  
  	while (es->s_last_orphan) {
  		struct inode *inode;
473043dce   David Howells   iget: stop EXT3 f...
1473
1474
  		inode = ext3_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
  		if (IS_ERR(inode)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
1476
1477
1478
1479
  			es->s_last_orphan = 0;
  			break;
  		}
  
  		list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
871a29315   Christoph Hellwig   dquot: cleanup dq...
1480
  		dquot_initialize(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
1482
  		if (inode->i_nlink) {
  			printk(KERN_DEBUG
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
1483
1484
  				"%s: truncating inode %lu to %Ld bytes
  ",
e05b6b524   Harvey Harrison   ext3: replace rem...
1485
  				__func__, inode->i_ino, inode->i_size);
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
1486
1487
  			jbd_debug(2, "truncating inode %lu to %Ld bytes
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488
1489
1490
1491
1492
  				  inode->i_ino, inode->i_size);
  			ext3_truncate(inode);
  			nr_truncates++;
  		} else {
  			printk(KERN_DEBUG
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
1493
1494
  				"%s: deleting unreferenced inode %lu
  ",
e05b6b524   Harvey Harrison   ext3: replace rem...
1495
  				__func__, inode->i_ino);
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
1496
1497
  			jbd_debug(2, "deleting unreferenced inode %lu
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
1500
1501
1502
1503
1504
1505
1506
  				  inode->i_ino);
  			nr_orphans++;
  		}
  		iput(inode);  /* The delete magic happens here! */
  	}
  
  #define PLURAL(x) (x), ((x)==1) ? "" : "s"
  
  	if (nr_orphans)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1507
1508
  		ext3_msg(sb, KERN_INFO, "%d orphan inode%s deleted",
  		       PLURAL(nr_orphans));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
  	if (nr_truncates)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1510
1511
  		ext3_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
  		       PLURAL(nr_truncates));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1512
1513
1514
1515
  #ifdef CONFIG_QUOTA
  	/* Turn quotas off */
  	for (i = 0; i < MAXQUOTAS; i++) {
  		if (sb_dqopt(sb)->files[i])
287a80958   Christoph Hellwig   quota: rename def...
1516
  			dquot_quota_off(sb, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
1518
1519
1520
  	}
  #endif
  	sb->s_flags = s_flags; /* Restore MS_RDONLY status */
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
1523
1524
1525
1526
1527
1528
  /*
   * Maximal file size.  There is a direct, and {,double-,triple-}indirect
   * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
   * We need to be 1 filesystem block less than the 2^32 sector limit.
   */
  static loff_t ext3_max_size(int bits)
  {
  	loff_t res = EXT3_NDIR_BLOCKS;
fe7fdc37b   Aneesh Kumar K.V   ext3: Fix the max...
1529
1530
1531
1532
1533
  	int meta_blocks;
  	loff_t upper_limit;
  
  	/* This is calculated to be the largest file size for a
  	 * dense, file such that the total number of
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
  	 * sectors in the file, including data and all indirect blocks,
fe7fdc37b   Aneesh Kumar K.V   ext3: Fix the max...
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
  	 * does not exceed 2^32 -1
  	 * __u32 i_blocks representing the total number of
  	 * 512 bytes blocks of the file
  	 */
  	upper_limit = (1LL << 32) - 1;
  
  	/* total blocks in file system block size */
  	upper_limit >>= (bits - 9);
  
  
  	/* indirect blocks */
  	meta_blocks = 1;
  	/* double indirect blocks */
  	meta_blocks += 1 + (1LL << (bits-2));
  	/* tripple indirect blocks */
  	meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
  
  	upper_limit -= meta_blocks;
  	upper_limit <<= bits;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
1555
1556
1557
1558
1559
1560
  
  	res += 1LL << (bits-2);
  	res += 1LL << (2*(bits-2));
  	res += 1LL << (3*(bits-2));
  	res <<= bits;
  	if (res > upper_limit)
  		res = upper_limit;
fe7fdc37b   Aneesh Kumar K.V   ext3: Fix the max...
1561
1562
1563
  
  	if (res > MAX_LFS_FILESIZE)
  		res = MAX_LFS_FILESIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564
1565
  	return res;
  }
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
1566
1567
  static ext3_fsblk_t descriptor_loc(struct super_block *sb,
  				    ext3_fsblk_t logic_sb_block,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1568
1569
1570
  				    int nr)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
1571
  	unsigned long bg, first_meta_bg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
  	int has_super = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1573
1574
1575
1576
1577
1578
1579
1580
  	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
  
  	if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_META_BG) ||
  	    nr < first_meta_bg)
  		return (logic_sb_block + nr + 1);
  	bg = sbi->s_desc_per_block * nr;
  	if (ext3_bg_has_super(sb, bg))
  		has_super = 1;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
1581
  	return (has_super + ext3_group_first_block_no(sb, bg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1582
1583
1584
1585
1586
1587
1588
1589
  }
  
  
  static int ext3_fill_super (struct super_block *sb, void *data, int silent)
  {
  	struct buffer_head * bh;
  	struct ext3_super_block *es = NULL;
  	struct ext3_sb_info *sbi;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
1590
  	ext3_fsblk_t block;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1591
  	ext3_fsblk_t sb_block = get_sb_block(&data, sb);
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
1592
  	ext3_fsblk_t logic_sb_block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
  	unsigned long offset = 0;
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
1594
  	unsigned int journal_inum = 0;
71b962574   Johann Lombardi   [PATCH] ext3: ext...
1595
  	unsigned long journal_devnum = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
1597
1598
1599
1600
1601
1602
  	unsigned long def_mount_opts;
  	struct inode *root;
  	int blocksize;
  	int hblock;
  	int db_count;
  	int i;
  	int needs_recovery;
473043dce   David Howells   iget: stop EXT3 f...
1603
  	int ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1604
  	__le32 features;
833f4077b   Peter Zijlstra   lib: percpu_count...
1605
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606

f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
1607
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
1609
  	if (!sbi)
  		return -ENOMEM;
5df096d67   Pekka Enberg   ext3: allocate ->...
1610
1611
1612
1613
1614
1615
1616
  
  	sbi->s_blockgroup_lock =
  		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
  	if (!sbi->s_blockgroup_lock) {
  		kfree(sbi);
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617
  	sb->s_fs_info = sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
1619
1620
  	sbi->s_mount_opt = 0;
  	sbi->s_resuid = EXT3_DEF_RESUID;
  	sbi->s_resgid = EXT3_DEF_RESGID;
571beed8d   Miklos Szeredi   ext3: show all mo...
1621
  	sbi->s_sb_block = sb_block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1622

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
1624
  	blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE);
  	if (!blocksize) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1625
  		ext3_msg(sb, KERN_ERR, "error: unable to set blocksize");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
  		goto out_fail;
  	}
  
  	/*
  	 * The ext3 superblock will not be buffer aligned for other than 1kB
  	 * block sizes.  We need to calculate the offset from buffer start.
  	 */
  	if (blocksize != EXT3_MIN_BLOCK_SIZE) {
  		logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
  		offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
  	} else {
  		logic_sb_block = sb_block;
  	}
  
  	if (!(bh = sb_bread(sb, logic_sb_block))) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1641
  		ext3_msg(sb, KERN_ERR, "error: unable to read superblock");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1642
1643
1644
1645
1646
1647
  		goto out_fail;
  	}
  	/*
  	 * Note: s_es must be initialized as soon as possible because
  	 *       some ext3 macro-instructions depend on its value
  	 */
57e94d864   Namhyung Kim   ext3: Remove unne...
1648
  	es = (struct ext3_super_block *) (bh->b_data + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
  	sbi->s_es = es;
  	sb->s_magic = le16_to_cpu(es->s_magic);
  	if (sb->s_magic != EXT3_SUPER_MAGIC)
  		goto cantfind_ext3;
  
  	/* Set defaults before we parse the mount options */
  	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
  	if (def_mount_opts & EXT3_DEFM_DEBUG)
  		set_opt(sbi->s_mount_opt, DEBUG);
  	if (def_mount_opts & EXT3_DEFM_BSDGROUPS)
  		set_opt(sbi->s_mount_opt, GRPID);
  	if (def_mount_opts & EXT3_DEFM_UID16)
  		set_opt(sbi->s_mount_opt, NO_UID32);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
1662
  #ifdef CONFIG_EXT3_FS_XATTR
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1663
1664
  	if (def_mount_opts & EXT3_DEFM_XATTR_USER)
  		set_opt(sbi->s_mount_opt, XATTR_USER);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
1665
1666
  #endif
  #ifdef CONFIG_EXT3_FS_POSIX_ACL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
1668
  	if (def_mount_opts & EXT3_DEFM_ACL)
  		set_opt(sbi->s_mount_opt, POSIX_ACL);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
1669
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
  	if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_DATA)
e3c964359   Dmitry Monakhov   ext3: mount flags...
1671
  		set_opt(sbi->s_mount_opt, JOURNAL_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
  	else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_ORDERED)
e3c964359   Dmitry Monakhov   ext3: mount flags...
1673
  		set_opt(sbi->s_mount_opt, ORDERED_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
  	else if ((def_mount_opts & EXT3_DEFM_JMODE) == EXT3_DEFM_JMODE_WBACK)
e3c964359   Dmitry Monakhov   ext3: mount flags...
1675
  		set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1676
1677
1678
  
  	if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_PANIC)
  		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
1eca93f9c   Aneesh Kumar K.V   ext3: change the ...
1679
  	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_CONTINUE)
2245d7c21   Dmitry Mishin   [PATCH] ext3: err...
1680
  		set_opt(sbi->s_mount_opt, ERRORS_CONT);
1eca93f9c   Aneesh Kumar K.V   ext3: change the ...
1681
1682
  	else
  		set_opt(sbi->s_mount_opt, ERRORS_RO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
1684
1685
  
  	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
  	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
00eacd66c   Christoph Hellwig   ext3: make ext3 m...
1686
1687
  	/* enable barriers by default */
  	set_opt(sbi->s_mount_opt, BARRIER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
  	set_opt(sbi->s_mount_opt, RESERVATION);
71b962574   Johann Lombardi   [PATCH] ext3: ext...
1689
1690
  	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
  			    NULL, 0))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1691
1692
1693
  		goto failed_mount;
  
  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
e3c964359   Dmitry Monakhov   ext3: mount flags...
1694
  		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
1696
1697
1698
1699
  
  	if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&
  	    (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
  	     EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
  	     EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1700
1701
1702
  		ext3_msg(sb, KERN_WARNING,
  			"warning: feature flags set on rev 0 fs, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
1704
1705
1706
1707
1708
1709
  	/*
  	 * Check feature flags regardless of the revision level, since we
  	 * previously didn't change the revision level when setting the flags,
  	 * so there is a chance incompat flags are set on a rev 0 filesystem.
  	 */
  	features = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP);
  	if (features) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1710
1711
1712
  		ext3_msg(sb, KERN_ERR,
  			"error: couldn't mount because of unsupported "
  			"optional features (%x)", le32_to_cpu(features));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1713
1714
1715
1716
  		goto failed_mount;
  	}
  	features = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP);
  	if (!(sb->s_flags & MS_RDONLY) && features) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1717
1718
1719
  		ext3_msg(sb, KERN_ERR,
  			"error: couldn't mount RDWR because of unsupported "
  			"optional features (%x)", le32_to_cpu(features));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
1721
1722
1723
1724
1725
  		goto failed_mount;
  	}
  	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
  
  	if (blocksize < EXT3_MIN_BLOCK_SIZE ||
  	    blocksize > EXT3_MAX_BLOCK_SIZE) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1726
1727
1728
  		ext3_msg(sb, KERN_ERR,
  			"error: couldn't mount because of unsupported "
  			"filesystem blocksize %d", blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
1730
  		goto failed_mount;
  	}
e1defc4ff   Martin K. Petersen   block: Do away wi...
1731
  	hblock = bdev_logical_block_size(sb->s_bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
1733
1734
1735
1736
1737
  	if (sb->s_blocksize != blocksize) {
  		/*
  		 * Make sure the blocksize for the filesystem is larger
  		 * than the hardware sectorsize for the machine.
  		 */
  		if (blocksize < hblock) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1738
1739
1740
  			ext3_msg(sb, KERN_ERR,
  				"error: fsblocksize %d too small for "
  				"hardware sectorsize %d", blocksize, hblock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
1742
1743
1744
  			goto failed_mount;
  		}
  
  		brelse (bh);
0f0a89ebe   Takashi Sato   ext3: support lar...
1745
  		if (!sb_set_blocksize(sb, blocksize)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1746
1747
  			ext3_msg(sb, KERN_ERR,
  				"error: bad blocksize %d", blocksize);
0f0a89ebe   Takashi Sato   ext3: support lar...
1748
1749
  			goto out_fail;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750
1751
1752
1753
  		logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
  		offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
  		bh = sb_bread(sb, logic_sb_block);
  		if (!bh) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1754
1755
  			ext3_msg(sb, KERN_ERR,
  			       "error: can't read superblock on 2nd try");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756
1757
  			goto failed_mount;
  		}
57e94d864   Namhyung Kim   ext3: Remove unne...
1758
  		es = (struct ext3_super_block *)(bh->b_data + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1759
1760
  		sbi->s_es = es;
  		if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1761
1762
  			ext3_msg(sb, KERN_ERR,
  				"error: magic mismatch");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
  			goto failed_mount;
  		}
  	}
  
  	sb->s_maxbytes = ext3_max_size(sb->s_blocksize_bits);
  
  	if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV) {
  		sbi->s_inode_size = EXT3_GOOD_OLD_INODE_SIZE;
  		sbi->s_first_ino = EXT3_GOOD_OLD_FIRST_INO;
  	} else {
  		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
  		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
  		if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) ||
3fc74269c   vignesh babu   is_power_of_2: ex...
1776
  		    (!is_power_of_2(sbi->s_inode_size)) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777
  		    (sbi->s_inode_size > blocksize)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1778
1779
  			ext3_msg(sb, KERN_ERR,
  				"error: unsupported inode size: %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
1781
1782
1783
1784
1785
1786
  				sbi->s_inode_size);
  			goto failed_mount;
  		}
  	}
  	sbi->s_frag_size = EXT3_MIN_FRAG_SIZE <<
  				   le32_to_cpu(es->s_log_frag_size);
  	if (blocksize != sbi->s_frag_size) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1787
1788
  		ext3_msg(sb, KERN_ERR,
  		       "error: fragsize %lu != blocksize %u (unsupported)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1789
1790
1791
1792
1793
1794
1795
  		       sbi->s_frag_size, blocksize);
  		goto failed_mount;
  	}
  	sbi->s_frags_per_block = 1;
  	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
  	sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
  	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
b47b6f38e   Andries E. Brouwer   ext3, ext4: avoid...
1796
  	if (EXT3_INODE_SIZE(sb) == 0 || EXT3_INODES_PER_GROUP(sb) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1797
1798
1799
1800
1801
1802
1803
1804
1805
  		goto cantfind_ext3;
  	sbi->s_inodes_per_block = blocksize / EXT3_INODE_SIZE(sb);
  	if (sbi->s_inodes_per_block == 0)
  		goto cantfind_ext3;
  	sbi->s_itb_per_group = sbi->s_inodes_per_group /
  					sbi->s_inodes_per_block;
  	sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);
  	sbi->s_sbh = bh;
  	sbi->s_mount_state = le16_to_cpu(es->s_state);
f0d1b0b30   David Howells   [PATCH] LOG2: Imp...
1806
1807
  	sbi->s_addr_per_block_bits = ilog2(EXT3_ADDR_PER_BLOCK(sb));
  	sbi->s_desc_per_block_bits = ilog2(EXT3_DESC_PER_BLOCK(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1808
1809
1810
  	for (i=0; i < 4; i++)
  		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
  	sbi->s_def_hash_version = es->s_def_hash_version;
5e1f8c9e2   Theodore Ts'o   ext3: Add support...
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
  	i = le32_to_cpu(es->s_flags);
  	if (i & EXT2_FLAGS_UNSIGNED_HASH)
  		sbi->s_hash_unsigned = 3;
  	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
  #ifdef __CHAR_UNSIGNED__
  		es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
  		sbi->s_hash_unsigned = 3;
  #else
  		es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
  #endif
5e1f8c9e2   Theodore Ts'o   ext3: Add support...
1821
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1822
1823
  
  	if (sbi->s_blocks_per_group > blocksize * 8) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1824
1825
  		ext3_msg(sb, KERN_ERR,
  			"#blocks per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1826
1827
1828
1829
  			sbi->s_blocks_per_group);
  		goto failed_mount;
  	}
  	if (sbi->s_frags_per_group > blocksize * 8) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1830
1831
  		ext3_msg(sb, KERN_ERR,
  			"error: #fragments per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1832
1833
1834
1835
  			sbi->s_frags_per_group);
  		goto failed_mount;
  	}
  	if (sbi->s_inodes_per_group > blocksize * 8) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1836
1837
  		ext3_msg(sb, KERN_ERR,
  			"error: #inodes per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1838
1839
1840
  			sbi->s_inodes_per_group);
  		goto failed_mount;
  	}
ad692bf3e   Darrick J. Wong   ext3: Return erro...
1841
1842
1843
  	err = generic_check_addressable(sb->s_blocksize_bits,
  					le32_to_cpu(es->s_blocks_count));
  	if (err) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1844
1845
  		ext3_msg(sb, KERN_ERR,
  			"error: filesystem is too large to mount safely");
fcd5df358   Mingming Cao   [PATCH] Avoid dis...
1846
  		if (sizeof(sector_t) < 8)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1847
1848
  			ext3_msg(sb, KERN_ERR,
  				"error: CONFIG_LBDAF not enabled");
ad692bf3e   Darrick J. Wong   ext3: Return erro...
1849
  		ret = err;
fcd5df358   Mingming Cao   [PATCH] Avoid dis...
1850
1851
  		goto failed_mount;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
1853
  	if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
  		goto cantfind_ext3;
855565e81   Eric Sandeen   [PATCH] fix ext3 ...
1854
1855
1856
  	sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
  			       le32_to_cpu(es->s_first_data_block) - 1)
  				       / EXT3_BLOCKS_PER_GROUP(sb)) + 1;
81a4e320e   Namhyung Kim   ext3: Use DIV_ROU...
1857
  	db_count = DIV_ROUND_UP(sbi->s_groups_count, EXT3_DESC_PER_BLOCK(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858
1859
1860
  	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
  				    GFP_KERNEL);
  	if (sbi->s_group_desc == NULL) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1861
1862
  		ext3_msg(sb, KERN_ERR,
  			"error: not enough memory");
4569cd1b0   Namhyung Kim   ext3: Return prop...
1863
  		ret = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1864
1865
  		goto failed_mount;
  	}
5df096d67   Pekka Enberg   ext3: allocate ->...
1866
  	bgl_lock_init(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1867
1868
1869
1870
1871
  
  	for (i = 0; i < db_count; i++) {
  		block = descriptor_loc(sb, logic_sb_block, i);
  		sbi->s_group_desc[i] = sb_bread(sb, block);
  		if (!sbi->s_group_desc[i]) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1872
1873
  			ext3_msg(sb, KERN_ERR,
  				"error: can't read group descriptor %d", i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
1875
1876
1877
1878
  			db_count = i;
  			goto failed_mount2;
  		}
  	}
  	if (!ext3_check_descriptors (sb)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1879
1880
  		ext3_msg(sb, KERN_ERR,
  			"error: group descriptors corrupted");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1881
1882
1883
1884
1885
  		goto failed_mount2;
  	}
  	sbi->s_gdb_count = db_count;
  	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
  	spin_lock_init(&sbi->s_next_gen_lock);
0216bfcff   Mingming Cao   [PATCH] percpu co...
1886

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
  	/* per fileystem reservation list head & lock */
  	spin_lock_init(&sbi->s_rsv_window_lock);
  	sbi->s_rsv_window_root = RB_ROOT;
  	/* Add a single, static dummy reservation to the start of the
  	 * reservation window list --- it gives us a placeholder for
  	 * append-at-start-of-list which makes the allocation logic
  	 * _much_ simpler. */
  	sbi->s_rsv_window_head.rsv_start = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
  	sbi->s_rsv_window_head.rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
  	sbi->s_rsv_window_head.rsv_alloc_hit = 0;
  	sbi->s_rsv_window_head.rsv_goal_size = 0;
  	ext3_rsv_window_add(sb, &sbi->s_rsv_window_head);
  
  	/*
  	 * set up enough so that it can read an inode
  	 */
  	sb->s_op = &ext3_sops;
  	sb->s_export_op = &ext3_export_ops;
  	sb->s_xattr = ext3_xattr_handlers;
  #ifdef CONFIG_QUOTA
  	sb->s_qcop = &ext3_qctl_operations;
  	sb->dq_op = &ext3_quota_operations;
  #endif
03cb5f03d   Aneesh Kumar K.V   ext3: Copy fs UUI...
1910
  	memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1911
  	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
b8a052d01   Eric Sandeen   ext3: Replace loc...
1912
  	mutex_init(&sbi->s_orphan_lock);
96d2a495c   Eric Sandeen   ext3: Replace loc...
1913
  	mutex_init(&sbi->s_resize_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
  
  	sb->s_root = NULL;
  
  	needs_recovery = (es->s_last_orphan != 0 ||
  			  EXT3_HAS_INCOMPAT_FEATURE(sb,
  				    EXT3_FEATURE_INCOMPAT_RECOVER));
  
  	/*
  	 * The first inode we look at is the journal inode.  Don't try
  	 * root first: it may be modified in the journal!
  	 */
  	if (!test_opt(sb, NOLOAD) &&
  	    EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
71b962574   Johann Lombardi   [PATCH] ext3: ext...
1927
  		if (ext3_load_journal(sb, es, journal_devnum))
41d1a636b   Dmitry Monakhov   ext3: init statis...
1928
  			goto failed_mount2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1929
1930
  	} else if (journal_inum) {
  		if (ext3_create_journal(sb, es, journal_inum))
41d1a636b   Dmitry Monakhov   ext3: init statis...
1931
  			goto failed_mount2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1932
1933
  	} else {
  		if (!silent)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1934
1935
1936
  			ext3_msg(sb, KERN_ERR,
  				"error: no journal found. "
  				"mounting ext3 over ext2?");
41d1a636b   Dmitry Monakhov   ext3: init statis...
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
  		goto failed_mount2;
  	}
  	err = percpu_counter_init(&sbi->s_freeblocks_counter,
  			ext3_count_free_blocks(sb));
  	if (!err) {
  		err = percpu_counter_init(&sbi->s_freeinodes_counter,
  				ext3_count_free_inodes(sb));
  	}
  	if (!err) {
  		err = percpu_counter_init(&sbi->s_dirs_counter,
  				ext3_count_dirs(sb));
  	}
  	if (err) {
  		ext3_msg(sb, KERN_ERR, "error: insufficient memory");
4569cd1b0   Namhyung Kim   ext3: Return prop...
1951
  		ret = err;
0216bfcff   Mingming Cao   [PATCH] percpu co...
1952
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
  	}
  
  	/* We have now updated the journal if required, so we can
  	 * validate the data journaling mode. */
  	switch (test_opt(sb, DATA_FLAGS)) {
  	case 0:
  		/* No mode set, assume a default based on the journal
                     capabilities: ORDERED_DATA if the journal can
                     cope, else JOURNAL_DATA */
  		if (journal_check_available_features
  		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE))
bbae8bcc4   Linus Torvalds   ext3: make defaul...
1964
  			set_opt(sbi->s_mount_opt, DEFAULT_DATA_MODE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1965
1966
1967
1968
1969
1970
1971
1972
  		else
  			set_opt(sbi->s_mount_opt, JOURNAL_DATA);
  		break;
  
  	case EXT3_MOUNT_ORDERED_DATA:
  	case EXT3_MOUNT_WRITEBACK_DATA:
  		if (!journal_check_available_features
  		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1973
1974
1975
  			ext3_msg(sb, KERN_ERR,
  				"error: journal does not support "
  				"requested data journaling mode");
41d1a636b   Dmitry Monakhov   ext3: init statis...
1976
  			goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1977
1978
1979
1980
  		}
  	default:
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1981
1982
1983
1984
  	/*
  	 * The journal_load will have done any necessary log recovery,
  	 * so we can safely mount the rest of the filesystem now.
  	 */
473043dce   David Howells   iget: stop EXT3 f...
1985
1986
  	root = ext3_iget(sb, EXT3_ROOT_INO);
  	if (IS_ERR(root)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1987
  		ext3_msg(sb, KERN_ERR, "error: get root inode failed");
473043dce   David Howells   iget: stop EXT3 f...
1988
  		ret = PTR_ERR(root);
41d1a636b   Dmitry Monakhov   ext3: init statis...
1989
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990
1991
  	}
  	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
473043dce   David Howells   iget: stop EXT3 f...
1992
  		iput(root);
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1993
  		ext3_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
41d1a636b   Dmitry Monakhov   ext3: init statis...
1994
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1995
  	}
473043dce   David Howells   iget: stop EXT3 f...
1996
1997
  	sb->s_root = d_alloc_root(root);
  	if (!sb->s_root) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
1998
  		ext3_msg(sb, KERN_ERR, "error: get root dentry failed");
473043dce   David Howells   iget: stop EXT3 f...
1999
2000
  		iput(root);
  		ret = -ENOMEM;
41d1a636b   Dmitry Monakhov   ext3: init statis...
2001
  		goto failed_mount3;
473043dce   David Howells   iget: stop EXT3 f...
2002
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003
2004
  
  	ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
ed505ee45   Eric Sandeen   ext3: Remove outd...
2005

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2006
2007
2008
  	EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;
  	ext3_orphan_cleanup(sb, es);
  	EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;
63894ab9f   Eryu Guan   ext3: call ext3_m...
2009
2010
  	if (needs_recovery) {
  		ext3_mark_recovery_complete(sb, es);
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2011
  		ext3_msg(sb, KERN_INFO, "recovery complete");
63894ab9f   Eryu Guan   ext3: call ext3_m...
2012
  	}
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2013
  	ext3_msg(sb, KERN_INFO, "mounted filesystem with %s data mode",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014
2015
2016
  		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":
  		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
  		"writeback");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2017
2018
2019
2020
  	return 0;
  
  cantfind_ext3:
  	if (!silent)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2021
2022
  		ext3_msg(sb, KERN_INFO,
  			"error: can't find ext3 filesystem on dev %s.",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2023
2024
  		       sb->s_id);
  	goto failed_mount;
0216bfcff   Mingming Cao   [PATCH] percpu co...
2025
2026
2027
2028
  failed_mount3:
  	percpu_counter_destroy(&sbi->s_freeblocks_counter);
  	percpu_counter_destroy(&sbi->s_freeinodes_counter);
  	percpu_counter_destroy(&sbi->s_dirs_counter);
41d1a636b   Dmitry Monakhov   ext3: init statis...
2029
  	journal_destroy(sbi->s_journal);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
  failed_mount2:
  	for (i = 0; i < db_count; i++)
  		brelse(sbi->s_group_desc[i]);
  	kfree(sbi->s_group_desc);
  failed_mount:
  #ifdef CONFIG_QUOTA
  	for (i = 0; i < MAXQUOTAS; i++)
  		kfree(sbi->s_qf_names[i]);
  #endif
  	ext3_blkdev_remove(sbi);
  	brelse(bh);
  out_fail:
  	sb->s_fs_info = NULL;
de5ce0373   Manish Katiyar   ext3: Fix memory ...
2043
  	kfree(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2044
  	kfree(sbi);
473043dce   David Howells   iget: stop EXT3 f...
2045
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2046
2047
2048
2049
2050
  }
  
  /*
   * Setup any per-fs journal parameters now.  We'll do this both on
   * initial mount, once the journal has been initialised but before we've
ae6ddcc5f   Mingming Cao   [PATCH] ext3 and ...
2051
   * done any recovery; and again on any subsequent remount.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
   */
  static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  
  	if (sbi->s_commit_interval)
  		journal->j_commit_interval = sbi->s_commit_interval;
  	/* We could also set up an ext3-specific default for the commit
  	 * interval here, but for now we'll just fall back to the jbd
  	 * default. */
  
  	spin_lock(&journal->j_state_lock);
  	if (test_opt(sb, BARRIER))
  		journal->j_flags |= JFS_BARRIER;
  	else
  		journal->j_flags &= ~JFS_BARRIER;
0e4fb5e28   Hidehiro Kawai   ext3: add an opti...
2068
2069
2070
2071
  	if (test_opt(sb, DATA_ERR_ABORT))
  		journal->j_flags |= JFS_ABORT_ON_SYNCDATA_ERR;
  	else
  		journal->j_flags &= ~JFS_ABORT_ON_SYNCDATA_ERR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2072
2073
  	spin_unlock(&journal->j_state_lock);
  }
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
2074
2075
  static journal_t *ext3_get_journal(struct super_block *sb,
  				   unsigned int journal_inum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
2077
2078
2079
2080
2081
2082
  {
  	struct inode *journal_inode;
  	journal_t *journal;
  
  	/* First, test for the existence of a valid inode on disk.  Bad
  	 * things happen if we iget() an unused inode, as the subsequent
  	 * iput() will try to delete it. */
473043dce   David Howells   iget: stop EXT3 f...
2083
2084
  	journal_inode = ext3_iget(sb, journal_inum);
  	if (IS_ERR(journal_inode)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2085
  		ext3_msg(sb, KERN_ERR, "error: no journal found");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2086
2087
2088
2089
2090
  		return NULL;
  	}
  	if (!journal_inode->i_nlink) {
  		make_bad_inode(journal_inode);
  		iput(journal_inode);
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2091
  		ext3_msg(sb, KERN_ERR, "error: journal inode is deleted");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2092
2093
2094
2095
2096
2097
  		return NULL;
  	}
  
  	jbd_debug(2, "Journal inode found at %p: %Ld bytes
  ",
  		  journal_inode, journal_inode->i_size);
473043dce   David Howells   iget: stop EXT3 f...
2098
  	if (!S_ISREG(journal_inode->i_mode)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2099
  		ext3_msg(sb, KERN_ERR, "error: invalid journal inode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2100
2101
2102
2103
2104
2105
  		iput(journal_inode);
  		return NULL;
  	}
  
  	journal = journal_init_inode(journal_inode);
  	if (!journal) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2106
  		ext3_msg(sb, KERN_ERR, "error: could not load journal inode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
  		iput(journal_inode);
  		return NULL;
  	}
  	journal->j_private = sb;
  	ext3_init_journal_params(sb, journal);
  	return journal;
  }
  
  static journal_t *ext3_get_dev_journal(struct super_block *sb,
  				       dev_t j_dev)
  {
  	struct buffer_head * bh;
  	journal_t *journal;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
2120
  	ext3_fsblk_t start;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
2121
  	ext3_fsblk_t len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
  	int hblock, blocksize;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
2123
  	ext3_fsblk_t sb_block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2124
2125
2126
  	unsigned long offset;
  	struct ext3_super_block * es;
  	struct block_device *bdev;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2127
  	bdev = ext3_blkdev_get(j_dev, sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2128
2129
  	if (bdev == NULL)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2130
  	blocksize = sb->s_blocksize;
e1defc4ff   Martin K. Petersen   block: Do away wi...
2131
  	hblock = bdev_logical_block_size(bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2132
  	if (blocksize < hblock) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2133
2134
  		ext3_msg(sb, KERN_ERR,
  			"error: blocksize too small for journal device");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
2136
2137
2138
2139
2140
2141
  		goto out_bdev;
  	}
  
  	sb_block = EXT3_MIN_BLOCK_SIZE / blocksize;
  	offset = EXT3_MIN_BLOCK_SIZE % blocksize;
  	set_blocksize(bdev, blocksize);
  	if (!(bh = __bread(bdev, sb_block, blocksize))) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2142
2143
  		ext3_msg(sb, KERN_ERR, "error: couldn't read superblock of "
  			"external journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
2145
  		goto out_bdev;
  	}
57e94d864   Namhyung Kim   ext3: Remove unne...
2146
  	es = (struct ext3_super_block *) (bh->b_data + offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2147
2148
2149
  	if ((le16_to_cpu(es->s_magic) != EXT3_SUPER_MAGIC) ||
  	    !(le32_to_cpu(es->s_feature_incompat) &
  	      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2150
2151
  		ext3_msg(sb, KERN_ERR, "error: external journal has "
  			"bad superblock");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2152
2153
2154
2155
2156
  		brelse(bh);
  		goto out_bdev;
  	}
  
  	if (memcmp(EXT3_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2157
  		ext3_msg(sb, KERN_ERR, "error: journal UUID does not match");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
  		brelse(bh);
  		goto out_bdev;
  	}
  
  	len = le32_to_cpu(es->s_blocks_count);
  	start = sb_block + 1;
  	brelse(bh);	/* we're done with the superblock */
  
  	journal = journal_init_dev(bdev, sb->s_bdev,
  					start, len, blocksize);
  	if (!journal) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2169
2170
  		ext3_msg(sb, KERN_ERR,
  			"error: failed to create device journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2171
2172
2173
  		goto out_bdev;
  	}
  	journal->j_private = sb;
d03e1292c   Zheng Liu   ext3: replace ll_...
2174
2175
2176
2177
2178
  	if (!bh_uptodate_or_lock(journal->j_sb_buffer)) {
  		if (bh_submit_read(journal->j_sb_buffer)) {
  			ext3_msg(sb, KERN_ERR, "I/O error on journal device");
  			goto out_journal;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2179
2180
  	}
  	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2181
2182
2183
  		ext3_msg(sb, KERN_ERR,
  			"error: external journal has more than one "
  			"user (unsupported) - %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
  			be32_to_cpu(journal->j_superblock->s_nr_users));
  		goto out_journal;
  	}
  	EXT3_SB(sb)->journal_bdev = bdev;
  	ext3_init_journal_params(sb, journal);
  	return journal;
  out_journal:
  	journal_destroy(journal);
  out_bdev:
  	ext3_blkdev_put(bdev);
  	return NULL;
  }
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2196
2197
2198
  static int ext3_load_journal(struct super_block *sb,
  			     struct ext3_super_block *es,
  			     unsigned long journal_devnum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2199
2200
  {
  	journal_t *journal;
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
2201
  	unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2202
  	dev_t journal_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2203
2204
  	int err = 0;
  	int really_read_only;
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2205
2206
  	if (journal_devnum &&
  	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2207
2208
  		ext3_msg(sb, KERN_INFO, "external journal device major/minor "
  			"numbers have changed");
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2209
2210
2211
  		journal_dev = new_decode_dev(journal_devnum);
  	} else
  		journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
  	really_read_only = bdev_read_only(sb->s_bdev);
  
  	/*
  	 * Are we loading a blank journal or performing recovery after a
  	 * crash?  For recovery, we need to check in advance whether we
  	 * can get read-write access to the device.
  	 */
  
  	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER)) {
  		if (sb->s_flags & MS_RDONLY) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2222
2223
  			ext3_msg(sb, KERN_INFO,
  				"recovery required on readonly filesystem");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2224
  			if (really_read_only) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2225
2226
  				ext3_msg(sb, KERN_ERR, "error: write access "
  					"unavailable, cannot proceed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2227
2228
  				return -EROFS;
  			}
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2229
2230
  			ext3_msg(sb, KERN_INFO,
  				"write access will be enabled during recovery");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2231
2232
2233
2234
  		}
  	}
  
  	if (journal_inum && journal_dev) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2235
2236
  		ext3_msg(sb, KERN_ERR, "error: filesystem has both journal "
  		       "and inode journals");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
  		return -EINVAL;
  	}
  
  	if (journal_inum) {
  		if (!(journal = ext3_get_journal(sb, journal_inum)))
  			return -EINVAL;
  	} else {
  		if (!(journal = ext3_get_dev_journal(sb, journal_dev)))
  			return -EINVAL;
  	}
0636c73ee   Eric Sandeen   ext3: make barrie...
2247
2248
2249
  	if (!(journal->j_flags & JFS_BARRIER))
  		printk(KERN_INFO "EXT3-fs: barriers not enabled
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2250
2251
2252
  	if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
  		err = journal_update_format(journal);
  		if (err)  {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2253
  			ext3_msg(sb, KERN_ERR, "error updating journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
  			journal_destroy(journal);
  			return err;
  		}
  	}
  
  	if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER))
  		err = journal_wipe(journal, !really_read_only);
  	if (!err)
  		err = journal_load(journal);
  
  	if (err) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2265
  		ext3_msg(sb, KERN_ERR, "error loading journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2266
2267
2268
2269
2270
2271
  		journal_destroy(journal);
  		return err;
  	}
  
  	EXT3_SB(sb)->s_journal = journal;
  	ext3_clear_journal_err(sb, es);
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2272

31d710a7b   Maciej Å»enczykowski   ext3: don't updat...
2273
  	if (!really_read_only && journal_devnum &&
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2274
2275
  	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
  		es->s_journal_dev = cpu_to_le32(journal_devnum);
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2276
2277
2278
2279
  
  		/* Make sure we flush the recovery flag to disk. */
  		ext3_commit_super(sb, es, 1);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280
2281
  	return 0;
  }
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2282
2283
  static int ext3_create_journal(struct super_block *sb,
  			       struct ext3_super_block *es,
eee194e76   Eric Sandeen   [PATCH] ext3: ino...
2284
  			       unsigned int journal_inum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2285
2286
  {
  	journal_t *journal;
952d9de11   Borislav Petkov   ext3: fix error h...
2287
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2288
2289
  
  	if (sb->s_flags & MS_RDONLY) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2290
2291
2292
  		ext3_msg(sb, KERN_ERR,
  			"error: readonly filesystem when trying to "
  			"create journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2293
2294
  		return -EROFS;
  	}
952d9de11   Borislav Petkov   ext3: fix error h...
2295
2296
  	journal = ext3_get_journal(sb, journal_inum);
  	if (!journal)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2297
  		return -EINVAL;
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2298
  	ext3_msg(sb, KERN_INFO, "creating new journal on inode %u",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2299
  	       journal_inum);
952d9de11   Borislav Petkov   ext3: fix error h...
2300
2301
  	err = journal_create(journal);
  	if (err) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2302
  		ext3_msg(sb, KERN_ERR, "error creating journal");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
  		journal_destroy(journal);
  		return -EIO;
  	}
  
  	EXT3_SB(sb)->s_journal = journal;
  
  	ext3_update_dynamic_rev(sb);
  	EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
  	EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL);
  
  	es->s_journal_inum = cpu_to_le32(journal_inum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2314
2315
2316
2317
2318
2319
  
  	/* Make sure we flush the recovery flag to disk. */
  	ext3_commit_super(sb, es, 1);
  
  	return 0;
  }
c4be0c1dc   Takashi Sato   filesystem freeze...
2320
2321
  static int ext3_commit_super(struct super_block *sb,
  			       struct ext3_super_block *es,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2322
2323
2324
  			       int sync)
  {
  	struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
c4be0c1dc   Takashi Sato   filesystem freeze...
2325
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2326
2327
  
  	if (!sbh)
c4be0c1dc   Takashi Sato   filesystem freeze...
2328
  		return error;
dff6825e9   Darrick J. Wong   ext3/jbd: Avoid W...
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
  
  	if (buffer_write_io_error(sbh)) {
  		/*
  		 * Oh, dear.  A previous attempt to write the
  		 * superblock failed.  This could happen because the
  		 * USB device was yanked out.  Or it could happen to
  		 * be a transient write error and maybe the block will
  		 * be remapped.  Nothing we can do but to retry the
  		 * write and hope for the best.
  		 */
  		ext3_msg(sb, KERN_ERR, "previous I/O error to "
  		       "superblock detected");
  		clear_buffer_write_io_error(sbh);
  		set_buffer_uptodate(sbh);
  	}
96ec2e0a7   Theodore Ts'o   ext3: Don't updat...
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
  	/*
  	 * If the file system is mounted read-only, don't update the
  	 * superblock write time.  This avoids updating the superblock
  	 * write time when we are mounting the root file system
  	 * read/only but we need to replay the journal; at that point,
  	 * for people who are east of GMT and who make their clock
  	 * tick in localtime for Windows bug-for-bug compatibility,
  	 * the clock is set in the future, and this will cause e2fsck
  	 * to complain and force a full file system check.
  	 */
  	if (!(sb->s_flags & MS_RDONLY))
  		es->s_wtime = cpu_to_le32(get_seconds());
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2356
2357
2358
2359
  	es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
  	es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
  	BUFFER_TRACE(sbh, "marking dirty");
  	mark_buffer_dirty(sbh);
dff6825e9   Darrick J. Wong   ext3/jbd: Avoid W...
2360
  	if (sync) {
c4be0c1dc   Takashi Sato   filesystem freeze...
2361
  		error = sync_dirty_buffer(sbh);
dff6825e9   Darrick J. Wong   ext3/jbd: Avoid W...
2362
2363
2364
2365
2366
2367
2368
  		if (buffer_write_io_error(sbh)) {
  			ext3_msg(sb, KERN_ERR, "I/O error while writing "
  			       "superblock");
  			clear_buffer_write_io_error(sbh);
  			set_buffer_uptodate(sbh);
  		}
  	}
c4be0c1dc   Takashi Sato   filesystem freeze...
2369
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
  }
  
  
  /*
   * Have we just finished recovery?  If so, and if we are mounting (or
   * remounting) the filesystem readonly, then we will end up with a
   * consistent fs on disk.  Record that fact.
   */
  static void ext3_mark_recovery_complete(struct super_block * sb,
  					struct ext3_super_block * es)
  {
  	journal_t *journal = EXT3_SB(sb)->s_journal;
  
  	journal_lock_updates(journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
2384
2385
  	if (journal_flush(journal) < 0)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2386
2387
2388
  	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) &&
  	    sb->s_flags & MS_RDONLY) {
  		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2389
2390
  		ext3_commit_super(sb, es, 1);
  	}
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
2391
2392
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2393
2394
2395
2396
2397
2398
2399
2400
  	journal_unlock_updates(journal);
  }
  
  /*
   * If we are mounting (or read-write remounting) a filesystem whose journal
   * has recorded an error from a previous lifetime, move that error to the
   * main filesystem now.
   */
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2401
2402
  static void ext3_clear_journal_err(struct super_block *sb,
  				   struct ext3_super_block *es)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
  {
  	journal_t *journal;
  	int j_errno;
  	const char *errstr;
  
  	journal = EXT3_SB(sb)->s_journal;
  
  	/*
  	 * Now check for any error status which may have been recorded in the
  	 * journal by a prior ext3_error() or ext3_abort()
  	 */
  
  	j_errno = journal_errno(journal);
  	if (j_errno) {
  		char nbuf[16];
  
  		errstr = ext3_decode_error(sb, j_errno, nbuf);
e05b6b524   Harvey Harrison   ext3: replace rem...
2420
  		ext3_warning(sb, __func__, "Filesystem error recorded "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2421
  			     "from previous mount: %s", errstr);
e05b6b524   Harvey Harrison   ext3: replace rem...
2422
  		ext3_warning(sb, __func__, "Marking fs in need of "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
  			     "filesystem check.");
  
  		EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
  		es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
  		ext3_commit_super (sb, es, 1);
  
  		journal_clear_err(journal);
  	}
  }
  
  /*
   * Force the running and committing transactions to commit,
   * and wait on the commit.
   */
  int ext3_force_commit(struct super_block *sb)
  {
  	journal_t *journal;
  	int ret;
  
  	if (sb->s_flags & MS_RDONLY)
  		return 0;
  
  	journal = EXT3_SB(sb)->s_journal;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2446
2447
2448
  	ret = ext3_journal_force_commit(journal);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2449
2450
  static int ext3_sync_fs(struct super_block *sb, int wait)
  {
02ac597c9   Jan Kara   ext3: revert "ext...
2451
  	tid_t target;
c87591b71   Arthur Jones   ext3: wait on all...
2452

785c4bcc0   Lukas Czerner   ext3: Add fixed t...
2453
  	trace_ext3_sync_fs(sb, wait);
02ac597c9   Jan Kara   ext3: revert "ext...
2454
2455
2456
2457
  	if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
  		if (wait)
  			log_wait_commit(EXT3_SB(sb)->s_journal, target);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2458
2459
2460
2461
2462
2463
2464
  	return 0;
  }
  
  /*
   * LVM calls this function before a (read-only) snapshot is created.  This
   * gives us a chance to flush the journal completely and mark the fs clean.
   */
c4be0c1dc   Takashi Sato   filesystem freeze...
2465
  static int ext3_freeze(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2466
  {
c4be0c1dc   Takashi Sato   filesystem freeze...
2467
2468
  	int error = 0;
  	journal_t *journal;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2469
2470
  
  	if (!(sb->s_flags & MS_RDONLY)) {
c4be0c1dc   Takashi Sato   filesystem freeze...
2471
  		journal = EXT3_SB(sb)->s_journal;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2472
2473
2474
  
  		/* Now we set up the journal barrier. */
  		journal_lock_updates(journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
2475
2476
2477
2478
2479
  
  		/*
  		 * We don't want to clear needs_recovery flag when we failed
  		 * to flush the journal.
  		 */
c4be0c1dc   Takashi Sato   filesystem freeze...
2480
2481
2482
  		error = journal_flush(journal);
  		if (error < 0)
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2483
2484
2485
  
  		/* Journal blocked and flushed, clear needs_recovery flag. */
  		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
c4be0c1dc   Takashi Sato   filesystem freeze...
2486
2487
2488
  		error = ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
  		if (error)
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2489
  	}
c4be0c1dc   Takashi Sato   filesystem freeze...
2490
2491
2492
2493
2494
  	return 0;
  
  out:
  	journal_unlock_updates(journal);
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2495
2496
2497
2498
2499
2500
  }
  
  /*
   * Called by LVM after the snapshot is done.  We need to reset the RECOVER
   * flag here, even though the filesystem is not technically dirty yet.
   */
c4be0c1dc   Takashi Sato   filesystem freeze...
2501
  static int ext3_unfreeze(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2502
2503
2504
2505
2506
2507
2508
2509
2510
  {
  	if (!(sb->s_flags & MS_RDONLY)) {
  		lock_super(sb);
  		/* Reser the needs_recovery flag before the fs is unlocked. */
  		EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
  		ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
  		unlock_super(sb);
  		journal_unlock_updates(EXT3_SB(sb)->s_journal);
  	}
c4be0c1dc   Takashi Sato   filesystem freeze...
2511
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2512
2513
2514
2515
2516
2517
  }
  
  static int ext3_remount (struct super_block * sb, int * flags, char * data)
  {
  	struct ext3_super_block * es;
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
2518
  	ext3_fsblk_t n_blocks_count = 0;
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2519
2520
  	unsigned long old_sb_flags;
  	struct ext3_mount_options old_opts;
c79d967de   Christoph Hellwig   quota: move remou...
2521
  	int enable_quota = 0;
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2522
2523
2524
2525
2526
2527
  	int err;
  #ifdef CONFIG_QUOTA
  	int i;
  #endif
  
  	/* Store the original options */
bbd6851a3   Al Viro   Push lock_super()...
2528
  	lock_super(sb);
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
  	old_sb_flags = sb->s_flags;
  	old_opts.s_mount_opt = sbi->s_mount_opt;
  	old_opts.s_resuid = sbi->s_resuid;
  	old_opts.s_resgid = sbi->s_resgid;
  	old_opts.s_commit_interval = sbi->s_commit_interval;
  #ifdef CONFIG_QUOTA
  	old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
  	for (i = 0; i < MAXQUOTAS; i++)
  		old_opts.s_qf_names[i] = sbi->s_qf_names[i];
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2539
2540
2541
2542
  
  	/*
  	 * Allow the "check" option to be passed as a remount option.
  	 */
71b962574   Johann Lombardi   [PATCH] ext3: ext...
2543
  	if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2544
2545
2546
  		err = -EINVAL;
  		goto restore_opts;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2547

e3c964359   Dmitry Monakhov   ext3: mount flags...
2548
  	if (test_opt(sb, ABORT))
e05b6b524   Harvey Harrison   ext3: replace rem...
2549
  		ext3_abort(sb, __func__, "Abort forced by user");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2550
2551
  
  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
e3c964359   Dmitry Monakhov   ext3: mount flags...
2552
  		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2553
2554
2555
2556
2557
2558
2559
  
  	es = sbi->s_es;
  
  	ext3_init_journal_params(sb, sbi->s_journal);
  
  	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
  		n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
e3c964359   Dmitry Monakhov   ext3: mount flags...
2560
  		if (test_opt(sb, ABORT)) {
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2561
2562
2563
  			err = -EROFS;
  			goto restore_opts;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2564
2565
  
  		if (*flags & MS_RDONLY) {
0f0dd62fd   Christoph Hellwig   quota: kill the v...
2566
2567
  			err = dquot_suspend(sb, -1);
  			if (err < 0)
c79d967de   Christoph Hellwig   quota: move remou...
2568
  				goto restore_opts;
c79d967de   Christoph Hellwig   quota: move remou...
2569

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
  			/*
  			 * First of all, the unconditional stuff we have to do
  			 * to disable replay of the journal when we next remount
  			 */
  			sb->s_flags |= MS_RDONLY;
  
  			/*
  			 * OK, test if we are remounting a valid rw partition
  			 * readonly, and if so set the rdonly flag and then
  			 * mark the partition as valid again.
  			 */
  			if (!(es->s_state & cpu_to_le16(EXT3_VALID_FS)) &&
  			    (sbi->s_mount_state & EXT3_VALID_FS))
  				es->s_state = cpu_to_le16(sbi->s_mount_state);
  
  			ext3_mark_recovery_complete(sb, es);
  		} else {
  			__le32 ret;
  			if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
  					~EXT3_FEATURE_RO_COMPAT_SUPP))) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2590
2591
2592
2593
  				ext3_msg(sb, KERN_WARNING,
  					"warning: couldn't remount RDWR "
  					"because of unsupported optional "
  					"features (%x)", le32_to_cpu(ret));
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2594
2595
  				err = -EROFS;
  				goto restore_opts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596
  			}
ea9a05a13   Eric Sandeen   [PATCH] ext3: ref...
2597
2598
2599
2600
  
  			/*
  			 * If we have an unprocessed orphan list hanging
  			 * around from a previously readonly bdev mount,
1cde201da   Toshiyuki Okajima   ext3: fix message...
2601
  			 * require a full umount & mount for now.
ea9a05a13   Eric Sandeen   [PATCH] ext3: ref...
2602
2603
  			 */
  			if (es->s_last_orphan) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2604
  				ext3_msg(sb, KERN_WARNING, "warning: couldn't "
ea9a05a13   Eric Sandeen   [PATCH] ext3: ref...
2605
2606
  				       "remount RDWR because of unprocessed "
  				       "orphan inode list.  Please "
1cde201da   Toshiyuki Okajima   ext3: fix message...
2607
  				       "umount & mount instead.");
ea9a05a13   Eric Sandeen   [PATCH] ext3: ref...
2608
2609
2610
  				err = -EINVAL;
  				goto restore_opts;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2611
2612
2613
2614
2615
2616
2617
2618
  			/*
  			 * Mounting a RDONLY partition read-write, so reread
  			 * and store the current valid flag.  (It may have
  			 * been changed by e2fsck since we originally mounted
  			 * the partition.)
  			 */
  			ext3_clear_journal_err(sb, es);
  			sbi->s_mount_state = le16_to_cpu(es->s_state);
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
2619
  			if ((err = ext3_group_extend(sb, es, n_blocks_count)))
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2620
  				goto restore_opts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2621
2622
  			if (!ext3_setup_super (sb, es, 0))
  				sb->s_flags &= ~MS_RDONLY;
c79d967de   Christoph Hellwig   quota: move remou...
2623
  			enable_quota = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2624
2625
  		}
  	}
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2626
2627
2628
2629
2630
2631
2632
  #ifdef CONFIG_QUOTA
  	/* Release old quota file names */
  	for (i = 0; i < MAXQUOTAS; i++)
  		if (old_opts.s_qf_names[i] &&
  		    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
  			kfree(old_opts.s_qf_names[i]);
  #endif
bbd6851a3   Al Viro   Push lock_super()...
2633
  	unlock_super(sb);
c79d967de   Christoph Hellwig   quota: move remou...
2634
2635
  
  	if (enable_quota)
0f0dd62fd   Christoph Hellwig   quota: kill the v...
2636
  		dquot_resume(sb, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2637
  	return 0;
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
  restore_opts:
  	sb->s_flags = old_sb_flags;
  	sbi->s_mount_opt = old_opts.s_mount_opt;
  	sbi->s_resuid = old_opts.s_resuid;
  	sbi->s_resgid = old_opts.s_resgid;
  	sbi->s_commit_interval = old_opts.s_commit_interval;
  #ifdef CONFIG_QUOTA
  	sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
  	for (i = 0; i < MAXQUOTAS; i++) {
  		if (sbi->s_qf_names[i] &&
  		    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
  			kfree(sbi->s_qf_names[i]);
  		sbi->s_qf_names[i] = old_opts.s_qf_names[i];
  	}
  #endif
bbd6851a3   Al Viro   Push lock_super()...
2653
  	unlock_super(sb);
08c6a96fd   Jan Kara   [PATCH] ext3: fix...
2654
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2655
  }
726c33422   David Howells   [PATCH] VFS: Perm...
2656
  static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2657
  {
726c33422   David Howells   [PATCH] VFS: Perm...
2658
  	struct super_block *sb = dentry->d_sb;
09fe316a7   Alex Tomas   [PATCH] fast ext3...
2659
2660
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	struct ext3_super_block *es = sbi->s_es;
50ee0a32b   Pekka Enberg   [PATCH] ext3: fsi...
2661
  	u64 fsid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2662

a71ce8c6c   Badari Pulavarty   ext3: statfs spee...
2663
2664
2665
2666
2667
  	if (test_opt(sb, MINIX_DF)) {
  		sbi->s_overhead_last = 0;
  	} else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
  		unsigned long ngroups = sbi->s_groups_count, i;
  		ext3_fsblk_t overhead = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2668
2669
2670
  		smp_rmb();
  
  		/*
a71ce8c6c   Badari Pulavarty   ext3: statfs spee...
2671
2672
2673
  		 * Compute the overhead (FS structures).  This is constant
  		 * for a given filesystem unless the number of block groups
  		 * changes so we cache the previous value until it does.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
  		 */
  
  		/*
  		 * All of the blocks before first_data_block are
  		 * overhead
  		 */
  		overhead = le32_to_cpu(es->s_first_data_block);
  
  		/*
  		 * Add the overhead attributed to the superblock and
  		 * block group descriptors.  If the sparse superblocks
  		 * feature is turned on, then not all groups have this.
  		 */
  		for (i = 0; i < ngroups; i++) {
  			overhead += ext3_bg_has_super(sb, i) +
  				ext3_bg_num_gdb(sb, i);
  			cond_resched();
  		}
  
  		/*
  		 * Every block group has an inode bitmap, a block
  		 * bitmap, and an inode table.
  		 */
a71ce8c6c   Badari Pulavarty   ext3: statfs spee...
2697
2698
2699
2700
  		overhead += ngroups * (2 + sbi->s_itb_per_group);
  		sbi->s_overhead_last = overhead;
  		smp_wmb();
  		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2701
2702
2703
2704
  	}
  
  	buf->f_type = EXT3_SUPER_MAGIC;
  	buf->f_bsize = sb->s_blocksize;
a71ce8c6c   Badari Pulavarty   ext3: statfs spee...
2705
  	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
52d9f3b40   Peter Zijlstra   lib: percpu_count...
2706
  	buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2707
2708
2709
2710
  	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
  	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
  		buf->f_bavail = 0;
  	buf->f_files = le32_to_cpu(es->s_inodes_count);
52d9f3b40   Peter Zijlstra   lib: percpu_count...
2711
  	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2712
  	buf->f_namelen = EXT3_NAME_LEN;
50ee0a32b   Pekka Enberg   [PATCH] ext3: fsi...
2713
2714
2715
2716
  	fsid = le64_to_cpup((void *)es->s_uuid) ^
  	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
  	buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
  	buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2717
2718
2719
2720
2721
2722
2723
2724
  	return 0;
  }
  
  /* Helper function for writing quotas on sync - we need to start transaction before quota file
   * is locked for write. Otherwise the are possible deadlocks:
   * Process 1                         Process 2
   * ext3_create()                     quota_sync()
   *   journal_start()                   write_dquot()
871a29315   Christoph Hellwig   dquot: cleanup dq...
2725
   *   dquot_initialize()                       down(dqio_mutex)
d3be915fc   Ingo Molnar   [PATCH] sem2mutex...
2726
   *     down(dqio_mutex)                    journal_start()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2727
2728
2729
2730
2731
2732
2733
2734
2735
   *
   */
  
  #ifdef CONFIG_QUOTA
  
  static inline struct inode *dquot_to_inode(struct dquot *dquot)
  {
  	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2736
2737
2738
2739
2740
2741
2742
2743
  static int ext3_write_dquot(struct dquot *dquot)
  {
  	int ret, err;
  	handle_t *handle;
  	struct inode *inode;
  
  	inode = dquot_to_inode(dquot);
  	handle = ext3_journal_start(inode,
1f54587be   Jan Kara   [PATCH] quota: ex...
2744
  					EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
  	if (IS_ERR(handle))
  		return PTR_ERR(handle);
  	ret = dquot_commit(dquot);
  	err = ext3_journal_stop(handle);
  	if (!ret)
  		ret = err;
  	return ret;
  }
  
  static int ext3_acquire_dquot(struct dquot *dquot)
  {
  	int ret, err;
  	handle_t *handle;
  
  	handle = ext3_journal_start(dquot_to_inode(dquot),
1f54587be   Jan Kara   [PATCH] quota: ex...
2760
  					EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
  	if (IS_ERR(handle))
  		return PTR_ERR(handle);
  	ret = dquot_acquire(dquot);
  	err = ext3_journal_stop(handle);
  	if (!ret)
  		ret = err;
  	return ret;
  }
  
  static int ext3_release_dquot(struct dquot *dquot)
  {
  	int ret, err;
  	handle_t *handle;
  
  	handle = ext3_journal_start(dquot_to_inode(dquot),
1f54587be   Jan Kara   [PATCH] quota: ex...
2776
  					EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
9c3013e9b   Jan Kara   quota: fix infini...
2777
2778
2779
  	if (IS_ERR(handle)) {
  		/* Release dquot anyway to avoid endless cycle in dqput() */
  		dquot_release(dquot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2780
  		return PTR_ERR(handle);
9c3013e9b   Jan Kara   quota: fix infini...
2781
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2782
2783
2784
2785
2786
2787
2788
2789
2790
  	ret = dquot_release(dquot);
  	err = ext3_journal_stop(handle);
  	if (!ret)
  		ret = err;
  	return ret;
  }
  
  static int ext3_mark_dquot_dirty(struct dquot *dquot)
  {
99aeaf639   Jan Kara   ext3: fix typos i...
2791
  	/* Are we journaling quotas? */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
  	if (EXT3_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
  	    EXT3_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
  		dquot_mark_dquot_dirty(dquot);
  		return ext3_write_dquot(dquot);
  	} else {
  		return dquot_mark_dquot_dirty(dquot);
  	}
  }
  
  static int ext3_write_info(struct super_block *sb, int type)
  {
  	int ret, err;
  	handle_t *handle;
  
  	/* Data block + inode block */
  	handle = ext3_journal_start(sb->s_root->d_inode, 2);
  	if (IS_ERR(handle))
  		return PTR_ERR(handle);
  	ret = dquot_commit_info(sb, type);
  	err = ext3_journal_stop(handle);
  	if (!ret)
  		ret = err;
  	return ret;
  }
  
  /*
   * Turn on quotas during mount time - we need to find
   * the quota file and such...
   */
  static int ext3_quota_on_mount(struct super_block *sb, int type)
  {
287a80958   Christoph Hellwig   quota: rename def...
2823
2824
  	return dquot_quota_on_mount(sb, EXT3_SB(sb)->s_qf_names[type],
  					EXT3_SB(sb)->s_jquota_fmt, type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2825
2826
2827
2828
2829
2830
  }
  
  /*
   * Standard function to be called on quota_on
   */
  static int ext3_quota_on(struct super_block *sb, int type, int format_id,
f00c9e44a   Jan Kara   quota: Fix deadlo...
2831
  			 struct path *path)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2832
2833
  {
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2834

1f54587be   Jan Kara   [PATCH] quota: ex...
2835
2836
  	if (!test_opt(sb, QUOTA))
  		return -EINVAL;
9cfe7b901   Jan Kara   ext3: fix synchro...
2837

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2838
  	/* Quotafile not on the same filesystem? */
d8c9584ea   Al Viro   vfs: prefer ->den...
2839
  	if (path->dentry->d_sb != sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2840
  		return -EXDEV;
9cfe7b901   Jan Kara   ext3: fix synchro...
2841
2842
2843
  	/* Journaling quota? */
  	if (EXT3_SB(sb)->s_qf_names[type]) {
  		/* Quotafile not of fs root? */
f00c9e44a   Jan Kara   quota: Fix deadlo...
2844
  		if (path->dentry->d_parent != sb->s_root)
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2845
2846
2847
  			ext3_msg(sb, KERN_WARNING,
  				"warning: Quota file not on filesystem root. "
  				"Journaled quota will not work.");
9cfe7b901   Jan Kara   ext3: fix synchro...
2848
2849
2850
2851
2852
2853
  	}
  
  	/*
  	 * When we journal data on quota file, we have to flush journal to see
  	 * all updates to the file when we bypass pagecache...
  	 */
f00c9e44a   Jan Kara   quota: Fix deadlo...
2854
  	if (ext3_should_journal_data(path->dentry->d_inode)) {
9cfe7b901   Jan Kara   ext3: fix synchro...
2855
2856
2857
2858
2859
  		/*
  		 * We don't need to lock updates but journal_flush() could
  		 * otherwise be livelocked...
  		 */
  		journal_lock_updates(EXT3_SB(sb)->s_journal);
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
2860
  		err = journal_flush(EXT3_SB(sb)->s_journal);
9cfe7b901   Jan Kara   ext3: fix synchro...
2861
  		journal_unlock_updates(EXT3_SB(sb)->s_journal);
f00c9e44a   Jan Kara   quota: Fix deadlo...
2862
  		if (err)
2d7c820e5   Hidehiro Kawai   ext3: add checks ...
2863
  			return err;
9cfe7b901   Jan Kara   ext3: fix synchro...
2864
  	}
f00c9e44a   Jan Kara   quota: Fix deadlo...
2865
  	return dquot_quota_on(sb, type, format_id, path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2866
2867
2868
2869
  }
  
  /* 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...
2870
   * itself serializes the operations (and no one else should touch the files)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
   * we don't have to be afraid of races */
  static ssize_t ext3_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 >> EXT3_BLOCK_SIZE_BITS(sb);
  	int err = 0;
  	int offset = off & (sb->s_blocksize - 1);
  	int tocopy;
  	size_t toread;
  	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;
  		bh = ext3_bread(NULL, inode, blk, 0, &err);
  		if (err)
  			return err;
  		if (!bh)	/* A hole? */
  			memset(data, 0, tocopy);
  		else
  			memcpy(data, bh->b_data+offset, tocopy);
  		brelse(bh);
  		offset = 0;
  		toread -= tocopy;
  		data += tocopy;
  		blk++;
  	}
  	return len;
  }
  
  /* Write to quotafile (we know the transaction is already started and has
   * enough credits) */
  static ssize_t ext3_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 >> EXT3_BLOCK_SIZE_BITS(sb);
  	int err = 0;
  	int offset = off & (sb->s_blocksize - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2917
  	int journal_quota = EXT3_SB(sb)->s_qf_names[type] != NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2918
2919
  	struct buffer_head *bh;
  	handle_t *handle = journal_current_handle();
9c3013e9b   Jan Kara   quota: fix infini...
2920
  	if (!handle) {
4cf46b67e   Alexey Fisher   ext3: Unify log m...
2921
2922
2923
  		ext3_msg(sb, KERN_WARNING,
  			"warning: quota write (off=%llu, len=%llu)"
  			" cancelled because transaction is not started.",
9c3013e9b   Jan Kara   quota: fix infini...
2924
2925
2926
  			(unsigned long long)off, (unsigned long long)len);
  		return -EIO;
  	}
e5472147e   Dmitry Monakhov   ext3: quota_write...
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
  
  	/*
  	 * Since we account only one data block in transaction credits,
  	 * then it is impossible to cross a block boundary.
  	 */
  	if (sb->s_blocksize - offset < len) {
  		ext3_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
  			" cancelled because not block aligned",
  			(unsigned long long)off, (unsigned long long)len);
  		return -EIO;
  	}
5c81a4197   Arjan van de Ven   [PATCH] lockdep: ...
2938
  	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
e5472147e   Dmitry Monakhov   ext3: quota_write...
2939
2940
2941
2942
2943
2944
2945
  	bh = ext3_bread(handle, inode, blk, 1, &err);
  	if (!bh)
  		goto out;
  	if (journal_quota) {
  		err = ext3_journal_get_write_access(handle, bh);
  		if (err) {
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2946
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2947
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2948
  	}
e5472147e   Dmitry Monakhov   ext3: quota_write...
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
  	lock_buffer(bh);
  	memcpy(bh->b_data+offset, data, len);
  	flush_dcache_page(bh->b_page);
  	unlock_buffer(bh);
  	if (journal_quota)
  		err = ext3_journal_dirty_metadata(handle, bh);
  	else {
  		/* Always do at least ordered writes for quotas */
  		err = ext3_journal_dirty_data(handle, bh);
  		mark_buffer_dirty(bh);
  	}
  	brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2961
  out:
e5472147e   Dmitry Monakhov   ext3: quota_write...
2962
  	if (err) {
f5c8f7dae   Jan Kara   ext3: add missing...
2963
  		mutex_unlock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2964
  		return err;
f5c8f7dae   Jan Kara   ext3: add missing...
2965
  	}
e5472147e   Dmitry Monakhov   ext3: quota_write...
2966
2967
  	if (inode->i_size < off + len) {
  		i_size_write(inode, off + len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2968
2969
2970
2971
2972
  		EXT3_I(inode)->i_disksize = inode->i_size;
  	}
  	inode->i_version++;
  	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  	ext3_mark_inode_dirty(handle, inode);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
2973
  	mutex_unlock(&inode->i_mutex);
e5472147e   Dmitry Monakhov   ext3: quota_write...
2974
  	return len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2975
2976
2977
  }
  
  #endif
152a08366   Al Viro   new helper: mount...
2978
2979
  static struct dentry *ext3_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2980
  {
152a08366   Al Viro   new helper: mount...
2981
  	return mount_bdev(fs_type, flags, dev_name, data, ext3_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2982
2983
2984
2985
2986
  }
  
  static struct file_system_type ext3_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "ext3",
152a08366   Al Viro   new helper: mount...
2987
  	.mount		= ext3_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
  
  static int __init init_ext3_fs(void)
  {
  	int err = init_ext3_xattr();
  	if (err)
  		return err;
  	err = init_inodecache();
  	if (err)
  		goto out1;
          err = register_filesystem(&ext3_fs_type);
  	if (err)
  		goto out;
  	return 0;
  out:
  	destroy_inodecache();
  out1:
e9ad5620b   Dave Kleikamp   [PATCH] ext3: Mor...
3007
  	exit_ext3_xattr();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
  	return err;
  }
  
  static void __exit exit_ext3_fs(void)
  {
  	unregister_filesystem(&ext3_fs_type);
  	destroy_inodecache();
  	exit_ext3_xattr();
  }
  
  MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
  MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
  MODULE_LICENSE("GPL");
  module_init(init_ext3_fs)
  module_exit(exit_ext3_fs)