Blame view

fs/ext2/super.c 42.4 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
37
38
  #include <asm/uaccess.h>
  #include "ext2.h"
  #include "xattr.h"
  #include "acl.h"
  
  static void ext2_sync_super(struct super_block *sb,
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
39
  			    struct ext2_super_block *es, int wait);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  static int ext2_remount (struct super_block * sb, int * flags, char * data);
726c33422   David Howells   [PATCH] VFS: Perm...
41
  static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
42
  static int ext2_sync_fs(struct super_block *sb, int wait);
1e8b212fe   Jan Kara   ext2: Implement f...
43
44
  static int ext2_freeze(struct super_block *sb);
  static int ext2_unfreeze(struct super_block *sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
46
47
  void ext2_error(struct super_block *sb, const char *function,
  		const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
  {
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
49
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
  	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...
55
  		spin_lock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  		sbi->s_mount_state |= EXT2_ERROR_FS;
31f68e130   Marcin Slusarz   ext2: convert byt...
57
  		es->s_state |= cpu_to_le16(EXT2_ERROR_FS);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
58
  		spin_unlock(&sbi->s_lock);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
59
  		ext2_sync_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  	}
  
  	va_start(args, fmt);
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
63
64
65
66
67
68
69
  
  	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
70
71
72
  	va_end(args);
  
  	if (test_opt(sb, ERRORS_PANIC))
2314b07cb   Alexey Fisher   ext2: Unify log m...
73
74
  		panic("EXT2-fs: panic from previous error
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  	if (test_opt(sb, ERRORS_RO)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
76
77
  		ext2_msg(sb, KERN_CRIT,
  			     "error: remounting filesystem read-only");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
  		sb->s_flags |= MS_RDONLY;
  	}
  }
2314b07cb   Alexey Fisher   ext2: Unify log m...
81
82
  void ext2_msg(struct super_block *sb, const char *prefix,
  		const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  {
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
84
  	struct va_format vaf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
  	va_list args;
  
  	va_start(args, fmt);
23a2ad6d0   Joe Perches   fs/ext2/super.c: ...
88
89
90
91
92
93
  
  	vaf.fmt = fmt;
  	vaf.va = &args;
  
  	printk("%sEXT2-fs (%s): %pV
  ", prefix, sb->s_id, &vaf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
  	va_end(args);
  }
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
96
97
98
  /*
   * This must be called with sbi->s_lock held.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
101
102
103
104
  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...
105
106
107
  	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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  		     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...
128
  	dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
be0726d33   Jan Kara   ext2: convert to ...
129
130
131
132
  	if (sbi->s_mb_cache) {
  		ext2_xattr_destroy_cache(sbi->s_mb_cache);
  		sbi->s_mb_cache = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
  	if (!(sb->s_flags & MS_RDONLY)) {
  		struct ext2_super_block *es = sbi->s_es;
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
135
  		spin_lock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  		es->s_state = cpu_to_le16(sbi->s_mount_state);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
137
  		spin_unlock(&sbi->s_lock);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
138
  		ext2_sync_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
146
147
148
149
150
  	}
  	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 ->...
151
  	kfree(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  	kfree(sbi);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
154
  static struct kmem_cache * ext2_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
  
  static struct inode *ext2_alloc_inode(struct super_block *sb)
  {
  	struct ext2_inode_info *ei;
e625b310e   Himangi Saraogi   fs/ext2/super.c: ...
159
  	ei = kmem_cache_alloc(ext2_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
  	if (!ei)
  		return NULL;
a686cd898   Martin J. Bligh   ext2 reservations
162
  	ei->i_block_alloc_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  	ei->vfs_inode.i_version = 1;
64241118b   Jan Kara   ext2: Convert to ...
164
165
166
  #ifdef CONFIG_QUOTA
  	memset(&ei->i_dquot, 0, sizeof(ei->i_dquot));
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
169
  static void ext2_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
171
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
  	kmem_cache_free(ext2_inode_cachep, EXT2_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
174
175
176
177
  static void ext2_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, ext2_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
178
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
  {
  	struct ext2_inode_info *ei = (struct ext2_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
181
  	rwlock_init(&ei->i_meta_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  #ifdef CONFIG_EXT2_FS_XATTR
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
183
  	init_rwsem(&ei->xattr_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
  #endif
a686cd898   Martin J. Bligh   ext2 reservations
185
  	mutex_init(&ei->truncate_mutex);
5726b27b0   Ross Zwisler   ext2: Add locking...
186
187
188
  #ifdef CONFIG_FS_DAX
  	init_rwsem(&ei->dax_sem);
  #endif
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
189
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
191

0903353a1   Fabian Frederick   ext2: Add __init ...
192
  static int __init init_inodecache(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
  {
  	ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
  					     sizeof(struct ext2_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
196
  					     0, (SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
197
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
20c2df83d   Paul Mundt   mm: Remove slab d...
198
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
205
  	if (ext2_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
206
207
208
209
210
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
211
  	kmem_cache_destroy(ext2_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  }
34c80b1d9   Al Viro   vfs: switch ->sho...
213
  static int ext2_show_options(struct seq_file *seq, struct dentry *root)
8fc2751be   Mark Bellon   [PATCH] disk quot...
214
  {
34c80b1d9   Al Viro   vfs: switch ->sho...
215
  	struct super_block *sb = root->d_sb;
93d44cb27   Miklos Szeredi   ext2: show all mo...
216
217
218
  	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...
219

c15271f4e   Jan Blunck   ext2: Add ext2_sb...
220
  	spin_lock(&sbi->s_lock);
93d44cb27   Miklos Szeredi   ext2: show all mo...
221
222
223
224
225
226
227
  	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...
228
  		seq_puts(seq, ",grpid");
93d44cb27   Miklos Szeredi   ext2: show all mo...
229
230
  	if (!test_opt(sb, GRPID) && (def_mount_opts & EXT2_DEFM_BSDGROUPS))
  		seq_puts(seq, ",nogrpid");
b8a9f9e18   Eric W. Biederman   userns: Convert e...
231
  	if (!uid_eq(sbi->s_resuid, make_kuid(&init_user_ns, EXT2_DEF_RESUID)) ||
93d44cb27   Miklos Szeredi   ext2: show all mo...
232
  	    le16_to_cpu(es->s_def_resuid) != EXT2_DEF_RESUID) {
b8a9f9e18   Eric W. Biederman   userns: Convert e...
233
234
  		seq_printf(seq, ",resuid=%u",
  				from_kuid_munged(&init_user_ns, sbi->s_resuid));
93d44cb27   Miklos Szeredi   ext2: show all mo...
235
  	}
b8a9f9e18   Eric W. Biederman   userns: Convert e...
236
  	if (!gid_eq(sbi->s_resgid, make_kgid(&init_user_ns, EXT2_DEF_RESGID)) ||
93d44cb27   Miklos Szeredi   ext2: show all mo...
237
  	    le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) {
b8a9f9e18   Eric W. Biederman   userns: Convert e...
238
239
  		seq_printf(seq, ",resgid=%u",
  				from_kgid_munged(&init_user_ns, sbi->s_resgid));
93d44cb27   Miklos Szeredi   ext2: show all mo...
240
  	}
14e11e106   Aneesh Kumar K.V   ext2: change the ...
241
  	if (test_opt(sb, ERRORS_RO)) {
93d44cb27   Miklos Szeredi   ext2: show all mo...
242
243
244
  		int def_errors = le16_to_cpu(es->s_errors);
  
  		if (def_errors == EXT2_ERRORS_PANIC ||
14e11e106   Aneesh Kumar K.V   ext2: change the ...
245
246
  		    def_errors == EXT2_ERRORS_CONTINUE) {
  			seq_puts(seq, ",errors=remount-ro");
93d44cb27   Miklos Szeredi   ext2: show all mo...
247
248
  		}
  	}
14e11e106   Aneesh Kumar K.V   ext2: change the ...
249
250
  	if (test_opt(sb, ERRORS_CONT))
  		seq_puts(seq, ",errors=continue");
93d44cb27   Miklos Szeredi   ext2: show all mo...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  	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...
278
279
280
281
282
283
284
285
  
  #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
6cd176a51   Matthew Wilcox   vfs,ext2: remove ...
286
  #ifdef CONFIG_FS_DAX
835417967   Carsten Otte   [PATCH] ext2: pri...
287
288
  	if (sbi->s_mount_opt & EXT2_MOUNT_XIP)
  		seq_puts(seq, ",xip");
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
289
290
  	if (sbi->s_mount_opt & EXT2_MOUNT_DAX)
  		seq_puts(seq, ",dax");
835417967   Carsten Otte   [PATCH] ext2: pri...
291
  #endif
35c879dc3   Miklos Szeredi   mount options: fi...
292
293
  	if (!test_opt(sb, RESERVATION))
  		seq_puts(seq, ",noreservation");
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
294
  	spin_unlock(&sbi->s_lock);
8fc2751be   Mark Bellon   [PATCH] disk quot...
295
296
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
  #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);
64241118b   Jan Kara   ext2: Convert to ...
300
301
302
303
  static struct dquot **ext2_get_dquots(struct inode *inode)
  {
  	return EXT2_I(inode)->i_dquot;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  #endif
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
305
  static const struct super_operations ext2_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
  	.alloc_inode	= ext2_alloc_inode,
  	.destroy_inode	= ext2_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  	.write_inode	= ext2_write_inode,
72edc4d08   Al Viro   merge ext2 delete...
309
  	.evict_inode	= ext2_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  	.put_super	= ext2_put_super,
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
311
  	.sync_fs	= ext2_sync_fs,
1e8b212fe   Jan Kara   ext2: Implement f...
312
313
  	.freeze_fs	= ext2_freeze,
  	.unfreeze_fs	= ext2_unfreeze,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
315
  	.statfs		= ext2_statfs,
  	.remount_fs	= ext2_remount,
8fc2751be   Mark Bellon   [PATCH] disk quot...
316
  	.show_options	= ext2_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
  #ifdef CONFIG_QUOTA
  	.quota_read	= ext2_quota_read,
  	.quota_write	= ext2_quota_write,
64241118b   Jan Kara   ext2: Convert to ...
320
  	.get_dquots	= ext2_get_dquots,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
  #endif
  };
2e4c68e30   Christoph Hellwig   ext2: new export ops
323
324
  static struct inode *ext2_nfs_get_inode(struct super_block *sb,
  		u64 ino, u32 generation)
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
325
  {
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
326
  	struct inode *inode;
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
327
328
329
330
331
  
  	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...
332
333
334
335
  	/*
  	 * 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...
336
  	 */
52fcf7032   David Howells   iget: stop EXT2 f...
337
338
339
340
  	inode = ext2_iget(sb, ino);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
  	if (generation && inode->i_generation != generation) {
ecaff756f   NeilBrown   [PATCH] knfsd: Ha...
341
342
343
344
  		/* we didn't find the right inode.. */
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
2e4c68e30   Christoph Hellwig   ext2: new export ops
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  	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...
360
  }
396551644   Christoph Hellwig   exportfs: make st...
361
  static const struct export_operations ext2_export_ops = {
2e4c68e30   Christoph Hellwig   ext2: new export ops
362
363
  	.fh_to_dentry = ext2_fh_to_dentry,
  	.fh_to_parent = ext2_fh_to_parent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  	.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...
390
  	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic,
2860b733f   Adrian Bunk   [PATCH] remove CO...
391
  	Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug,
8fc2751be   Mark Bellon   [PATCH] disk quot...
392
  	Opt_oldalloc, Opt_orlov, Opt_nobh, Opt_user_xattr, Opt_nouser_xattr,
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
393
  	Opt_acl, Opt_noacl, Opt_xip, Opt_dax, Opt_ignore, Opt_err, Opt_quota,
a686cd898   Martin J. Bligh   ext2 reservations
394
  	Opt_usrquota, Opt_grpquota, Opt_reservation, Opt_noreservation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
396
  static const match_table_t tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  	{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
412
413
414
415
416
417
418
419
  	{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...
420
  	{Opt_xip, "xip"},
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
421
  	{Opt_dax, "dax"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
422
  	{Opt_grpquota, "grpquota"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  	{Opt_ignore, "noquota"},
8fc2751be   Mark Bellon   [PATCH] disk quot...
424
425
  	{Opt_quota, "quota"},
  	{Opt_usrquota, "usrquota"},
a686cd898   Martin J. Bligh   ext2 reservations
426
427
  	{Opt_reservation, "reservation"},
  	{Opt_noreservation, "noreservation"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
  	{Opt_err, NULL}
  };
2314b07cb   Alexey Fisher   ext2: Unify log m...
430
  static int parse_options(char *options, struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  {
2314b07cb   Alexey Fisher   ext2: Unify log m...
432
433
  	char *p;
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  	substring_t args[MAX_OPT_ARGS];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  	int option;
b8a9f9e18   Eric W. Biederman   userns: Convert e...
436
437
  	kuid_t uid;
  	kgid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  
  	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;
b8a9f9e18   Eric W. Biederman   userns: Convert e...
464
465
466
  			uid = make_kuid(current_user_ns(), option);
  			if (!uid_valid(uid)) {
  				ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
ae2cf4284   Zhao Hongjiang   ext2: fix return ...
467
  				return 0;
b8a9f9e18   Eric W. Biederman   userns: Convert e...
468
469
470
  
  			}
  			sbi->s_resuid = uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471
472
473
474
  			break;
  		case Opt_resgid:
  			if (match_int(&args[0], &option))
  				return 0;
b8a9f9e18   Eric W. Biederman   userns: Convert e...
475
476
477
  			gid = make_kgid(current_user_ns(), option);
  			if (!gid_valid(gid)) {
  				ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
ae2cf4284   Zhao Hongjiang   ext2: fix return ...
478
  				return 0;
b8a9f9e18   Eric W. Biederman   userns: Convert e...
479
480
  			}
  			sbi->s_resgid = gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
  			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...
487
488
489
  			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
490
491
  			break;
  		case Opt_err_ro:
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
492
493
494
  			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
495
496
  			break;
  		case Opt_err_cont:
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
497
498
499
  			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
500
501
502
503
  			break;
  		case Opt_nouid32:
  			set_opt (sbi->s_mount_opt, NO_UID32);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
  		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...
529
530
  			ext2_msg(sb, KERN_INFO, "(no)user_xattr options"
  				"not supported");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
534
535
536
537
538
539
540
541
542
  			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...
543
544
  			ext2_msg(sb, KERN_INFO,
  				"(no)acl options not supported");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
  			break;
  #endif
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
547
  		case Opt_xip:
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
548
549
550
551
  			ext2_msg(sb, KERN_INFO, "use dax instead of xip");
  			set_opt(sbi->s_mount_opt, XIP);
  			/* Fall through */
  		case Opt_dax:
6cd176a51   Matthew Wilcox   vfs,ext2: remove ...
552
  #ifdef CONFIG_FS_DAX
ef83b6e8f   Dan Williams   ext2, ext4: warn ...
553
554
  			ext2_msg(sb, KERN_WARNING,
  		"DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
555
  			set_opt(sbi->s_mount_opt, DAX);
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
556
  #else
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
557
  			ext2_msg(sb, KERN_INFO, "dax option not supported");
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
558
559
  #endif
  			break;
8fc2751be   Mark Bellon   [PATCH] disk quot...
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  
  #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...
574
575
  			ext2_msg(sb, KERN_INFO,
  				"quota operations not supported");
8fc2751be   Mark Bellon   [PATCH] disk quot...
576
577
  			break;
  #endif
a686cd898   Martin J. Bligh   ext2 reservations
578
579
  		case Opt_reservation:
  			set_opt(sbi->s_mount_opt, RESERVATION);
2314b07cb   Alexey Fisher   ext2: Unify log m...
580
  			ext2_msg(sb, KERN_INFO, "reservations ON");
a686cd898   Martin J. Bligh   ext2 reservations
581
582
583
  			break;
  		case Opt_noreservation:
  			clear_opt(sbi->s_mount_opt, RESERVATION);
2314b07cb   Alexey Fisher   ext2: Unify log m...
584
  			ext2_msg(sb, KERN_INFO, "reservations OFF");
a686cd898   Martin J. Bligh   ext2 reservations
585
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
589
590
591
  		case Opt_ignore:
  			break;
  		default:
  			return 0;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
594
595
596
597
598
599
600
601
602
  	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...
603
604
605
  		ext2_msg(sb, KERN_ERR,
  			"error: revision level too high, "
  			"forcing read-only mode");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
608
609
610
  		res = MS_RDONLY;
  	}
  	if (read_only)
  		return res;
  	if (!(sbi->s_mount_state & EXT2_VALID_FS))
2314b07cb   Alexey Fisher   ext2: Unify log m...
611
612
613
  		ext2_msg(sb, KERN_WARNING,
  			"warning: mounting unchecked fs, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
  	else if ((sbi->s_mount_state & EXT2_ERROR_FS))
2314b07cb   Alexey Fisher   ext2: Unify log m...
615
616
617
  		ext2_msg(sb, KERN_WARNING,
  			"warning: mounting fs with errors, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
620
  	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...
621
622
623
  		ext2_msg(sb, KERN_WARNING,
  			"warning: maximal mount count reached, "
  			"running e2fsck is recommended");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  	else if (le32_to_cpu(es->s_checkinterval) &&
2314b07cb   Alexey Fisher   ext2: Unify log m...
625
626
627
628
629
  		(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
630
631
  	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...
632
  	le16_add_cpu(&es->s_mnt_count, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
  	if (test_opt (sb, DEBUG))
2314b07cb   Alexey Fisher   ext2: Unify log m...
634
635
  		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
636
637
638
639
640
641
  			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
642
643
  	return res;
  }
197cd65ac   Akinobu Mita   ext[234]: use ext...
644
  static int ext2_check_descriptors(struct super_block *sb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
  {
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
  
  	ext2_debug ("Checking group descriptors");
197cd65ac   Akinobu Mita   ext[234]: use ext...
650
651
  	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...
652
653
  		ext2_fsblk_t first_block = ext2_group_first_block_no(sb, i);
  		ext2_fsblk_t last_block;
197cd65ac   Akinobu Mita   ext[234]: use ext...
654

41f04d852   Eric Sandeen   [PATCH] ext2: fix...
655
656
657
658
659
  		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...
660
661
  		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
662
663
664
665
666
667
668
  		{
  			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...
669
670
  		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
671
672
673
674
675
676
677
  		{
  			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...
678
  		if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
780dcdb21   Eric Sandeen   fix inode_table t...
679
  		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group - 1 >
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
680
  		    last_block)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
685
686
687
  		{
  			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
688
689
690
  	}
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
695
696
697
698
  /*
   * 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...
699
700
701
702
703
  	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
704
  	 * sectors in the file, including data and all indirect blocks,
902be4c5e   Aneesh Kumar K.V   ext2: Fix the max...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
  	 * 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
724
725
726
727
728
729
730
  
  	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...
731
732
733
  
  	if (res > MAX_LFS_FILESIZE)
  		res = MAX_LFS_FILESIZE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
740
741
  	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...
742
  	unsigned long bg, first_meta_bg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743
744
  	int has_super = 0;
  	
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
747
748
749
750
751
752
  	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...
753
754
  
  	return ext2_group_first_block_no(sb, bg) + has_super;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
756
757
758
759
760
761
762
763
764
765
766
767
  }
  
  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...
768
  	long ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
771
772
  	int blocksize = BLOCK_SIZE;
  	int db_count;
  	int i, j;
  	__le32 features;
833f4077b   Peter Zijlstra   lib: percpu_count...
773
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774

db7192221   Jan Blunck   BKL: Explicitly a...
775
  	err = -ENOMEM;
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
776
  	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
  	if (!sbi)
e124a3204   Wanlong Gao   ext2: cleanup the...
778
  		goto failed;
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
779
780
781
782
783
  
  	sbi->s_blockgroup_lock =
  		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
  	if (!sbi->s_blockgroup_lock) {
  		kfree(sbi);
e124a3204   Wanlong Gao   ext2: cleanup the...
784
  		goto failed;
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
785
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
  	sb->s_fs_info = sbi;
93d44cb27   Miklos Szeredi   ext2: show all mo...
787
  	sbi->s_sb_block = sb_block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788

c15271f4e   Jan Blunck   ext2: Add ext2_sb...
789
  	spin_lock_init(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
791
792
793
794
795
796
797
798
  	/*
  	 * 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...
799
  		ext2_msg(sb, KERN_ERR, "error: unable to set blocksize");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
  		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...
815
  		ext2_msg(sb, KERN_ERR, "error: unable to read superblock");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  		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...
837
  #ifdef CONFIG_EXT2_FS_XATTR
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
  	if (def_mount_opts & EXT2_DEFM_XATTR_USER)
  		set_opt(sbi->s_mount_opt, XATTR_USER);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
840
841
  #endif
  #ifdef CONFIG_EXT2_FS_POSIX_ACL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
843
  	if (def_mount_opts & EXT2_DEFM_ACL)
  		set_opt(sbi->s_mount_opt, POSIX_ACL);
2e7842b88   Hugh Dickins   [PATCH] fix umask...
844
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
847
  	
  	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 ...
848
  	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
5a2b4062f   Vasily Averin   [PATCH] ext2: err...
849
  		set_opt(sbi->s_mount_opt, ERRORS_CONT);
14e11e106   Aneesh Kumar K.V   ext2: change the ...
850
851
  	else
  		set_opt(sbi->s_mount_opt, ERRORS_RO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852

b8a9f9e18   Eric W. Biederman   userns: Convert e...
853
854
  	sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid));
  	sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  	
a686cd898   Martin J. Bligh   ext2 reservations
856
  	set_opt(sbi->s_mount_opt, RESERVATION);
2314b07cb   Alexey Fisher   ext2: Unify log m...
857
  	if (!parse_options((char *) data, sb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
859
860
861
862
  		goto failed_mount;
  
  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
  		((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
  		 MS_POSIXACL : 0);
46b15caa7   Tejun Heo   vfs, writeback: r...
863
  	sb->s_iflags |= SB_I_CGROUPWB;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
867
868
  
  	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...
869
870
871
  		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
872
873
874
875
876
877
878
  	/*
  	 * 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...
879
880
881
  		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
882
883
884
885
  		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...
886
887
888
  		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
889
890
891
892
  		goto failed_mount;
  	}
  
  	blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
893
  	if (sbi->s_mount_opt & EXT2_MOUNT_DAX) {
284854be2   Toshi Kani   ext2: Add alignme...
894
895
  		err = bdev_dax_supported(sb, blocksize);
  		if (err)
0de4830fd   Matthew Wilcox   ext2: remove ext2...
896
  			goto failed_mount;
6d79125bb   Carsten Otte   [PATCH] xip: ext2...
897
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
898
899
900
901
902
  	/* 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...
903
904
  			ext2_msg(sb, KERN_ERR,
  				"error: bad blocksize %d", blocksize);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
908
909
910
911
  			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...
912
913
  			ext2_msg(sb, KERN_ERR, "error: couldn't read"
  				"superblock on 2nd try");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
916
917
918
  			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...
919
  			ext2_msg(sb, KERN_ERR, "error: magic mismatch");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
921
922
923
924
  			goto failed_mount;
  		}
  	}
  
  	sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
8de527787   Al Viro   vfs: check i_nlin...
925
  	sb->s_max_links = EXT2_LINK_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
927
928
929
930
931
932
933
  
  	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...
934
  		    !is_power_of_2(sbi->s_inode_size) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
935
  		    (sbi->s_inode_size > blocksize)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
936
937
  			ext2_msg(sb, KERN_ERR,
  				"error: unsupported inode size: %d",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
  				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...
956
  	if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
958
959
960
961
962
963
964
  		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...
965
  		ilog2 (EXT2_ADDR_PER_BLOCK(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
  	sbi->s_desc_per_block_bits =
f0d1b0b30   David Howells   [PATCH] LOG2: Imp...
967
  		ilog2 (EXT2_DESC_PER_BLOCK(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
969
970
971
972
973
  
  	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...
974
  			ext2_msg(sb, KERN_ERR, "error: unsupported blocksize");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
977
978
  		goto failed_mount;
  	}
  
  	if (sb->s_blocksize != sbi->s_frag_size) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
979
980
981
  		ext2_msg(sb, KERN_ERR,
  			"error: fragsize %lu != blocksize %lu"
  			"(not supported yet)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982
983
984
985
986
  			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...
987
988
  		ext2_msg(sb, KERN_ERR,
  			"error: #blocks per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
990
991
992
  			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...
993
994
  		ext2_msg(sb, KERN_ERR,
  			"error: #fragments per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995
996
997
998
  			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...
999
1000
  		ext2_msg(sb, KERN_ERR,
  			"error: #inodes per group too big: %lu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1001
1002
1003
1004
1005
1006
  			sbi->s_inodes_per_group);
  		goto failed_mount;
  	}
  
  	if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
  		goto cantfind_ext2;
41f04d852   Eric Sandeen   [PATCH] ext2: fix...
1007
1008
1009
   	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
1010
1011
1012
1013
  	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...
1014
  		ext2_msg(sb, KERN_ERR, "error: not enough memory");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
  		goto failed_mount;
  	}
18a82eb9f   Pekka J Enberg   ext2: allocate ->...
1017
  	bgl_lock_init(sbi->s_blockgroup_lock);
dd00cc486   Yoann Padioleau   some kmalloc/mems...
1018
  	sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  	if (!sbi->s_debts) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1020
  		ext2_msg(sb, KERN_ERR, "error: not enough memory");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1021
1022
  		goto failed_mount_group_desc;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
1026
1027
1028
  	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...
1029
1030
  			ext2_msg(sb, KERN_ERR,
  				"error: unable to read group descriptors");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1031
1032
1033
1034
  			goto failed_mount_group_desc;
  		}
  	}
  	if (!ext2_check_descriptors (sb)) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1035
  		ext2_msg(sb, KERN_ERR, "group descriptors corrupted");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
1038
1039
1040
  		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...
1041

a686cd898   Martin J. Bligh   ext2 reservations
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
  	/* 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...
1056
  	err = percpu_counter_init(&sbi->s_freeblocks_counter,
908c7f194   Tejun Heo   percpu_counter: a...
1057
  				ext2_count_free_blocks(sb), GFP_KERNEL);
833f4077b   Peter Zijlstra   lib: percpu_count...
1058
1059
  	if (!err) {
  		err = percpu_counter_init(&sbi->s_freeinodes_counter,
908c7f194   Tejun Heo   percpu_counter: a...
1060
  				ext2_count_free_inodes(sb), GFP_KERNEL);
833f4077b   Peter Zijlstra   lib: percpu_count...
1061
1062
1063
  	}
  	if (!err) {
  		err = percpu_counter_init(&sbi->s_dirs_counter,
908c7f194   Tejun Heo   percpu_counter: a...
1064
  				ext2_count_dirs(sb), GFP_KERNEL);
833f4077b   Peter Zijlstra   lib: percpu_count...
1065
1066
  	}
  	if (err) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1067
  		ext2_msg(sb, KERN_ERR, "error: insufficient memory");
833f4077b   Peter Zijlstra   lib: percpu_count...
1068
1069
  		goto failed_mount3;
  	}
be0726d33   Jan Kara   ext2: convert to ...
1070
1071
1072
1073
1074
1075
1076
1077
  
  #ifdef CONFIG_EXT2_FS_XATTR
  	sbi->s_mb_cache = ext2_xattr_create_cache();
  	if (!sbi->s_mb_cache) {
  		ext2_msg(sb, KERN_ERR, "Failed to create an mb_cache");
  		goto failed_mount3;
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
1080
1081
1082
1083
  	/*
  	 * 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...
1084
1085
1086
  
  #ifdef CONFIG_QUOTA
  	sb->dq_op = &dquot_operations;
287a80958   Christoph Hellwig   quota: rename def...
1087
  	sb->s_qcop = &dquot_quotactl_ops;
64241118b   Jan Kara   ext2: Convert to ...
1088
  	sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
123e9caf1   Christoph Hellwig   quota: explicitly...
1089
  #endif
52fcf7032   David Howells   iget: stop EXT2 f...
1090
1091
1092
  	root = ext2_iget(sb, EXT2_ROOT_INO);
  	if (IS_ERR(root)) {
  		ret = PTR_ERR(root);
0216bfcff   Mingming Cao   [PATCH] percpu co...
1093
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
1095
  	}
  	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
52fcf7032   David Howells   iget: stop EXT2 f...
1096
  		iput(root);
2314b07cb   Alexey Fisher   ext2: Unify log m...
1097
  		ext2_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
0216bfcff   Mingming Cao   [PATCH] percpu co...
1098
  		goto failed_mount3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
  	}
52fcf7032   David Howells   iget: stop EXT2 f...
1100

48fde701a   Al Viro   switch open-coded...
1101
  	sb->s_root = d_make_root(root);
52fcf7032   David Howells   iget: stop EXT2 f...
1102
  	if (!sb->s_root) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1103
  		ext2_msg(sb, KERN_ERR, "error: get root inode failed");
52fcf7032   David Howells   iget: stop EXT2 f...
1104
1105
1106
  		ret = -ENOMEM;
  		goto failed_mount3;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
  	if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2314b07cb   Alexey Fisher   ext2: Unify log m...
1108
1109
  		ext2_msg(sb, KERN_WARNING,
  			"warning: mounting ext3 filesystem as ext2");
4c96a68bf   Jan Blunck   ext2: Move ext2_w...
1110
1111
1112
  	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
1113
1114
1115
1116
  	return 0;
  
  cantfind_ext2:
  	if (!silent)
2314b07cb   Alexey Fisher   ext2: Unify log m...
1117
1118
1119
  		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
1120
  	goto failed_mount;
0216bfcff   Mingming Cao   [PATCH] percpu co...
1121
  failed_mount3:
be0726d33   Jan Kara   ext2: convert to ...
1122
1123
  	if (sbi->s_mb_cache)
  		ext2_xattr_destroy_cache(sbi->s_mb_cache);
0216bfcff   Mingming Cao   [PATCH] percpu co...
1124
1125
1126
  	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
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
  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 ...
1137
  	kfree(sbi->s_blockgroup_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
  	kfree(sbi);
e124a3204   Wanlong Gao   ext2: cleanup the...
1139
  failed:
52fcf7032   David Howells   iget: stop EXT2 f...
1140
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1141
  }
7bf0dc9b0   Theodore Ts'o   ext2: avoid WARN(...
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
  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...
1155
1156
1157
  		ext2_msg(sb, KERN_ERR,
  		       "previous I/O error to superblock detected
  ");
7bf0dc9b0   Theodore Ts'o   ext2: avoid WARN(...
1158
1159
1160
1161
  		clear_buffer_write_io_error(sbh);
  		set_buffer_uptodate(sbh);
  	}
  }
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
1162
1163
  static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es,
  			    int wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
  {
7bf0dc9b0   Theodore Ts'o   ext2: avoid WARN(...
1165
  	ext2_clear_super_error(sb);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1166
  	spin_lock(&EXT2_SB(sb)->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167
1168
1169
  	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...
1170
1171
  	/* unlock before we do IO */
  	spin_unlock(&EXT2_SB(sb)->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
  	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
1173
1174
  	if (wait)
  		sync_dirty_buffer(EXT2_SB(sb)->s_sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
  }
  
  /*
   * 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
1187
  static int ext2_sync_fs(struct super_block *sb, int wait)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
  {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1189
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1190
  	struct ext2_super_block *es = EXT2_SB(sb)->s_es;
a11778257   Jan Kara   quota: Move quota...
1191
1192
1193
1194
1195
  	/*
  	 * Write quota structures to quota file, sync_blockdev() will write
  	 * them to disk later
  	 */
  	dquot_writeback_dquots(sb, -1);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1196
  	spin_lock(&sbi->s_lock);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1197
1198
1199
1200
  	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
1201
  	}
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1202
  	spin_unlock(&sbi->s_lock);
ee6921ebd   Jan Blunck   ext2: Fold ext2_c...
1203
  	ext2_sync_super(sb, es, wait);
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1204
1205
  	return 0;
  }
1e8b212fe   Jan Kara   ext2: Implement f...
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
  static int ext2_freeze(struct super_block *sb)
  {
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
  
  	/*
  	 * Open but unlinked files present? Keep EXT2_VALID_FS flag cleared
  	 * because we have unattached inodes and thus filesystem is not fully
  	 * consistent.
  	 */
  	if (atomic_long_read(&sb->s_remove_count)) {
  		ext2_sync_fs(sb, 1);
  		return 0;
  	}
  	/* Set EXT2_FS_VALID flag */
  	spin_lock(&sbi->s_lock);
  	sbi->s_es->s_state = cpu_to_le16(sbi->s_mount_state);
  	spin_unlock(&sbi->s_lock);
  	ext2_sync_super(sb, sbi->s_es, 1);
  
  	return 0;
  }
  
  static int ext2_unfreeze(struct super_block *sb)
  {
  	/* Just write sb to clear EXT2_VALID_FS flag */
  	ext2_write_super(sb);
  
  	return 0;
  }
40f31dd47   Christoph Hellwig   ext2: add ->sync_fs
1235
1236
1237
1238
1239
  
  void ext2_write_super(struct super_block *sb)
  {
  	if (!(sb->s_flags & MS_RDONLY))
  		ext2_sync_fs(sb, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240
1241
1242
1243
1244
1245
  }
  
  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;
50a522342   Jan Kara   [PATCH] ext2: fix...
1246
1247
1248
  	struct ext2_mount_options old_opts;
  	unsigned long old_sb_flags;
  	int err;
02b9984d6   Theodore Ts'o   fs: push sync_fil...
1249
  	sync_filesystem(sb);
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1250
  	spin_lock(&sbi->s_lock);
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1251

50a522342   Jan Kara   [PATCH] ext2: fix...
1252
1253
1254
1255
1256
  	/* 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
1257
1258
1259
1260
  
  	/*
  	 * Allow the "check" option to be passed as a remount option.
  	 */
2314b07cb   Alexey Fisher   ext2: Unify log m...
1261
  	if (!parse_options(data, sb)) {
50a522342   Jan Kara   [PATCH] ext2: fix...
1262
1263
1264
  		err = -EINVAL;
  		goto restore_opts;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1265
1266
1267
1268
1269
  
  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
  		((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
  
  	es = sbi->s_es;
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
1270
  	if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT2_MOUNT_DAX) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1271
  		ext2_msg(sb, KERN_WARNING, "warning: refusing change of "
9c3ce9ec5   Matthew Wilcox   ext2: get rid of ...
1272
1273
  			 "dax flag with busy inodes while remounting");
  		sbi->s_mount_opt ^= EXT2_MOUNT_DAX;
0e4a9b592   Carsten Otte   ext2/xip: refuse ...
1274
  	}
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1275
  	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1276
  		spin_unlock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
  		return 0;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1278
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279
1280
  	if (*flags & MS_RDONLY) {
  		if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1281
  		    !(sbi->s_mount_state & EXT2_VALID_FS)) {
c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1282
  			spin_unlock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1283
  			return 0;
337eb00a2   Alessio Igor Bogani   Push BKL down int...
1284
  		}
c79d967de   Christoph Hellwig   quota: move remou...
1285

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
1287
1288
1289
1290
1291
  		/*
  		 * 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...
1292
  		spin_unlock(&sbi->s_lock);
c79d967de   Christoph Hellwig   quota: move remou...
1293

0f0dd62fd   Christoph Hellwig   quota: kill the v...
1294
1295
  		err = dquot_suspend(sb, -1);
  		if (err < 0) {
c79d967de   Christoph Hellwig   quota: move remou...
1296
1297
1298
  			spin_lock(&sbi->s_lock);
  			goto restore_opts;
  		}
4c96a68bf   Jan Blunck   ext2: Move ext2_w...
1299
  		ext2_sync_super(sb, es, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300
1301
1302
1303
  	} else {
  		__le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
  					       ~EXT2_FEATURE_RO_COMPAT_SUPP);
  		if (ret) {
2314b07cb   Alexey Fisher   ext2: Unify log m...
1304
1305
1306
1307
  			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...
1308
1309
  			err = -EROFS;
  			goto restore_opts;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
1312
1313
1314
1315
1316
1317
1318
  		}
  		/*
  		 * 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...
1319
  		spin_unlock(&sbi->s_lock);
c79d967de   Christoph Hellwig   quota: move remou...
1320

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
  	return 0;
50a522342   Jan Kara   [PATCH] ext2: fix...
1327
1328
1329
1330
1331
  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...
1332
  	spin_unlock(&sbi->s_lock);
50a522342   Jan Kara   [PATCH] ext2: fix...
1333
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1334
  }
726c33422   David Howells   [PATCH] VFS: Perm...
1335
  static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1336
  {
726c33422   David Howells   [PATCH] VFS: Perm...
1337
  	struct super_block *sb = dentry->d_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338
  	struct ext2_sb_info *sbi = EXT2_SB(sb);
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1339
  	struct ext2_super_block *es = sbi->s_es;
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1340
  	u64 fsid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341

c15271f4e   Jan Blunck   ext2: Add ext2_sb...
1342
  	spin_lock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
  	if (test_opt (sb, MINIX_DF))
2235219b7   Badari Pulavarty   ext2: statfs spee...
1344
1345
1346
1347
  		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
1348
  		/*
2235219b7   Badari Pulavarty   ext2: statfs spee...
1349
1350
1351
  		 * 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
1352
1353
1354
1355
1356
1357
  		 */
  
  		/*
  		 * All of the blocks before first_data_block are
  		 * overhead
  		 */
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1358
  		overhead = le32_to_cpu(es->s_first_data_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
  
  		/*
  		 * 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...
1375
1376
1377
  		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
1378
1379
1380
1381
  	}
  
  	buf->f_type = EXT2_SUPER_MAGIC;
  	buf->f_bsize = sb->s_blocksize;
2235219b7   Badari Pulavarty   ext2: statfs spee...
1382
  	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383
  	buf->f_bfree = ext2_count_free_blocks(sb);
2235219b7   Badari Pulavarty   ext2: statfs spee...
1384
  	es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1385
1386
  	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
1387
  		buf->f_bavail = 0;
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1388
1389
  	buf->f_files = le32_to_cpu(es->s_inodes_count);
  	buf->f_ffree = ext2_count_free_inodes(sb);
2235219b7   Badari Pulavarty   ext2: statfs spee...
1390
  	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
  	buf->f_namelen = EXT2_NAME_LEN;
e4fca01ea   Pekka Enberg   [PATCH] ext2: fsi...
1392
1393
1394
1395
  	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...
1396
  	spin_unlock(&sbi->s_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1397
1398
  	return 0;
  }
152a08366   Al Viro   new helper: mount...
1399
1400
  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
1401
  {
152a08366   Al Viro   new helper: mount...
1402
  	return mount_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
1404
1405
1406
1407
1408
  }
  
  #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...
1409
   * itself serializes the operations (and no one else should touch the files)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
   * 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_...
1434
  		tmp_bh.b_size = sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
  		err = ext2_get_block(inode, blk, &tmp_bh, 0);
a686cd898   Martin J. Bligh   ext2 reservations
1436
  		if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
  			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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
1468
1469
1470
1471
  	while (towrite > 0) {
  		tocopy = sb->s_blocksize - offset < towrite ?
  				sb->s_blocksize - offset : towrite;
  
  		tmp_bh.b_state = 0;
df4e7ac0b   Jan Kara   ext2: Fix oops in...
1472
  		tmp_bh.b_size = sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1473
  		err = ext2_get_block(inode, blk, &tmp_bh, 1);
a686cd898   Martin J. Bligh   ext2 reservations
1474
  		if (err < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1475
1476
1477
1478
1479
  			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);
2b0542a4a   Wang Shilong   Ext2: use unlikel...
1480
  		if (unlikely(!bh)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
  			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:
e2a3fde75   Jan Kara   ext2: Remove i_mu...
1497
  	if (len == towrite)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
1500
1501
  		return err;
  	if (inode->i_size < off+len-towrite)
  		i_size_write(inode, off+len-towrite);
  	inode->i_version++;
078cd8279   Deepa Dinamani   fs: Replace CURRE...
1502
  	inode->i_mtime = inode->i_ctime = current_time(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
  	mark_inode_dirty(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1504
1505
1506
1507
1508
1509
1510
1511
  	return len - towrite;
  }
  
  #endif
  
  static struct file_system_type ext2_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "ext2",
152a08366   Al Viro   new helper: mount...
1512
  	.mount		= ext2_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
  	.kill_sb	= kill_block_super,
46b15caa7   Tejun Heo   vfs, writeback: r...
1514
  	.fs_flags	= FS_REQUIRES_DEV,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1515
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
1516
  MODULE_ALIAS_FS("ext2");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1517
1518
1519
  
  static int __init init_ext2_fs(void)
  {
be0726d33   Jan Kara   ext2: convert to ...
1520
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
  	err = init_inodecache();
  	if (err)
be0726d33   Jan Kara   ext2: convert to ...
1523
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
1525
1526
1527
1528
1529
          err = register_filesystem(&ext2_fs_type);
  	if (err)
  		goto out;
  	return 0;
  out:
  	destroy_inodecache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1530
1531
1532
1533
1534
1535
1536
  	return err;
  }
  
  static void __exit exit_ext2_fs(void)
  {
  	unregister_filesystem(&ext2_fs_type);
  	destroy_inodecache();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
  }
302bf2f32   Paul Gortmaker   ext2/3/4: delete ...
1538
1539
1540
  MODULE_AUTHOR("Remy Card and others");
  MODULE_DESCRIPTION("Second Extended Filesystem");
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
1542
  module_init(init_ext2_fs)
  module_exit(exit_ext2_fs)