Blame view

fs/ext2/super.c 40.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/ext2/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
  #include <linux/module.h>
  #include <linux/string.h>
8fc2751be   Mark Bellon   [PATCH] disk quot...
20
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
26
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
  #include <linux/parser.h>
  #include <linux/random.h>
  #include <linux/buffer_head.h>
a56942551   Christoph Hellwig   knfsd: exportfs: ...
27
  #include <linux/exportfs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #include <linux/vfs.h>
8fc2751be   Mark Bellon   [PATCH] disk quot...
29
30
  #include <linux/seq_file.h>
  #include <linux/mount.h>
d8ea6cf89   vignesh babu   ext2/4: use is_po...
31
  #include <linux/log2.h>
74abb9890   Jan Kara   quota: move funct...
32
  #include <linux/quotaops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
  #include <asm/uaccess.h>
  #include "ext2.h"
  #include "xattr.h"
  #include "acl.h"
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
37
  #include "xip.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
  
  static void ext2_sync_super(struct super_block *sb,
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
40
  			    struct ext2_super_block *es, int wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  static int ext2_remount (struct super_block * sb, int * flags, char * data);
726c33422   David Howells   [PATCH] VFS: Perm...
42
  static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
43
  static int ext2_sync_fs(struct super_block *sb, int wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44

23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
45
46
  void ext2_error(struct super_block *sb, const char *function,
  		const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  {
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
48
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
  	va_list args;
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
  	struct ext2_super_block *es = sbi->s_es;
  
  	if (!(sb->s_flags & MS_RDONLY)) {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
54
  		spin_lock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  		sbi->s_mount_state |= EXT2_ERROR_FS;
31f68e130   Marcin Slusarz   ext2: convert byt...
56
  		es->s_state |= cpu_to_le16(EXT2_ERROR_FS);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
57
  		spin_unlock(&sbi->s_lock);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
58
  		ext2_sync_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  	}
  
  	va_start(args, fmt);
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
62
63
64
65
66
67
68
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk(KERN_CRIT "EXT2-fs (%s): error: %s: %pV
  ",
  	       sb->s_id, function, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
  	va_end(args);
  
  	if (test_opt(sb, ERRORS_PANIC))
2314b07cb   Alexey Fisher   ext2: Unify log m...
72
73
  		panic("EXT2-fs: panic from previous error
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  	if (test_opt(sb, ERRORS_RO)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
75
76
  		ext2_msg(sb, KERN_CRIT,
  			     "error: remounting filesystem read-only");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
  		sb->s_flags |= MS_RDONLY;
  	}
  }
2314b07cb   Alexey Fisher   ext2: Unify log m...
80
81
  void ext2_msg(struct super_block *sb, const char *prefix,
  		const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  {
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
83
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
  	va_list args;
  
  	va_start(args, fmt);
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
87
88
89
90
91
92
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk("%sEXT2-fs (%s): %pV
  ", prefix, sb->s_id, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  	va_end(args);
  }
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
95
96
97
  /*
   * This must be called with sbi->s_lock held.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
103
  void ext2_update_dynamic_rev(struct super_block *sb)
  {
  	struct ext2_super_block *es = EXT2_SB(sb)->s_es;
  
  	if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
  		return;
2314b07cb   Alexey Fisher   ext2: Unify log m...
104
105
106
  	ext2_msg(sb, KERN_WARNING,
  		     "warning: updating to rev %d because of "
  		     "new feature flag, running e2fsck is recommended",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  		     EXT2_DYNAMIC_REV);
  
  	es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
  	es->s_inode_size = cpu_to_le16(EXT2_GOOD_OLD_INODE_SIZE);
  	es->s_rev_level = cpu_to_le32(EXT2_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.
  	 */
  }
  
  static void ext2_put_super (struct super_block * sb)
  {
  	int db_count;
  	int i;
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
e0ccfd959   Christoph Hellwig   quota: move unmou...
127
  	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
8c85e1251   Christoph Hellwig   remove ->write_su...
128
129
  	if (sb->s_dirt)
  		ext2_write_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
  	ext2_xattr_put_super(sb);
  	if (!(sb->s_flags & MS_RDONLY)) {
  		struct ext2_super_block *es = sbi->s_es;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
133
  		spin_lock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  		es->s_state = cpu_to_le16(sbi->s_mount_state);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
135
  		spin_unlock(&sbi->s_lock);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
136
  		ext2_sync_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
142
143
144
145
146
147
148
  	}
  	db_count = sbi->s_gdb_count;
  	for (i = 0; i < db_count; i++)
  		if (sbi->s_group_desc[i])
  			brelse (sbi->s_group_desc[i]);
  	kfree(sbi->s_group_desc);
  	kfree(sbi->s_debts);
  	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);
  	sb->s_fs_info = NULL;
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
149
  	kfree(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  	kfree(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
152
  static struct kmem_cache * ext2_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
  
  static struct inode *ext2_alloc_inode(struct super_block *sb)
  {
  	struct ext2_inode_info *ei;
e94b17660   Christoph Lameter   [PATCH] slab: rem...
157
  	ei = (struct ext2_inode_info *)kmem_cache_alloc(ext2_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  	if (!ei)
  		return NULL;
a686cd898   Martin J. Bligh   ext2 reservations
160
  	ei->i_block_alloc_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
  	ei->vfs_inode.i_version = 1;
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
164
  static void ext2_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
166
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  	kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
169
170
171
172
  static void ext2_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, ext2_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
173
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
  {
  	struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
176
  	rwlock_init(&ei->i_meta_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  #ifdef CONFIG_EXT2_FS_XATTR
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
178
  	init_rwsem(&ei->xattr_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  #endif
a686cd898   Martin J. Bligh   ext2 reservations
180
  	mutex_init(&ei->truncate_mutex);
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
181
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
183

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
  static int init_inodecache(void)
  {
  	ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
  					     sizeof(struct ext2_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
188
189
  					     0, (SLAB_RECLAIM_ACCOUNT|
  						SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
190
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
194
195
196
197
  	if (ext2_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
198
  	kmem_cache_destroy(ext2_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  }
34c80b1d9   Al Viro   vfs: switch ->sho...
200
  static int ext2_show_options(struct seq_file *seq, struct dentry *root)
8fc2751be   Mark Bellon   [PATCH] disk quot...
201
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
202
  	struct super_block *sb = root->d_sb;
93d44cb27   Miklos Szeredi   ext2: show all mo...
203
204
205
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
  	struct ext2_super_block *es = sbi->s_es;
  	unsigned long def_mount_opts;
8fc2751be   Mark Bellon   [PATCH] disk quot...
206

c15271f4e   Jan Blunck   ext2: Add ext2_sb...
207
  	spin_lock(&sbi->s_lock);
93d44cb27   Miklos Szeredi   ext2: show all mo...
208
209
210
211
212
213
214
  	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))
8fc2751be   Mark Bellon   [PATCH] disk quot...
215
  		seq_puts(seq, ",grpid");
93d44cb27   Miklos Szeredi   ext2: show all mo...
216
217
218
219
220
221
222
223
224
225
  	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS))
  		seq_puts(seq, ",nogrpid");
  	if (sbi->s_resuid != EXT2_DEF_RESUID ||
  	    le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) {
  		seq_printf(seq, ",resuid=%u", sbi->s_resuid);
  	}
  	if (sbi->s_resgid != EXT2_DEF_RESGID ||
  	    le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) {
  		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
  	}
14e11e106   Aneesh Kumar K.V   ext2: change the ...
226
  	if (test_opt(sb, ERRORS_RO)) {
93d44cb27   Miklos Szeredi   ext2: show all mo...
227
228
229
  		int def_errors = le16_to_cpu(es->s_errors);
  
  		if (def_errors == EXT2_ERRORS_PANIC ||
14e11e106   Aneesh Kumar K.V   ext2: change the ...
230
231
  		    def_errors == EXT2_ERRORS_CONTINUE) {
  			seq_puts(seq, ",errors=remount-ro");
93d44cb27   Miklos Szeredi   ext2: show all mo...
232
233
  		}
  	}
14e11e106   Aneesh Kumar K.V   ext2: change the ...
234
235
  	if (test_opt(sb, ERRORS_CONT))
  		seq_puts(seq, ",errors=continue");
93d44cb27   Miklos Szeredi   ext2: show all mo...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  	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");
  	if (test_opt(sb, OLDALLOC))
  		seq_puts(seq, ",oldalloc");
  
  #ifdef CONFIG_EXT2_FS_XATTR
  	if (test_opt(sb, XATTR_USER))
  		seq_puts(seq, ",user_xattr");
  	if (!test_opt(sb, XATTR_USER) &&
  	    (def_mount_opts & EXT2_DEFM_XATTR_USER)) {
  		seq_puts(seq, ",nouser_xattr");
  	}
  #endif
  
  #ifdef CONFIG_EXT2_FS_POSIX_ACL
  	if (test_opt(sb, POSIX_ACL))
  		seq_puts(seq, ",acl");
  	if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT2_DEFM_ACL))
  		seq_puts(seq, ",noacl");
  #endif
  
  	if (test_opt(sb, NOBH))
  		seq_puts(seq, ",nobh");
8fc2751be   Mark Bellon   [PATCH] disk quot...
263
264
265
266
267
268
269
270
  
  #if defined(CONFIG_QUOTA)
  	if (sbi->s_mount_opt & EXT2_MOUNT_USRQUOTA)
  		seq_puts(seq, ",usrquota");
  
  	if (sbi->s_mount_opt & EXT2_MOUNT_GRPQUOTA)
  		seq_puts(seq, ",grpquota");
  #endif
835417967   Carsten Otte   [PATCH] ext2: pri...
271
272
273
274
  #if defined(CONFIG_EXT2_FS_XIP)
  	if (sbi->s_mount_opt & EXT2_MOUNT_XIP)
  		seq_puts(seq, ",xip");
  #endif
35c879dc3   Miklos Szeredi   mount options: fi...
275
276
  	if (!test_opt(sb, RESERVATION))
  		seq_puts(seq, ",noreservation");
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
277
  	spin_unlock(&sbi->s_lock);
8fc2751be   Mark Bellon   [PATCH] disk quot...
278
279
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
  #ifdef CONFIG_QUOTA
  static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off);
  static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
  #endif
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
284
  static const struct super_operations ext2_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
  	.alloc_inode	= ext2_alloc_inode,
  	.destroy_inode	= ext2_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	.write_inode	= ext2_write_inode,
72edc4d08   Al Viro   merge ext2 delete...
288
  	.evict_inode	= ext2_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
  	.put_super	= ext2_put_super,
  	.write_super	= ext2_write_super,
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
291
  	.sync_fs	= ext2_sync_fs,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
  	.statfs		= ext2_statfs,
  	.remount_fs	= ext2_remount,
8fc2751be   Mark Bellon   [PATCH] disk quot...
294
  	.show_options	= ext2_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
299
  #ifdef CONFIG_QUOTA
  	.quota_read	= ext2_quota_read,
  	.quota_write	= ext2_quota_write,
  #endif
  };
2e4c68e30   Christoph Hellwig   ext2: new export ops
300
301
  static struct inode *ext2_nfs_get_inode(struct super_block *sb,
  		u64 ino, u32 generation)
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
302
  {
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
303
  	struct inode *inode;
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
304
305
306
307
308
  
  	if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO)
  		return ERR_PTR(-ESTALE);
  	if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
  		return ERR_PTR(-ESTALE);
f32948ddd   Li Haifeng   ext2: fix the out...
309
310
311
312
  	/*
  	 * ext2_iget isn't quite right if the inode is currently unallocated!
  	 * However ext2_iget currently does appropriate checks to handle stale
  	 * inodes so everything is OK.
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
313
  	 */
52fcf7032   David Howells   iget: stop EXT2 f...
314
315
316
317
  	inode = ext2_iget(sb, ino);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
  	if (generation && inode->i_generation != generation) {
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
318
319
320
321
  		/* we didn't find the right inode.. */
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
2e4c68e30   Christoph Hellwig   ext2: new export ops
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  	return inode;
  }
  
  static struct dentry *ext2_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,
  				    ext2_nfs_get_inode);
  }
  
  static struct dentry *ext2_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,
  				    ext2_nfs_get_inode);
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
337
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
340
341
342
  /* Yes, most of these are left as NULL!!
   * A NULL value implies the default, which works with ext2-like file
   * systems, but can be improved upon.
   * Currently only get_parent is required.
   */
396551644   Christoph Hellwig   exportfs: make st...
343
  static const struct export_operations ext2_export_ops = {
2e4c68e30   Christoph Hellwig   ext2: new export ops
344
345
  	.fh_to_dentry = ext2_fh_to_dentry,
  	.fh_to_parent = ext2_fh_to_parent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  	.get_parent = ext2_get_parent,
  };
  
  static unsigned long get_sb_block(void **data)
  {
  	unsigned long 	sb_block;
  	char 		*options = (char *) *data;
  
  	if (!options || strncmp(options, "sb=", 3) != 0)
  		return 1;	/* Default location */
  	options += 3;
  	sb_block = simple_strtoul(options, &options, 0);
  	if (*options && *options != ',') {
  		printk("EXT2-fs: Invalid sb specification: %s
  ",
  		       (char *) *data);
  		return 1;
  	}
  	if (*options == ',')
  		options++;
  	*data = (void *) options;
  	return sb_block;
  }
  
  enum {
  	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
8fc2751be   Mark Bellon   [PATCH] disk quot...
372
  	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
2860b733f   Adrian Bunk   [PATCH] remove CO...
373
  	Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
8fc2751be   Mark Bellon   [PATCH] disk quot...
374
375
  	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
  	Opt_acl, Opt_noacl, Opt_xip, Opt_ignore, Opt_err, Opt_quota,
a686cd898   Martin J. Bligh   ext2 reservations
376
  	Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
378
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  	{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, "check=none"},
  	{Opt_nocheck, "nocheck"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
395
396
397
398
399
400
401
  	{Opt_debug, "debug"},
  	{Opt_oldalloc, "oldalloc"},
  	{Opt_orlov, "orlov"},
  	{Opt_nobh, "nobh"},
  	{Opt_user_xattr, "user_xattr"},
  	{Opt_nouser_xattr, "nouser_xattr"},
  	{Opt_acl, "acl"},
  	{Opt_noacl, "noacl"},
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
402
  	{Opt_xip, "xip"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
403
  	{Opt_grpquota, "grpquota"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  	{Opt_ignore, "noquota"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
405
406
  	{Opt_quota, "quota"},
  	{Opt_usrquota, "usrquota"},
a686cd898   Martin J. Bligh   ext2 reservations
407
408
  	{Opt_reservation, "reservation"},
  	{Opt_noreservation, "noreservation"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
  	{Opt_err, NULL}
  };
2314b07cb   Alexey Fisher   ext2: Unify log m...
411
  static int parse_options(char *options, struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  {
2314b07cb   Alexey Fisher   ext2: Unify log m...
413
414
  	char *p;
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  	substring_t args[MAX_OPT_ARGS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
418
419
420
421
422
423
424
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
452
453
454
  	int option;
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep (&options, ",")) != NULL) {
  		int token;
  		if (!*p)
  			continue;
  
  		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:
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
455
456
457
  			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
  			clear_opt (sbi->s_mount_opt, ERRORS_RO);
  			set_opt (sbi->s_mount_opt, ERRORS_PANIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
  			break;
  		case Opt_err_ro:
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
460
461
462
  			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
  			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
  			set_opt (sbi->s_mount_opt, ERRORS_RO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
  			break;
  		case Opt_err_cont:
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
465
466
467
  			clear_opt (sbi->s_mount_opt, ERRORS_RO);
  			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
  			set_opt (sbi->s_mount_opt, ERRORS_CONT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
  			break;
  		case Opt_nouid32:
  			set_opt (sbi->s_mount_opt, NO_UID32);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  		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:
  			set_opt (sbi->s_mount_opt, OLDALLOC);
  			break;
  		case Opt_orlov:
  			clear_opt (sbi->s_mount_opt, OLDALLOC);
  			break;
  		case Opt_nobh:
  			set_opt (sbi->s_mount_opt, NOBH);
  			break;
  #ifdef CONFIG_EXT2_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:
2314b07cb   Alexey Fisher   ext2: Unify log m...
497
498
  			ext2_msg(sb, KERN_INFO, "(no)user_xattr options"
  				"not supported");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
501
502
503
504
505
506
507
508
509
510
  			break;
  #endif
  #ifdef CONFIG_EXT2_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:
2314b07cb   Alexey Fisher   ext2: Unify log m...
511
512
  			ext2_msg(sb, KERN_INFO,
  				"(no)acl options not supported");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
  			break;
  #endif
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
515
516
517
518
  		case Opt_xip:
  #ifdef CONFIG_EXT2_FS_XIP
  			set_opt (sbi->s_mount_opt, XIP);
  #else
2314b07cb   Alexey Fisher   ext2: Unify log m...
519
  			ext2_msg(sb, KERN_INFO, "xip option not supported");
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
520
521
  #endif
  			break;
8fc2751be   Mark Bellon   [PATCH] disk quot...
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  
  #if defined(CONFIG_QUOTA)
  		case Opt_quota:
  		case Opt_usrquota:
  			set_opt(sbi->s_mount_opt, USRQUOTA);
  			break;
  
  		case Opt_grpquota:
  			set_opt(sbi->s_mount_opt, GRPQUOTA);
  			break;
  #else
  		case Opt_quota:
  		case Opt_usrquota:
  		case Opt_grpquota:
2314b07cb   Alexey Fisher   ext2: Unify log m...
536
537
  			ext2_msg(sb, KERN_INFO,
  				"quota operations not supported");
8fc2751be   Mark Bellon   [PATCH] disk quot...
538
539
  			break;
  #endif
a686cd898   Martin J. Bligh   ext2 reservations
540
541
  		case Opt_reservation:
  			set_opt(sbi->s_mount_opt, RESERVATION);
2314b07cb   Alexey Fisher   ext2: Unify log m...
542
  			ext2_msg(sb, KERN_INFO, "reservations ON");
a686cd898   Martin J. Bligh   ext2 reservations
543
544
545
  			break;
  		case Opt_noreservation:
  			clear_opt(sbi->s_mount_opt, RESERVATION);
2314b07cb   Alexey Fisher   ext2: Unify log m...
546
  			ext2_msg(sb, KERN_INFO, "reservations OFF");
a686cd898   Martin J. Bligh   ext2 reservations
547
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548
549
550
551
552
553
  		case Opt_ignore:
  			break;
  		default:
  			return 0;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
557
558
559
560
561
562
563
564
  	return 1;
  }
  
  static int ext2_setup_super (struct super_block * sb,
  			      struct ext2_super_block * es,
  			      int read_only)
  {
  	int res = 0;
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
  
  	if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
565
566
567
  		ext2_msg(sb, KERN_ERR,
  			"error: revision level too high, "
  			"forcing read-only mode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
571
572
  		res = MS_RDONLY;
  	}
  	if (read_only)
  		return res;
  	if (!(sbi->s_mount_state & EXT2_VALID_FS))
2314b07cb   Alexey Fisher   ext2: Unify log m...
573
574
575
  		ext2_msg(sb, KERN_WARNING,
  			"warning: mounting unchecked fs, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  	else if ((sbi->s_mount_state & EXT2_ERROR_FS))
2314b07cb   Alexey Fisher   ext2: Unify log m...
577
578
579
  		ext2_msg(sb, KERN_WARNING,
  			"warning: mounting fs with errors, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
  	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
  		 le16_to_cpu(es->s_mnt_count) >=
  		 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
2314b07cb   Alexey Fisher   ext2: Unify log m...
583
584
585
  		ext2_msg(sb, KERN_WARNING,
  			"warning: maximal mount count reached, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  	else if (le32_to_cpu(es->s_checkinterval) &&
2314b07cb   Alexey Fisher   ext2: Unify log m...
587
588
589
590
591
  		(le32_to_cpu(es->s_lastcheck) +
  			le32_to_cpu(es->s_checkinterval) <= get_seconds()))
  		ext2_msg(sb, KERN_WARNING,
  			"warning: checktime reached, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
  	if (!le16_to_cpu(es->s_max_mnt_count))
  		es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
fba4d3997   Marcin Slusarz   ext2: le*_add_cpu...
594
  	le16_add_cpu(&es->s_mnt_count, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  	if (test_opt (sb, DEBUG))
2314b07cb   Alexey Fisher   ext2: Unify log m...
596
597
  		ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, fs=%lu, gc=%lu, "
  			"bpg=%lu, ipg=%lu, mo=%04lx]",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
600
601
602
603
  			EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,
  			sbi->s_frag_size,
  			sbi->s_groups_count,
  			EXT2_BLOCKS_PER_GROUP(sb),
  			EXT2_INODES_PER_GROUP(sb),
  			sbi->s_mount_opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
  	return res;
  }
197cd65ac   Akinobu Mita   ext[234]: use ext...
606
  static int ext2_check_descriptors(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
  
  	ext2_debug ("Checking group descriptors");
197cd65ac   Akinobu Mita   ext[234]: use ext...
612
613
  	for (i = 0; i < sbi->s_groups_count; i++) {
  		struct ext2_group_desc *gdp = ext2_get_group_desc(sb, i, NULL);
24097d12e   Akinobu Mita   ext2: use ext2_gr...
614
615
  		ext2_fsblk_t first_block = ext2_group_first_block_no(sb, i);
  		ext2_fsblk_t last_block;
197cd65ac   Akinobu Mita   ext[234]: use ext...
616

41f04d852   Eric Sandeen   [PATCH] ext2: fix...
617
618
619
620
621
  		if (i == sbi->s_groups_count - 1)
  			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
  		else
  			last_block = first_block +
  				(EXT2_BLOCKS_PER_GROUP(sb) - 1);
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
622
623
  		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
624
625
626
627
628
629
630
  		{
  			ext2_error (sb, "ext2_check_descriptors",
  				    "Block bitmap for group %d"
  				    " not in group (block %lu)!",
  				    i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
  			return 0;
  		}
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
631
632
  		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
633
634
635
636
637
638
639
  		{
  			ext2_error (sb, "ext2_check_descriptors",
  				    "Inode bitmap for group %d"
  				    " not in group (block %lu)!",
  				    i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
  			return 0;
  		}
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
640
  		if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
780dcdb21   Eric Sandeen   fix inode_table t...
641
  		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group - 1 >
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
642
  		    last_block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
646
647
648
649
  		{
  			ext2_error (sb, "ext2_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
650
651
652
  	}
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
657
658
659
660
  /*
   * 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 ext2_max_size(int bits)
  {
  	loff_t res = EXT2_NDIR_BLOCKS;
902be4c5e   Aneesh Kumar K.V   ext2: Fix the max...
661
662
663
664
665
  	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
666
  	 * sectors in the file, including data and all indirect blocks,
902be4c5e   Aneesh Kumar K.V   ext2: Fix the max...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
  	 * 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
686
687
688
689
690
691
692
  
  	res += 1LL << (bits-2);
  	res += 1LL << (2*(bits-2));
  	res += 1LL << (3*(bits-2));
  	res <<= bits;
  	if (res > upper_limit)
  		res = upper_limit;
902be4c5e   Aneesh Kumar K.V   ext2: Fix the max...
693
694
695
  
  	if (res > MAX_LFS_FILESIZE)
  		res = MAX_LFS_FILESIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
699
700
701
702
703
  	return res;
  }
  
  static unsigned long descriptor_loc(struct super_block *sb,
  				    unsigned long logic_sb_block,
  				    int nr)
  {
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
24097d12e   Akinobu Mita   ext2: use ext2_gr...
704
  	unsigned long bg, first_meta_bg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
  	int has_super = 0;
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707
708
709
710
711
712
713
714
  	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
  
  	if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_META_BG) ||
  	    nr < first_meta_bg)
  		return (logic_sb_block + nr + 1);
  	bg = sbi->s_desc_per_block * nr;
  	if (ext2_bg_has_super(sb, bg))
  		has_super = 1;
24097d12e   Akinobu Mita   ext2: use ext2_gr...
715
716
  
  	return ext2_group_first_block_no(sb, bg) + has_super;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
718
719
720
721
722
723
724
725
726
727
728
729
  }
  
  static int ext2_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct buffer_head * bh;
  	struct ext2_sb_info * sbi;
  	struct ext2_super_block * es;
  	struct inode *root;
  	unsigned long block;
  	unsigned long sb_block = get_sb_block(&data);
  	unsigned long logic_sb_block;
  	unsigned long offset = 0;
  	unsigned long def_mount_opts;
52fcf7032   David Howells   iget: stop EXT2 f...
730
  	long ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
733
734
  	int blocksize = BLOCK_SIZE;
  	int db_count;
  	int i, j;
  	__le32 features;
833f4077b   Peter Zijlstra   lib: percpu_count...
735
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736

db7192221   Jan Blunck   BKL: Explicitly a...
737
  	err = -ENOMEM;
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
738
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
  	if (!sbi)
db7192221   Jan Blunck   BKL: Explicitly a...
740
  		goto failed_unlock;
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
741
742
743
744
745
  
  	sbi->s_blockgroup_lock =
  		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
  	if (!sbi->s_blockgroup_lock) {
  		kfree(sbi);
db7192221   Jan Blunck   BKL: Explicitly a...
746
  		goto failed_unlock;
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
747
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  	sb->s_fs_info = sbi;
93d44cb27   Miklos Szeredi   ext2: show all mo...
749
  	sbi->s_sb_block = sb_block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750

c15271f4e   Jan Blunck   ext2: Add ext2_sb...
751
  	spin_lock_init(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
754
755
756
757
758
759
760
  	/*
  	 * See what the current blocksize for the device is, and
  	 * use that as the blocksize.  Otherwise (or if the blocksize
  	 * is smaller than the default) use the default.
  	 * This is important for devices that have a hardware
  	 * sectorsize that is larger than the default.
  	 */
  	blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
  	if (!blocksize) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
761
  		ext2_msg(sb, KERN_ERR, "error: unable to set blocksize");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
  		goto failed_sbi;
  	}
  
  	/*
  	 * If the superblock doesn't start on a hardware sector boundary,
  	 * calculate the offset.  
  	 */
  	if (blocksize != BLOCK_SIZE) {
  		logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
  		offset = (sb_block*BLOCK_SIZE) % blocksize;
  	} else {
  		logic_sb_block = sb_block;
  	}
  
  	if (!(bh = sb_bread(sb, logic_sb_block))) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
777
  		ext2_msg(sb, KERN_ERR, "error: unable to read superblock");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  		goto failed_sbi;
  	}
  	/*
  	 * Note: s_es must be initialized as soon as possible because
  	 *       some ext2 macro-instructions depend on its value
  	 */
  	es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
  	sbi->s_es = es;
  	sb->s_magic = le16_to_cpu(es->s_magic);
  
  	if (sb->s_magic != EXT2_SUPER_MAGIC)
  		goto cantfind_ext2;
  
  	/* Set defaults before we parse the mount options */
  	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
  	if (def_mount_opts & EXT2_DEFM_DEBUG)
  		set_opt(sbi->s_mount_opt, DEBUG);
  	if (def_mount_opts & EXT2_DEFM_BSDGROUPS)
  		set_opt(sbi->s_mount_opt, GRPID);
  	if (def_mount_opts & EXT2_DEFM_UID16)
  		set_opt(sbi->s_mount_opt, NO_UID32);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
799
  #ifdef CONFIG_EXT2_FS_XATTR
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
  	if (def_mount_opts & EXT2_DEFM_XATTR_USER)
  		set_opt(sbi->s_mount_opt, XATTR_USER);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
802
803
  #endif
  #ifdef CONFIG_EXT2_FS_POSIX_ACL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
805
  	if (def_mount_opts & EXT2_DEFM_ACL)
  		set_opt(sbi->s_mount_opt, POSIX_ACL);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
806
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
808
809
  	
  	if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
  		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
14e11e106   Aneesh Kumar K.V   ext2: change the ...
810
  	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
811
  		set_opt(sbi->s_mount_opt, ERRORS_CONT);
14e11e106   Aneesh Kumar K.V   ext2: change the ...
812
813
  	else
  		set_opt(sbi->s_mount_opt, ERRORS_RO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
815
816
817
  
  	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
  	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
  	
a686cd898   Martin J. Bligh   ext2 reservations
818
  	set_opt(sbi->s_mount_opt, RESERVATION);
2314b07cb   Alexey Fisher   ext2: Unify log m...
819
  	if (!parse_options((char *) data, sb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
823
824
  		goto failed_mount;
  
  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
  		((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
  		 MS_POSIXACL : 0);
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
825
826
  	ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
  				    EXT2_MOUNT_XIP if not */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
828
829
830
  	if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
  	    (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
  	     EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
  	     EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U)))
2314b07cb   Alexey Fisher   ext2: Unify log m...
831
832
833
  		ext2_msg(sb, KERN_WARNING,
  			"warning: feature flags set on rev 0 fs, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834
835
836
837
838
839
840
  	/*
  	 * 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 = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP);
  	if (features) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
841
842
843
  		ext2_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
844
845
846
847
  		goto failed_mount;
  	}
  	if (!(sb->s_flags & MS_RDONLY) &&
  	    (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
2314b07cb   Alexey Fisher   ext2: Unify log m...
848
849
850
  		ext2_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
851
852
853
854
  		goto failed_mount;
  	}
  
  	blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
a8e3eff46   Nick Piggin   ext2: xip check fix
855
  	if (ext2_use_xip(sb) && blocksize != PAGE_SIZE) {
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
856
  		if (!silent)
2314b07cb   Alexey Fisher   ext2: Unify log m...
857
858
  			ext2_msg(sb, KERN_ERR,
  				"error: unsupported blocksize for xip");
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
859
860
  		goto failed_mount;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
862
863
864
865
  	/* If the blocksize doesn't match, re-read the thing.. */
  	if (sb->s_blocksize != blocksize) {
  		brelse(bh);
  
  		if (!sb_set_blocksize(sb, blocksize)) {
4e299c1d9   Robin Dong   ext2: fix error m...
866
867
  			ext2_msg(sb, KERN_ERR,
  				"error: bad blocksize %d", blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
869
870
871
872
873
874
  			goto failed_sbi;
  		}
  
  		logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
  		offset = (sb_block*BLOCK_SIZE) % blocksize;
  		bh = sb_bread(sb, logic_sb_block);
  		if(!bh) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
875
876
  			ext2_msg(sb, KERN_ERR, "error: couldn't read"
  				"superblock on 2nd try");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
878
879
880
881
  			goto failed_sbi;
  		}
  		es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
  		sbi->s_es = es;
  		if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
882
  			ext2_msg(sb, KERN_ERR, "error: magic mismatch");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
885
886
887
888
889
890
891
892
893
894
895
  			goto failed_mount;
  		}
  	}
  
  	sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
  
  	if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
  		sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
  		sbi->s_first_ino = EXT2_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 < EXT2_GOOD_OLD_INODE_SIZE) ||
d8ea6cf89   vignesh babu   ext2/4: use is_po...
896
  		    !is_power_of_2(sbi->s_inode_size) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
  		    (sbi->s_inode_size > blocksize)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
898
899
  			ext2_msg(sb, KERN_ERR,
  				"error: unsupported inode size: %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
  				sbi->s_inode_size);
  			goto failed_mount;
  		}
  	}
  
  	sbi->s_frag_size = EXT2_MIN_FRAG_SIZE <<
  				   le32_to_cpu(es->s_log_frag_size);
  	if (sbi->s_frag_size == 0)
  		goto cantfind_ext2;
  	sbi->s_frags_per_block = sb->s_blocksize / sbi->s_frag_size;
  
  	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);
  
  	if (EXT2_INODE_SIZE(sb) == 0)
  		goto cantfind_ext2;
  	sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb);
607eb266a   Andries Brouwer   [PATCH] ext2: pre...
918
  	if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
920
921
922
923
924
925
926
  		goto cantfind_ext2;
  	sbi->s_itb_per_group = sbi->s_inodes_per_group /
  					sbi->s_inodes_per_block;
  	sbi->s_desc_per_block = sb->s_blocksize /
  					sizeof (struct ext2_group_desc);
  	sbi->s_sbh = bh;
  	sbi->s_mount_state = le16_to_cpu(es->s_state);
  	sbi->s_addr_per_block_bits =
f0d1b0b30   David Howells   [PATCH] LOG2: Imp...
927
  		ilog2 (EXT2_ADDR_PER_BLOCK(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  	sbi->s_desc_per_block_bits =
f0d1b0b30   David Howells   [PATCH] LOG2: Imp...
929
  		ilog2 (EXT2_DESC_PER_BLOCK(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
933
934
935
  
  	if (sb->s_magic != EXT2_SUPER_MAGIC)
  		goto cantfind_ext2;
  
  	if (sb->s_blocksize != bh->b_size) {
  		if (!silent)
2314b07cb   Alexey Fisher   ext2: Unify log m...
936
  			ext2_msg(sb, KERN_ERR, "error: unsupported blocksize");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
937
938
939
940
  		goto failed_mount;
  	}
  
  	if (sb->s_blocksize != sbi->s_frag_size) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
941
942
943
  		ext2_msg(sb, KERN_ERR,
  			"error: fragsize %lu != blocksize %lu"
  			"(not supported yet)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
944
945
946
947
948
  			sbi->s_frag_size, sb->s_blocksize);
  		goto failed_mount;
  	}
  
  	if (sbi->s_blocks_per_group > sb->s_blocksize * 8) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
949
950
  		ext2_msg(sb, KERN_ERR,
  			"error: #blocks per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
952
953
954
  			sbi->s_blocks_per_group);
  		goto failed_mount;
  	}
  	if (sbi->s_frags_per_group > sb->s_blocksize * 8) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
955
956
  		ext2_msg(sb, KERN_ERR,
  			"error: #fragments per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
958
959
960
  			sbi->s_frags_per_group);
  		goto failed_mount;
  	}
  	if (sbi->s_inodes_per_group > sb->s_blocksize * 8) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
961
962
  		ext2_msg(sb, KERN_ERR,
  			"error: #inodes per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
965
966
967
968
  			sbi->s_inodes_per_group);
  		goto failed_mount;
  	}
  
  	if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
  		goto cantfind_ext2;
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
969
970
971
   	sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
   				le32_to_cpu(es->s_first_data_block) - 1)
   					/ EXT2_BLOCKS_PER_GROUP(sb)) + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
974
975
  	db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
  		   EXT2_DESC_PER_BLOCK(sb);
  	sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
  	if (sbi->s_group_desc == NULL) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
976
  		ext2_msg(sb, KERN_ERR, "error: not enough memory");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
  		goto failed_mount;
  	}
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
979
  	bgl_lock_init(sbi->s_blockgroup_lock);
dd00cc486   Yoann Padioleau   some kmalloc/mems...
980
  	sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  	if (!sbi->s_debts) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
982
  		ext2_msg(sb, KERN_ERR, "error: not enough memory");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
  		goto failed_mount_group_desc;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
988
989
990
  	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]) {
  			for (j = 0; j < i; j++)
  				brelse (sbi->s_group_desc[j]);
2314b07cb   Alexey Fisher   ext2: Unify log m...
991
992
  			ext2_msg(sb, KERN_ERR,
  				"error: unable to read group descriptors");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993
994
995
996
  			goto failed_mount_group_desc;
  		}
  	}
  	if (!ext2_check_descriptors (sb)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
997
  		ext2_msg(sb, KERN_ERR, "group descriptors corrupted");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
999
1000
1001
1002
  		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...
1003

a686cd898   Martin J. Bligh   ext2 reservations
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  	/* 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 = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
  	sbi->s_rsv_window_head.rsv_end = EXT2_RESERVE_WINDOW_NOT_ALLOCATED;
  	sbi->s_rsv_window_head.rsv_alloc_hit = 0;
  	sbi->s_rsv_window_head.rsv_goal_size = 0;
  	ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);
833f4077b   Peter Zijlstra   lib: percpu_count...
1018
  	err = percpu_counter_init(&sbi->s_freeblocks_counter,
0216bfcff   Mingming Cao   [PATCH] percpu co...
1019
  				ext2_count_free_blocks(sb));
833f4077b   Peter Zijlstra   lib: percpu_count...
1020
1021
  	if (!err) {
  		err = percpu_counter_init(&sbi->s_freeinodes_counter,
0216bfcff   Mingming Cao   [PATCH] percpu co...
1022
  				ext2_count_free_inodes(sb));
833f4077b   Peter Zijlstra   lib: percpu_count...
1023
1024
1025
  	}
  	if (!err) {
  		err = percpu_counter_init(&sbi->s_dirs_counter,
0216bfcff   Mingming Cao   [PATCH] percpu co...
1026
  				ext2_count_dirs(sb));
833f4077b   Peter Zijlstra   lib: percpu_count...
1027
1028
  	}
  	if (err) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1029
  		ext2_msg(sb, KERN_ERR, "error: insufficient memory");
833f4077b   Peter Zijlstra   lib: percpu_count...
1030
1031
  		goto failed_mount3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
1033
1034
1035
1036
1037
  	/*
  	 * set up enough so that it can read an inode
  	 */
  	sb->s_op = &ext2_sops;
  	sb->s_export_op = &ext2_export_ops;
  	sb->s_xattr = ext2_xattr_handlers;
123e9caf1   Christoph Hellwig   quota: explicitly...
1038
1039
1040
  
  #ifdef CONFIG_QUOTA
  	sb->dq_op = &dquot_operations;
287a80958   Christoph Hellwig   quota: rename def...
1041
  	sb->s_qcop = &dquot_quotactl_ops;
123e9caf1   Christoph Hellwig   quota: explicitly...
1042
  #endif
52fcf7032   David Howells   iget: stop EXT2 f...
1043
1044
1045
  	root = ext2_iget(sb, EXT2_ROOT_INO);
  	if (IS_ERR(root)) {
  		ret = PTR_ERR(root);
0216bfcff   Mingming Cao   [PATCH] percpu co...
1046
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1047
1048
  	}
  	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
52fcf7032   David Howells   iget: stop EXT2 f...
1049
  		iput(root);
2314b07cb   Alexey Fisher   ext2: Unify log m...
1050
  		ext2_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
0216bfcff   Mingming Cao   [PATCH] percpu co...
1051
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052
  	}
52fcf7032   David Howells   iget: stop EXT2 f...
1053
1054
1055
1056
  
  	sb->s_root = d_alloc_root(root);
  	if (!sb->s_root) {
  		iput(root);
2314b07cb   Alexey Fisher   ext2: Unify log m...
1057
  		ext2_msg(sb, KERN_ERR, "error: get root inode failed");
52fcf7032   David Howells   iget: stop EXT2 f...
1058
1059
1060
  		ret = -ENOMEM;
  		goto failed_mount3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
  	if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2314b07cb   Alexey Fisher   ext2: Unify log m...
1062
1063
  		ext2_msg(sb, KERN_WARNING,
  			"warning: mounting ext3 filesystem as ext2");
4c96a68bf   Jan Blunck   ext2: Move ext2_w...
1064
1065
1066
  	if (ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY))
  		sb->s_flags |= MS_RDONLY;
  	ext2_write_super(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1067
1068
1069
1070
  	return 0;
  
  cantfind_ext2:
  	if (!silent)
2314b07cb   Alexey Fisher   ext2: Unify log m...
1071
1072
1073
  		ext2_msg(sb, KERN_ERR,
  			"error: can't find an ext2 filesystem on dev %s.",
  			sb->s_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
  	goto failed_mount;
0216bfcff   Mingming Cao   [PATCH] percpu co...
1075
1076
1077
1078
  failed_mount3:
  	percpu_counter_destroy(&sbi->s_freeblocks_counter);
  	percpu_counter_destroy(&sbi->s_freeinodes_counter);
  	percpu_counter_destroy(&sbi->s_dirs_counter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  failed_mount2:
  	for (i = 0; i < db_count; i++)
  		brelse(sbi->s_group_desc[i]);
  failed_mount_group_desc:
  	kfree(sbi->s_group_desc);
  	kfree(sbi->s_debts);
  failed_mount:
  	brelse(bh);
  failed_sbi:
  	sb->s_fs_info = NULL;
0f7ee7c17   Manish Katiyar   ext2: Fix memory ...
1089
  	kfree(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
  	kfree(sbi);
db7192221   Jan Blunck   BKL: Explicitly a...
1091
  failed_unlock:
52fcf7032   David Howells   iget: stop EXT2 f...
1092
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1093
  }
7bf0dc9b0   Theodore Ts'o   ext2: avoid WARN(...
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  static void ext2_clear_super_error(struct super_block *sb)
  {
  	struct buffer_head *sbh = EXT2_SB(sb)->s_sbh;
  
  	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.
  		 */
2b8120efb   Jan Blunck   ext2: Use ext2_cl...
1107
1108
1109
  		ext2_msg(sb, KERN_ERR,
  		       "previous I/O error to superblock detected
  ");
7bf0dc9b0   Theodore Ts'o   ext2: avoid WARN(...
1110
1111
1112
1113
  		clear_buffer_write_io_error(sbh);
  		set_buffer_uptodate(sbh);
  	}
  }
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
1114
1115
  static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es,
  			    int wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116
  {
7bf0dc9b0   Theodore Ts'o   ext2: avoid WARN(...
1117
  	ext2_clear_super_error(sb);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1118
  	spin_lock(&EXT2_SB(sb)->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
1120
1121
  	es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb));
  	es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb));
  	es->s_wtime = cpu_to_le32(get_seconds());
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1122
1123
  	/* unlock before we do IO */
  	spin_unlock(&EXT2_SB(sb)->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124
  	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
1125
1126
  	if (wait)
  		sync_dirty_buffer(EXT2_SB(sb)->s_sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  	sb->s_dirt = 0;
  }
  
  /*
   * In the second extended file system, it is not necessary to
   * write the super block since we use a mapping of the
   * disk super block in a buffer.
   *
   * However, this function is still used to set the fs valid
   * flags to 0.  We need to set this flag to 0 since the fs
   * may have been checked while mounted and e2fsck may have
   * set s_state to EXT2_VALID_FS after some corrections.
   */
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1140
  static int ext2_sync_fs(struct super_block *sb, int wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
  {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1142
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1143
  	struct ext2_super_block *es = EXT2_SB(sb)->s_es;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1144
  	spin_lock(&sbi->s_lock);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1145
1146
1147
1148
  	if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) {
  		ext2_debug("setting valid to 0
  ");
  		es->s_state &= cpu_to_le16(~EXT2_VALID_FS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1149
  	}
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1150
  	spin_unlock(&sbi->s_lock);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
1151
  	ext2_sync_super(sb, es, wait);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
  	return 0;
  }
  
  
  void ext2_write_super(struct super_block *sb)
  {
  	if (!(sb->s_flags & MS_RDONLY))
  		ext2_sync_fs(sb, 1);
  	else
  		sb->s_dirt = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
1164
1165
1166
1167
  }
  
  static int ext2_remount (struct super_block * sb, int * flags, char * data)
  {
  	struct ext2_sb_info * sbi = EXT2_SB(sb);
  	struct ext2_super_block * es;
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
1168
  	unsigned long old_mount_opt = sbi->s_mount_opt;
50a522342   Jan Kara   [PATCH] ext2: fix...
1169
1170
1171
  	struct ext2_mount_options old_opts;
  	unsigned long old_sb_flags;
  	int err;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1172
  	spin_lock(&sbi->s_lock);
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1173

50a522342   Jan Kara   [PATCH] ext2: fix...
1174
1175
1176
1177
1178
  	/* Store the old options */
  	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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179
1180
1181
1182
  
  	/*
  	 * Allow the "check" option to be passed as a remount option.
  	 */
2314b07cb   Alexey Fisher   ext2: Unify log m...
1183
  	if (!parse_options(data, sb)) {
50a522342   Jan Kara   [PATCH] ext2: fix...
1184
1185
1186
  		err = -EINVAL;
  		goto restore_opts;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
1188
1189
  
  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
  		((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
266f5aa09   Carsten Otte   ext2: disallow se...
1190
1191
1192
1193
  	ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
  				    EXT2_MOUNT_XIP if not */
  
  	if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1194
1195
  		ext2_msg(sb, KERN_WARNING,
  			"warning: unsupported blocksize for xip");
ddc80bd78   Andrew Morton   ext2: fix return ...
1196
  		err = -EINVAL;
266f5aa09   Carsten Otte   ext2: disallow se...
1197
1198
  		goto restore_opts;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1199
  	es = sbi->s_es;
8e3b9a072   Al Viro   ext2_remount: don...
1200
  	if ((sbi->s_mount_opt ^ old_mount_opt) & EXT2_MOUNT_XIP) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1201
1202
  		ext2_msg(sb, KERN_WARNING, "warning: refusing change of "
  			 "xip flag with busy inodes while remounting");
0e4a9b592   Carsten Otte   ext2/xip: refuse ...
1203
1204
1205
  		sbi->s_mount_opt &= ~EXT2_MOUNT_XIP;
  		sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP;
  	}
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1206
  	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1207
  		spin_unlock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208
  		return 0;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1209
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
1211
  	if (*flags & MS_RDONLY) {
  		if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1212
  		    !(sbi->s_mount_state & EXT2_VALID_FS)) {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1213
  			spin_unlock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
  			return 0;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1215
  		}
c79d967de   Christoph Hellwig   quota: move remou...
1216

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
1218
1219
1220
1221
1222
  		/*
  		 * OK, we are remounting a valid rw partition rdonly, so set
  		 * the rdonly flag and then mark the partition as valid again.
  		 */
  		es->s_state = cpu_to_le16(sbi->s_mount_state);
  		es->s_mtime = cpu_to_le32(get_seconds());
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1223
  		spin_unlock(&sbi->s_lock);
c79d967de   Christoph Hellwig   quota: move remou...
1224

0f0dd62fd   Christoph Hellwig   quota: kill the v...
1225
1226
  		err = dquot_suspend(sb, -1);
  		if (err < 0) {
c79d967de   Christoph Hellwig   quota: move remou...
1227
1228
1229
  			spin_lock(&sbi->s_lock);
  			goto restore_opts;
  		}
4c96a68bf   Jan Blunck   ext2: Move ext2_w...
1230
  		ext2_sync_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231
1232
1233
1234
  	} else {
  		__le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
  					       ~EXT2_FEATURE_RO_COMPAT_SUPP);
  		if (ret) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1235
1236
1237
1238
  			ext2_msg(sb, KERN_WARNING,
  				"warning: couldn't remount RDWR because of "
  				"unsupported optional features (%x).",
  				le32_to_cpu(ret));
50a522342   Jan Kara   [PATCH] ext2: fix...
1239
1240
  			err = -EROFS;
  			goto restore_opts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241
1242
1243
1244
1245
1246
1247
1248
1249
  		}
  		/*
  		 * 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.)
  		 */
  		sbi->s_mount_state = le16_to_cpu(es->s_state);
  		if (!ext2_setup_super (sb, es, 0))
  			sb->s_flags &= ~MS_RDONLY;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1250
  		spin_unlock(&sbi->s_lock);
c79d967de   Christoph Hellwig   quota: move remou...
1251

4c96a68bf   Jan Blunck   ext2: Move ext2_w...
1252
  		ext2_write_super(sb);
c79d967de   Christoph Hellwig   quota: move remou...
1253

0f0dd62fd   Christoph Hellwig   quota: kill the v...
1254
  		dquot_resume(sb, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1255
  	}
c79d967de   Christoph Hellwig   quota: move remou...
1256

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
  	return 0;
50a522342   Jan Kara   [PATCH] ext2: fix...
1258
1259
1260
1261
1262
  restore_opts:
  	sbi->s_mount_opt = old_opts.s_mount_opt;
  	sbi->s_resuid = old_opts.s_resuid;
  	sbi->s_resgid = old_opts.s_resgid;
  	sb->s_flags = old_sb_flags;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1263
  	spin_unlock(&sbi->s_lock);
50a522342   Jan Kara   [PATCH] ext2: fix...
1264
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
  }
726c33422   David Howells   [PATCH] VFS: Perm...
1266
  static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
  {
726c33422   David Howells   [PATCH] VFS: Perm...
1268
  	struct super_block *sb = dentry->d_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1270
  	struct ext2_super_block *es = sbi->s_es;
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1271
  	u64 fsid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272

c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1273
  	spin_lock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
  	if (test_opt (sb, MINIX_DF))
2235219b7   Badari Pulavarty   ext2: statfs spee...
1275
1276
1277
1278
  		sbi->s_overhead_last = 0;
  	else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
  		unsigned long i, overhead = 0;
  		smp_rmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279
  		/*
2235219b7   Badari Pulavarty   ext2: statfs spee...
1280
1281
1282
  		 * 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
1283
1284
1285
1286
1287
1288
  		 */
  
  		/*
  		 * All of the blocks before first_data_block are
  		 * overhead
  		 */
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1289
  		overhead = le32_to_cpu(es->s_first_data_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
  
  		/*
  		 * 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 < sbi->s_groups_count; i++)
  			overhead += ext2_bg_has_super(sb, i) +
  				ext2_bg_num_gdb(sb, i);
  
  		/*
  		 * Every block group has an inode bitmap, a block
  		 * bitmap, and an inode table.
  		 */
  		overhead += (sbi->s_groups_count *
  			     (2 + sbi->s_itb_per_group));
2235219b7   Badari Pulavarty   ext2: statfs spee...
1306
1307
1308
  		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
1309
1310
1311
1312
  	}
  
  	buf->f_type = EXT2_SUPER_MAGIC;
  	buf->f_bsize = sb->s_blocksize;
2235219b7   Badari Pulavarty   ext2: statfs spee...
1313
  	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
  	buf->f_bfree = ext2_count_free_blocks(sb);
2235219b7   Badari Pulavarty   ext2: statfs spee...
1315
  	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1316
1317
  	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))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  		buf->f_bavail = 0;
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1319
1320
  	buf->f_files = le32_to_cpu(es->s_inodes_count);
  	buf->f_ffree = ext2_count_free_inodes(sb);
2235219b7   Badari Pulavarty   ext2: statfs spee...
1321
  	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1322
  	buf->f_namelen = EXT2_NAME_LEN;
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1323
1324
1325
1326
  	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;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1327
  	spin_unlock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
  	return 0;
  }
152a08366   Al Viro   new helper: mount...
1330
1331
  static struct dentry *ext2_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1332
  {
152a08366   Al Viro   new helper: mount...
1333
  	return mount_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
1335
1336
1337
1338
1339
  }
  
  #ifdef CONFIG_QUOTA
  
  /* Read data from quotafile - avoid pagecache and such because we cannot afford
   * acquiring the locks... As quota files are never truncated and quota code
25985edce   Lucas De Marchi   Fix common misspe...
1340
   * itself serializes the operations (and no one else should touch the files)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
   * we don't have to be afraid of races */
  static ssize_t ext2_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 >> EXT2_BLOCK_SIZE_BITS(sb);
  	int err = 0;
  	int offset = off & (sb->s_blocksize - 1);
  	int tocopy;
  	size_t toread;
  	struct buffer_head tmp_bh;
  	struct buffer_head *bh;
  	loff_t i_size = i_size_read(inode);
  
  	if (off > i_size)
  		return 0;
  	if (off+len > i_size)
  		len = i_size-off;
  	toread = len;
  	while (toread > 0) {
  		tocopy = sb->s_blocksize - offset < toread ?
  				sb->s_blocksize - offset : toread;
  
  		tmp_bh.b_state = 0;
c16831b4c   Manish Katiyar   ext2: Zero our b_...
1365
  		tmp_bh.b_size = sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
  		err = ext2_get_block(inode, blk, &tmp_bh, 0);
a686cd898   Martin J. Bligh   ext2 reservations
1367
  		if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
  			return err;
  		if (!buffer_mapped(&tmp_bh))	/* A hole? */
  			memset(data, 0, tocopy);
  		else {
  			bh = sb_bread(sb, tmp_bh.b_blocknr);
  			if (!bh)
  				return -EIO;
  			memcpy(data, bh->b_data+offset, tocopy);
  			brelse(bh);
  		}
  		offset = 0;
  		toread -= tocopy;
  		data += tocopy;
  		blk++;
  	}
  	return len;
  }
  
  /* Write to quotafile */
  static ssize_t ext2_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 >> EXT2_BLOCK_SIZE_BITS(sb);
  	int err = 0;
  	int offset = off & (sb->s_blocksize - 1);
  	int tocopy;
  	size_t towrite = len;
  	struct buffer_head tmp_bh;
  	struct buffer_head *bh;
5c81a4197   Arjan van de Ven   [PATCH] lockdep: ...
1398
  	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399
1400
1401
1402
1403
1404
  	while (towrite > 0) {
  		tocopy = sb->s_blocksize - offset < towrite ?
  				sb->s_blocksize - offset : towrite;
  
  		tmp_bh.b_state = 0;
  		err = ext2_get_block(inode, blk, &tmp_bh, 1);
a686cd898   Martin J. Bligh   ext2 reservations
1405
  		if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
  			goto out;
  		if (offset || tocopy != EXT2_BLOCK_SIZE(sb))
  			bh = sb_bread(sb, tmp_bh.b_blocknr);
  		else
  			bh = sb_getblk(sb, tmp_bh.b_blocknr);
  		if (!bh) {
  			err = -EIO;
  			goto out;
  		}
  		lock_buffer(bh);
  		memcpy(bh->b_data+offset, data, tocopy);
  		flush_dcache_page(bh->b_page);
  		set_buffer_uptodate(bh);
  		mark_buffer_dirty(bh);
  		unlock_buffer(bh);
  		brelse(bh);
  		offset = 0;
  		towrite -= tocopy;
  		data += tocopy;
  		blk++;
  	}
  out:
a069e9cee   Dan Carpenter   ext2: missing unl...
1428
1429
  	if (len == towrite) {
  		mutex_unlock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
  		return err;
a069e9cee   Dan Carpenter   ext2: missing unl...
1431
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432
1433
1434
1435
1436
  	if (inode->i_size < off+len-towrite)
  		i_size_write(inode, off+len-towrite);
  	inode->i_version++;
  	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  	mark_inode_dirty(inode);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
1437
  	mutex_unlock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
1440
1441
1442
1443
1444
1445
  	return len - towrite;
  }
  
  #endif
  
  static struct file_system_type ext2_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "ext2",
152a08366   Al Viro   new helper: mount...
1446
  	.mount		= ext2_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
  
  static int __init init_ext2_fs(void)
  {
  	int err = init_ext2_xattr();
  	if (err)
  		return err;
  	err = init_inodecache();
  	if (err)
  		goto out1;
          err = register_filesystem(&ext2_fs_type);
  	if (err)
  		goto out;
  	return 0;
  out:
  	destroy_inodecache();
  out1:
  	exit_ext2_xattr();
  	return err;
  }
  
  static void __exit exit_ext2_fs(void)
  {
  	unregister_filesystem(&ext2_fs_type);
  	destroy_inodecache();
  	exit_ext2_xattr();
  }
302bf2f32   Paul Gortmaker   ext2/3/4: delete ...
1476
1477
1478
  MODULE_AUTHOR("Remy Card and others");
  MODULE_DESCRIPTION("Second Extended Filesystem");
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
1480
  module_init(init_ext2_fs)
  module_exit(exit_ext2_fs)