Blame view

fs/ext3/resize.c 34 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   *  linux/fs/ext3/resize.c
   *
   * Support for resizing an ext3 filesystem while it is mounted.
   *
   * Copyright (C) 2001, 2002 Andreas Dilger <adilger@clusterfs.com>
   *
   * This could probably be made into a module, because it is not often in use.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
  
  #define EXT3FS_DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  #include <linux/ext3_jbd.h>
  
  #include <linux/errno.h>
  #include <linux/slab.h>
  
  
  #define outside(b, first, last)	((b) < (first) || (b) >= (last))
  #define inside(b, first, last)	((b) >= (first) && (b) < (last))
  
  static int verify_group_input(struct super_block *sb,
  			      struct ext3_new_group_data *input)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	struct ext3_super_block *es = sbi->s_es;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
26
27
  	ext3_fsblk_t start = le32_to_cpu(es->s_blocks_count);
  	ext3_fsblk_t end = start + input->blocks_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  	unsigned group = input->group;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
29
  	ext3_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
  	unsigned overhead = ext3_bg_has_super(sb, group) ?
  		(1 + ext3_bg_num_gdb(sb, group) +
  		 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
33
  	ext3_fsblk_t metaend = start + overhead;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  	struct buffer_head *bh = NULL;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
35
  	ext3_grpblk_t free_blocks_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  	int err = -EINVAL;
  
  	input->free_blocks_count = free_blocks_count =
  		input->blocks_count - 2 - overhead - sbi->s_itb_per_group;
  
  	if (test_opt(sb, DEBUG))
  		printk(KERN_DEBUG "EXT3-fs: adding %s group %u: %u blocks "
  		       "(%d free, %u reserved)
  ",
  		       ext3_bg_has_super(sb, input->group) ? "normal" :
  		       "no-super", input->group, input->blocks_count,
  		       free_blocks_count, input->reserved_blocks);
  
  	if (group != sbi->s_groups_count)
e05b6b524   Harvey Harrison   ext3: replace rem...
50
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
  			     "Cannot add at group %u (only %lu groups)",
  			     input->group, sbi->s_groups_count);
  	else if ((start - le32_to_cpu(es->s_first_data_block)) %
  		 EXT3_BLOCKS_PER_GROUP(sb))
e05b6b524   Harvey Harrison   ext3: replace rem...
55
  		ext3_warning(sb, __func__, "Last group not full");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	else if (input->reserved_blocks > input->blocks_count / 5)
e05b6b524   Harvey Harrison   ext3: replace rem...
57
  		ext3_warning(sb, __func__, "Reserved blocks too high (%u)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  			     input->reserved_blocks);
  	else if (free_blocks_count < 0)
e05b6b524   Harvey Harrison   ext3: replace rem...
60
  		ext3_warning(sb, __func__, "Bad blocks count %u",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
  			     input->blocks_count);
  	else if (!(bh = sb_bread(sb, end - 1)))
e05b6b524   Harvey Harrison   ext3: replace rem...
63
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
64
  			     "Cannot read last block ("E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  			     end - 1);
  	else if (outside(input->block_bitmap, start, end))
e05b6b524   Harvey Harrison   ext3: replace rem...
67
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  			     "Block bitmap not in group (block %u)",
  			     input->block_bitmap);
  	else if (outside(input->inode_bitmap, start, end))
e05b6b524   Harvey Harrison   ext3: replace rem...
71
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
  			     "Inode bitmap not in group (block %u)",
  			     input->inode_bitmap);
  	else if (outside(input->inode_table, start, end) ||
  	         outside(itend - 1, start, end))
e05b6b524   Harvey Harrison   ext3: replace rem...
76
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
77
  			     "Inode table not in group (blocks %u-"E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  			     input->inode_table, itend - 1);
  	else if (input->inode_bitmap == input->block_bitmap)
e05b6b524   Harvey Harrison   ext3: replace rem...
80
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
  			     "Block bitmap same as inode bitmap (%u)",
  			     input->block_bitmap);
  	else if (inside(input->block_bitmap, input->inode_table, itend))
e05b6b524   Harvey Harrison   ext3: replace rem...
84
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
85
  			     "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
  			     input->block_bitmap, input->inode_table, itend-1);
  	else if (inside(input->inode_bitmap, input->inode_table, itend))
e05b6b524   Harvey Harrison   ext3: replace rem...
88
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
89
  			     "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  			     input->inode_bitmap, input->inode_table, itend-1);
  	else if (inside(input->block_bitmap, start, metaend))
e05b6b524   Harvey Harrison   ext3: replace rem...
92
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
93
94
  			     "Block bitmap (%u) in GDT table"
  			     " ("E3FSBLK"-"E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  			     input->block_bitmap, start, metaend - 1);
  	else if (inside(input->inode_bitmap, start, metaend))
e05b6b524   Harvey Harrison   ext3: replace rem...
97
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
98
99
  			     "Inode bitmap (%u) in GDT table"
  			     " ("E3FSBLK"-"E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
  			     input->inode_bitmap, start, metaend - 1);
  	else if (inside(input->inode_table, start, metaend) ||
  	         inside(itend - 1, start, metaend))
e05b6b524   Harvey Harrison   ext3: replace rem...
103
  		ext3_warning(sb, __func__,
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
104
105
  			     "Inode table (%u-"E3FSBLK") overlaps"
  			     "GDT table ("E3FSBLK"-"E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
110
111
112
113
114
  			     input->inode_table, itend - 1, start, metaend - 1);
  	else
  		err = 0;
  	brelse(bh);
  
  	return err;
  }
  
  static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
115
  				  ext3_fsblk_t blk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
  {
  	struct buffer_head *bh;
  	int err;
  
  	bh = sb_getblk(sb, blk);
2973dfdb8   Glauber de Oliveira Costa   [PATCH] Test for ...
121
122
  	if (!bh)
  		return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  	if ((err = ext3_journal_get_write_access(handle, bh))) {
  		brelse(bh);
  		bh = ERR_PTR(err);
  	} else {
  		lock_buffer(bh);
  		memset(bh->b_data, 0, sb->s_blocksize);
  		set_buffer_uptodate(bh);
  		unlock_buffer(bh);
  	}
  
  	return bh;
  }
  
  /*
   * To avoid calling the atomic setbit hundreds or thousands of times, we only
   * need to use it within a single byte (to ensure we get endianness right).
   * We can use memset for the rest of the bitmap as there are no other users.
   */
  static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
  {
  	int i;
  
  	if (start_bit >= end_bit)
  		return;
  
  	ext3_debug("mark end bits +%d through +%d used
  ", start_bit, end_bit);
  	for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
  		ext3_set_bit(i, bitmap);
  	if (i < end_bit)
  		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
  }
  
  /*
1ad6ecf91   Eric Sandeen   ext3: lighten up ...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
   * If we have fewer than thresh credits, extend by EXT3_MAX_TRANS_DATA.
   * If that fails, restart the transaction & regain write access for the
   * buffer head which is used for block_bitmap modifications.
   */
  static int extend_or_restart_transaction(handle_t *handle, int thresh,
  					 struct buffer_head *bh)
  {
  	int err;
  
  	if (handle->h_buffer_credits >= thresh)
  		return 0;
  
  	err = ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA);
  	if (err < 0)
  		return err;
  	if (err) {
  		err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA);
  		if (err)
  			return err;
  		err = ext3_journal_get_write_access(handle, bh);
  		if (err)
  			return err;
  	}
  
  	return 0;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
190
191
192
193
194
   * Set up the block and inode bitmaps, and the inode table for the new group.
   * This doesn't need to be part of the main transaction, since we are only
   * changing blocks outside the actual filesystem.  We still do journaling to
   * ensure the recovery is correct in case of a failure just after resize.
   * If any part of this fails, we simply abort the resize.
   */
  static int setup_new_group_blocks(struct super_block *sb,
  				  struct ext3_new_group_data *input)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
195
  	ext3_fsblk_t start = ext3_group_first_block_no(sb, input->group);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
199
200
  	int reserved_gdb = ext3_bg_has_super(sb, input->group) ?
  		le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0;
  	unsigned long gdblocks = ext3_bg_num_gdb(sb, input->group);
  	struct buffer_head *bh;
  	handle_t *handle;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
201
  	ext3_fsblk_t block;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
202
  	ext3_grpblk_t bit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
  	int i;
  	int err = 0, err2;
1ad6ecf91   Eric Sandeen   ext3: lighten up ...
205
206
  	/* This transaction may be extended/restarted along the way */
  	handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
  	if (IS_ERR(handle))
  		return PTR_ERR(handle);
96d2a495c   Eric Sandeen   ext3: Replace loc...
209
  	mutex_lock(&sbi->s_resize_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	if (input->group != sbi->s_groups_count) {
  		err = -EBUSY;
  		goto exit_journal;
  	}
  
  	if (IS_ERR(bh = bclean(handle, sb, input->block_bitmap))) {
  		err = PTR_ERR(bh);
  		goto exit_journal;
  	}
  
  	if (ext3_bg_has_super(sb, input->group)) {
  		ext3_debug("mark backup superblock %#04lx (+0)
  ", start);
  		ext3_set_bit(0, bh->b_data);
  	}
  
  	/* Copy all of the GDT blocks into the backup in this group */
  	for (i = 0, bit = 1, block = start + 1;
  	     i < gdblocks; i++, block++, bit++) {
  		struct buffer_head *gdb;
  
  		ext3_debug("update backup group %#04lx (+%d)
  ", block, bit);
1ad6ecf91   Eric Sandeen   ext3: lighten up ...
233
234
235
  		err = extend_or_restart_transaction(handle, 1, bh);
  		if (err)
  			goto exit_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  		gdb = sb_getblk(sb, block);
2973dfdb8   Glauber de Oliveira Costa   [PATCH] Test for ...
237
238
239
240
  		if (!gdb) {
  			err = -EIO;
  			goto exit_bh;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
243
244
  		if ((err = ext3_journal_get_write_access(handle, gdb))) {
  			brelse(gdb);
  			goto exit_bh;
  		}
42a2b6ad7   Eric Sandeen   ext3: fix setup_n...
245
246
  		lock_buffer(gdb);
  		memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  		set_buffer_uptodate(gdb);
42a2b6ad7   Eric Sandeen   ext3: fix setup_n...
248
  		unlock_buffer(gdb);
41dc6385b   Namhyung Kim   ext3: Add journal...
249
250
251
252
253
  		err = ext3_journal_dirty_metadata(handle, gdb);
  		if (err) {
  			brelse(gdb);
  			goto exit_bh;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
257
258
259
260
261
262
263
264
  		ext3_set_bit(bit, bh->b_data);
  		brelse(gdb);
  	}
  
  	/* Zero out all of the reserved backup group descriptor table blocks */
  	for (i = 0, bit = gdblocks + 1, block = start + bit;
  	     i < reserved_gdb; i++, block++, bit++) {
  		struct buffer_head *gdb;
  
  		ext3_debug("clear reserved block %#04lx (+%d)
  ", block, bit);
1ad6ecf91   Eric Sandeen   ext3: lighten up ...
265
266
267
  		err = extend_or_restart_transaction(handle, 1, bh);
  		if (err)
  			goto exit_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  		if (IS_ERR(gdb = bclean(handle, sb, block))) {
8e0eb4011   Roel Kluin   ext3: PTR_ERR ret...
269
  			err = PTR_ERR(gdb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
  			goto exit_bh;
  		}
41dc6385b   Namhyung Kim   ext3: Add journal...
272
273
274
275
276
  		err = ext3_journal_dirty_metadata(handle, gdb);
  		if (err) {
  			brelse(gdb);
  			goto exit_bh;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  		ext3_set_bit(bit, bh->b_data);
  		brelse(gdb);
  	}
  	ext3_debug("mark block bitmap %#04x (+%ld)
  ", input->block_bitmap,
  		   input->block_bitmap - start);
  	ext3_set_bit(input->block_bitmap - start, bh->b_data);
  	ext3_debug("mark inode bitmap %#04x (+%ld)
  ", input->inode_bitmap,
  		   input->inode_bitmap - start);
  	ext3_set_bit(input->inode_bitmap - start, bh->b_data);
  
  	/* Zero out all of the inode table blocks */
  	for (i = 0, block = input->inode_table, bit = block - start;
  	     i < sbi->s_itb_per_group; i++, bit++, block++) {
  		struct buffer_head *it;
8bdac5d1e   Glauber de Oliveira Costa   [PATCH] ext3: EXT...
293
294
  		ext3_debug("clear inode block %#04lx (+%d)
  ", block, bit);
1ad6ecf91   Eric Sandeen   ext3: lighten up ...
295
296
297
298
  
  		err = extend_or_restart_transaction(handle, 1, bh);
  		if (err)
  			goto exit_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
  		if (IS_ERR(it = bclean(handle, sb, block))) {
  			err = PTR_ERR(it);
  			goto exit_bh;
  		}
41dc6385b   Namhyung Kim   ext3: Add journal...
303
304
305
306
307
  		err = ext3_journal_dirty_metadata(handle, it);
  		if (err) {
  			brelse(it);
  			goto exit_bh;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
  		brelse(it);
  		ext3_set_bit(bit, bh->b_data);
  	}
1ad6ecf91   Eric Sandeen   ext3: lighten up ...
311
312
313
314
  
  	err = extend_or_restart_transaction(handle, 2, bh);
  	if (err)
  		goto exit_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
  	mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb),
  			bh->b_data);
41dc6385b   Namhyung Kim   ext3: Add journal...
317
318
319
  	err = ext3_journal_dirty_metadata(handle, bh);
  	if (err)
  		goto exit_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
322
323
324
325
326
327
328
329
330
331
332
  	brelse(bh);
  
  	/* Mark unused entries in inode bitmap used */
  	ext3_debug("clear inode bitmap %#04x (+%ld)
  ",
  		   input->inode_bitmap, input->inode_bitmap - start);
  	if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) {
  		err = PTR_ERR(bh);
  		goto exit_journal;
  	}
  
  	mark_bitmap_end(EXT3_INODES_PER_GROUP(sb), EXT3_BLOCKS_PER_GROUP(sb),
  			bh->b_data);
41dc6385b   Namhyung Kim   ext3: Add journal...
333
  	err = ext3_journal_dirty_metadata(handle, bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
  exit_bh:
  	brelse(bh);
  
  exit_journal:
96d2a495c   Eric Sandeen   ext3: Replace loc...
338
  	mutex_unlock(&sbi->s_resize_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
344
345
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
  	if ((err2 = ext3_journal_stop(handle)) && !err)
  		err = err2;
  
  	return err;
  }
  
  /*
   * Iterate through the groups which hold BACKUP superblock/GDT copies in an
   * ext3 filesystem.  The counters should be initialized to 1, 5, and 7 before
   * calling this for the first time.  In a sparse filesystem it will be the
   * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
   * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
   */
  static unsigned ext3_list_backups(struct super_block *sb, unsigned *three,
  				  unsigned *five, unsigned *seven)
  {
  	unsigned *min = three;
  	int mult = 3;
  	unsigned ret;
  
  	if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
  					EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
  		ret = *min;
  		*min += 1;
  		return ret;
  	}
  
  	if (*five < *min) {
  		min = five;
  		mult = 5;
  	}
  	if (*seven < *min) {
  		min = seven;
  		mult = 7;
  	}
  
  	ret = *min;
  	*min *= mult;
  
  	return ret;
  }
  
  /*
   * Check that all of the backup GDT blocks are held in the primary GDT block.
   * It is assumed that they are stored in group order.  Returns the number of
   * groups in current filesystem that have BACKUPS, or -ve error code.
   */
  static int verify_reserved_gdb(struct super_block *sb,
  			       struct buffer_head *primary)
  {
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
389
  	const ext3_fsblk_t blk = primary->b_blocknr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
393
394
  	const unsigned long end = EXT3_SB(sb)->s_groups_count;
  	unsigned three = 1;
  	unsigned five = 5;
  	unsigned seven = 7;
  	unsigned grp;
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
395
  	__le32 *p = (__le32 *)primary->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
  	int gdbackups = 0;
  
  	while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
  		if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){
e05b6b524   Harvey Harrison   ext3: replace rem...
400
  			ext3_warning(sb, __func__,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
401
402
  				     "reserved GDT "E3FSBLK
  				     " missing grp %d ("E3FSBLK")",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  				     blk, grp,
  				     grp * EXT3_BLOCKS_PER_GROUP(sb) + blk);
  			return -EINVAL;
  		}
  		if (++gdbackups > EXT3_ADDR_PER_BLOCK(sb))
  			return -EFBIG;
  	}
  
  	return gdbackups;
  }
  
  /*
   * Called when we need to bring a reserved group descriptor table block into
   * use from the resize inode.  The primary copy of the new GDT block currently
   * is an indirect block (under the double indirect block in the resize inode).
   * The new backup GDT blocks will be stored as leaf blocks in this indirect
   * block, in group order.  Even though we know all the block numbers we need,
   * we check to ensure that the resize inode has actually reserved these blocks.
   *
   * Don't need to update the block bitmaps because the blocks are still in use.
   *
   * We get all of the error cases out of the way, so that we are sure to not
   * fail once we start modifying the data on disk, because JBD has no rollback.
   */
  static int add_new_gdb(handle_t *handle, struct inode *inode,
  		       struct ext3_new_group_data *input,
  		       struct buffer_head **primary)
  {
  	struct super_block *sb = inode->i_sb;
  	struct ext3_super_block *es = EXT3_SB(sb)->s_es;
  	unsigned long gdb_num = input->group / EXT3_DESC_PER_BLOCK(sb);
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
434
  	ext3_fsblk_t gdblock = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
  	struct buffer_head **o_group_desc, **n_group_desc;
  	struct buffer_head *dind;
  	int gdbackups;
  	struct ext3_iloc iloc;
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
439
  	__le32 *data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
  	int err;
  
  	if (test_opt(sb, DEBUG))
  		printk(KERN_DEBUG
  		       "EXT3-fs: ext3_add_new_gdb: adding group block %lu
  ",
  		       gdb_num);
  
  	/*
  	 * If we are not using the primary superblock/GDT copy don't resize,
  	 * because the user tools have no way of handling this.  Probably a
  	 * bad time to do it anyways.
  	 */
  	if (EXT3_SB(sb)->s_sbh->b_blocknr !=
  	    le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
455
  		ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
456
  			"won't resize using backup superblock at %llu",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
  			(unsigned long long)EXT3_SB(sb)->s_sbh->b_blocknr);
  		return -EPERM;
  	}
  
  	*primary = sb_bread(sb, gdblock);
  	if (!*primary)
  		return -EIO;
  
  	if ((gdbackups = verify_reserved_gdb(sb, *primary)) < 0) {
  		err = gdbackups;
  		goto exit_bh;
  	}
  
  	data = EXT3_I(inode)->i_data + EXT3_DIND_BLOCK;
  	dind = sb_bread(sb, le32_to_cpu(*data));
  	if (!dind) {
  		err = -EIO;
  		goto exit_bh;
  	}
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
476
  	data = (__le32 *)dind->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  	if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
e05b6b524   Harvey Harrison   ext3: replace rem...
478
  		ext3_warning(sb, __func__,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
479
  			     "new group %u GDT block "E3FSBLK" not reserved",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  			     input->group, gdblock);
  		err = -EINVAL;
  		goto exit_dind;
  	}
  
  	if ((err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh)))
  		goto exit_dind;
  
  	if ((err = ext3_journal_get_write_access(handle, *primary)))
  		goto exit_sbh;
  
  	if ((err = ext3_journal_get_write_access(handle, dind)))
  		goto exit_primary;
  
  	/* ext3_reserve_inode_write() gets a reference on the iloc */
  	if ((err = ext3_reserve_inode_write(handle, inode, &iloc)))
  		goto exit_dindj;
f52720ca5   Panagiotis Issaris   [PATCH] fs: Remov...
497
  	n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
c587f0c0a   Josef Bacik   ext3: fix wrong g...
498
  			GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
  	if (!n_group_desc) {
  		err = -ENOMEM;
e05b6b524   Harvey Harrison   ext3: replace rem...
501
  		ext3_warning (sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
507
508
509
510
511
512
513
514
515
  			      "not enough memory for %lu groups", gdb_num + 1);
  		goto exit_inode;
  	}
  
  	/*
  	 * Finally, we have all of the possible failures behind us...
  	 *
  	 * Remove new GDT block from inode double-indirect block and clear out
  	 * the new GDT block for use (which also "frees" the backup GDT blocks
  	 * from the reserved inode).  We don't need to change the bitmaps for
  	 * these blocks, because they are marked as in-use from being in the
  	 * reserved inode, and will become GDT blocks (primary and backup).
  	 */
  	data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)] = 0;
41dc6385b   Namhyung Kim   ext3: Add journal...
516
517
518
  	err = ext3_journal_dirty_metadata(handle, dind);
  	if (err)
  		goto exit_group_desc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  	brelse(dind);
41dc6385b   Namhyung Kim   ext3: Add journal...
520
  	dind = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  	inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
41dc6385b   Namhyung Kim   ext3: Add journal...
522
523
524
  	err = ext3_mark_iloc_dirty(handle, inode, &iloc);
  	if (err)
  		goto exit_group_desc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
  	memset((*primary)->b_data, 0, sb->s_blocksize);
41dc6385b   Namhyung Kim   ext3: Add journal...
526
527
528
  	err = ext3_journal_dirty_metadata(handle, *primary);
  	if (err)
  		goto exit_group_desc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
534
535
536
  
  	o_group_desc = EXT3_SB(sb)->s_group_desc;
  	memcpy(n_group_desc, o_group_desc,
  	       EXT3_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
  	n_group_desc[gdb_num] = *primary;
  	EXT3_SB(sb)->s_group_desc = n_group_desc;
  	EXT3_SB(sb)->s_gdb_count++;
  	kfree(o_group_desc);
50e8a2890   Marcin Slusarz   ext3: replace all...
537
  	le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
41dc6385b   Namhyung Kim   ext3: Add journal...
538
539
540
  	err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
  	if (err)
  		goto exit_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
  
  	return 0;
41dc6385b   Namhyung Kim   ext3: Add journal...
543
544
  exit_group_desc:
  	kfree(n_group_desc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
  exit_inode:
  	//ext3_journal_release_buffer(handle, iloc.bh);
  	brelse(iloc.bh);
  exit_dindj:
  	//ext3_journal_release_buffer(handle, dind);
  exit_primary:
  	//ext3_journal_release_buffer(handle, *primary);
  exit_sbh:
  	//ext3_journal_release_buffer(handle, *primary);
  exit_dind:
  	brelse(dind);
  exit_bh:
  	brelse(*primary);
  
  	ext3_debug("leaving with error %d
  ", err);
  	return err;
  }
  
  /*
   * Called when we are adding a new group which has a backup copy of each of
   * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks.
   * We need to add these reserved backup GDT blocks to the resize inode, so
   * that they are kept for future resizing and not allocated to files.
   *
   * Each reserved backup GDT block will go into a different indirect block.
   * The indirect blocks are actually the primary reserved GDT blocks,
   * so we know in advance what their block numbers are.  We only get the
   * double-indirect block to verify it is pointing to the primary reserved
   * GDT blocks so we don't overwrite a data block by accident.  The reserved
   * backup GDT blocks are stored in their reserved primary GDT block.
   */
  static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
  			      struct ext3_new_group_data *input)
  {
  	struct super_block *sb = inode->i_sb;
  	int reserved_gdb =le16_to_cpu(EXT3_SB(sb)->s_es->s_reserved_gdt_blocks);
  	struct buffer_head **primary;
  	struct buffer_head *dind;
  	struct ext3_iloc iloc;
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
585
  	ext3_fsblk_t blk;
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
586
  	__le32 *data, *end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
588
589
  	int gdbackups = 0;
  	int res, i;
  	int err;
c587f0c0a   Josef Bacik   ext3: fix wrong g...
590
  	primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
594
595
596
597
598
599
600
601
  	if (!primary)
  		return -ENOMEM;
  
  	data = EXT3_I(inode)->i_data + EXT3_DIND_BLOCK;
  	dind = sb_bread(sb, le32_to_cpu(*data));
  	if (!dind) {
  		err = -EIO;
  		goto exit_free;
  	}
  
  	blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count;
9bb91784d   Josef Bacik   ext3: fix online ...
602
603
  	data = (__le32 *)dind->b_data + (EXT3_SB(sb)->s_gdb_count %
  					 EXT3_ADDR_PER_BLOCK(sb));
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
604
  	end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
  
  	/* Get each reserved primary GDT block and verify it holds backups */
  	for (res = 0; res < reserved_gdb; res++, blk++) {
  		if (le32_to_cpu(*data) != blk) {
e05b6b524   Harvey Harrison   ext3: replace rem...
609
  			ext3_warning(sb, __func__,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
610
611
  				     "reserved block "E3FSBLK
  				     " not at offset %ld",
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
612
613
  				     blk,
  				     (long)(data - (__le32 *)dind->b_data));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  			err = -EINVAL;
  			goto exit_bh;
  		}
  		primary[res] = sb_bread(sb, blk);
  		if (!primary[res]) {
  			err = -EIO;
  			goto exit_bh;
  		}
  		if ((gdbackups = verify_reserved_gdb(sb, primary[res])) < 0) {
  			brelse(primary[res]);
  			err = gdbackups;
  			goto exit_bh;
  		}
  		if (++data >= end)
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
628
  			data = (__le32 *)dind->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
  	}
  
  	for (i = 0; i < reserved_gdb; i++) {
  		if ((err = ext3_journal_get_write_access(handle, primary[i]))) {
  			/*
  			int j;
  			for (j = 0; j < i; j++)
  				ext3_journal_release_buffer(handle, primary[j]);
  			 */
  			goto exit_bh;
  		}
  	}
  
  	if ((err = ext3_reserve_inode_write(handle, inode, &iloc)))
  		goto exit_bh;
  
  	/*
  	 * Finally we can add each of the reserved backup GDT blocks from
  	 * the new group to its reserved primary GDT block.
  	 */
  	blk = input->group * EXT3_BLOCKS_PER_GROUP(sb);
  	for (i = 0; i < reserved_gdb; i++) {
  		int err2;
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
652
  		data = (__le32 *)primary[i]->b_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
  		/* printk("reserving backup %lu[%u] = %lu
  ",
  		       primary[i]->b_blocknr, gdbackups,
  		       blk + primary[i]->b_blocknr); */
  		data[gdbackups] = cpu_to_le32(blk + primary[i]->b_blocknr);
  		err2 = ext3_journal_dirty_metadata(handle, primary[i]);
  		if (!err)
  			err = err2;
  	}
  	inode->i_blocks += reserved_gdb * sb->s_blocksize >> 9;
  	ext3_mark_iloc_dirty(handle, inode, &iloc);
  
  exit_bh:
  	while (--res >= 0)
  		brelse(primary[res]);
  	brelse(dind);
  
  exit_free:
  	kfree(primary);
  
  	return err;
  }
  
  /*
   * Update the backup copies of the ext3 metadata.  These don't need to be part
   * of the main resize transaction, because e2fsck will re-write them if there
   * is a problem (basically only OOM will cause a problem).  However, we
   * _should_ update the backups if possible, in case the primary gets trashed
   * for some reason and we need to run e2fsck from a backup superblock.  The
   * important part is that the new block and inode counts are in the backup
   * superblocks, and the location of the new group metadata in the GDT backups.
   *
96d2a495c   Eric Sandeen   ext3: Replace loc...
685
686
687
688
689
690
   * We do not need take the s_resize_lock for this, because these
   * blocks are not otherwise touched by the filesystem code when it is
   * mounted.  We don't need to worry about last changing from
   * sbi->s_groups_count, because the worst that can happen is that we
   * do not copy the full number of backups at this time.  The resize
   * which changed s_groups_count will backup again.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
   */
  static void update_backups(struct super_block *sb,
  			   int blk_off, char *data, int size)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	const unsigned long last = sbi->s_groups_count;
  	const int bpg = EXT3_BLOCKS_PER_GROUP(sb);
  	unsigned three = 1;
  	unsigned five = 5;
  	unsigned seven = 7;
  	unsigned group;
  	int rest = sb->s_blocksize - size;
  	handle_t *handle;
  	int err = 0, err2;
  
  	handle = ext3_journal_start_sb(sb, EXT3_MAX_TRANS_DATA);
  	if (IS_ERR(handle)) {
  		group = 1;
  		err = PTR_ERR(handle);
  		goto exit_err;
  	}
  
  	while ((group = ext3_list_backups(sb, &three, &five, &seven)) < last) {
  		struct buffer_head *bh;
  
  		/* Out of journal space, and can't get more - abort - so sad */
  		if (handle->h_buffer_credits == 0 &&
  		    ext3_journal_extend(handle, EXT3_MAX_TRANS_DATA) &&
  		    (err = ext3_journal_restart(handle, EXT3_MAX_TRANS_DATA)))
  			break;
  
  		bh = sb_getblk(sb, group * bpg + blk_off);
2973dfdb8   Glauber de Oliveira Costa   [PATCH] Test for ...
723
724
725
726
  		if (!bh) {
  			err = -EIO;
  			break;
  		}
8bdac5d1e   Glauber de Oliveira Costa   [PATCH] ext3: EXT...
727
728
729
  		ext3_debug("update metadata backup %#04lx
  ",
  			  (unsigned long)bh->b_blocknr);
41dc6385b   Namhyung Kim   ext3: Add journal...
730
731
  		if ((err = ext3_journal_get_write_access(handle, bh))) {
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  			break;
41dc6385b   Namhyung Kim   ext3: Add journal...
733
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
  		lock_buffer(bh);
  		memcpy(bh->b_data, data, size);
  		if (rest)
  			memset(bh->b_data + size, 0, rest);
  		set_buffer_uptodate(bh);
  		unlock_buffer(bh);
41dc6385b   Namhyung Kim   ext3: Add journal...
740
  		err = ext3_journal_dirty_metadata(handle, bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  		brelse(bh);
41dc6385b   Namhyung Kim   ext3: Add journal...
742
743
  		if (err)
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
  	}
  	if ((err2 = ext3_journal_stop(handle)) && !err)
  		err = err2;
  
  	/*
  	 * Ugh! Need to have e2fsck write the backup copies.  It is too
  	 * late to revert the resize, we shouldn't fail just because of
  	 * the backup copies (they are only needed in case of corruption).
  	 *
  	 * However, if we got here we have a journal problem too, so we
  	 * can't really start a transaction to mark the superblock.
  	 * Chicken out and just set the flag on the hope it will be written
  	 * to disk, and if not - we will simply wait until next fsck.
  	 */
  exit_err:
  	if (err) {
e05b6b524   Harvey Harrison   ext3: replace rem...
760
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
  			     "can't update backup for group %d (err %d), "
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
762
  			     "forcing fsck on next reboot", group, err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
  		sbi->s_mount_state &= ~EXT3_VALID_FS;
a4e4de36d   Dave Kleikamp   [PATCH] ext3: Fix...
764
  		sbi->s_es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
  		mark_buffer_dirty(sbi->s_sbh);
  	}
  }
  
  /* Add group descriptor data to an existing or new group descriptor block.
   * Ensure we handle all possible error conditions _before_ we start modifying
   * the filesystem, because we cannot abort the transaction and not have it
   * write the data to disk.
   *
   * If we are on a GDT block boundary, we need to get the reserved GDT block.
   * Otherwise, we may need to add backup GDT blocks for a sparse group.
   *
   * We only need to hold the superblock lock while we are actually adding
   * in the new group's counts to the superblock.  Prior to that we have
   * not really "added" the group at all.  We re-check that we are still
   * adding in the last group in case things have changed since verifying.
   */
  int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
  {
  	struct ext3_sb_info *sbi = EXT3_SB(sb);
  	struct ext3_super_block *es = sbi->s_es;
  	int reserved_gdb = ext3_bg_has_super(sb, input->group) ?
  		le16_to_cpu(es->s_reserved_gdt_blocks) : 0;
  	struct buffer_head *primary = NULL;
  	struct ext3_group_desc *gdp;
  	struct inode *inode = NULL;
  	handle_t *handle;
  	int gdb_off, gdb_num;
  	int err, err2;
  
  	gdb_num = input->group / EXT3_DESC_PER_BLOCK(sb);
  	gdb_off = input->group % EXT3_DESC_PER_BLOCK(sb);
  
  	if (gdb_off == 0 && !EXT3_HAS_RO_COMPAT_FEATURE(sb,
  					EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
800
  		ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
801
  			     "Can't resize non-sparse filesystem further");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
  		return -EPERM;
  	}
32c2d2bc4   Eric Sandeen   [PATCH] more ext3...
804
805
  	if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
  	    le32_to_cpu(es->s_blocks_count)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
806
807
  		ext3_warning(sb, __func__, "blocks_count overflow
  ");
32c2d2bc4   Eric Sandeen   [PATCH] more ext3...
808
809
810
811
812
  		return -EINVAL;
  	}
  
  	if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) <
  	    le32_to_cpu(es->s_inodes_count)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
813
814
  		ext3_warning(sb, __func__, "inodes_count overflow
  ");
32c2d2bc4   Eric Sandeen   [PATCH] more ext3...
815
816
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  	if (reserved_gdb || gdb_off == 0) {
  		if (!EXT3_HAS_COMPAT_FEATURE(sb,
972fbf779   Josef Bacik   ext3: don't try t...
819
820
  					     EXT3_FEATURE_COMPAT_RESIZE_INODE)
  		    || !le16_to_cpu(es->s_reserved_gdt_blocks)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
821
  			ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
822
  				     "No reserved GDT blocks, can't resize");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
824
  			return -EPERM;
  		}
473043dce   David Howells   iget: stop EXT3 f...
825
826
  		inode = ext3_iget(sb, EXT3_RESIZE_INO);
  		if (IS_ERR(inode)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
827
  			ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
828
  				     "Error opening resize inode");
473043dce   David Howells   iget: stop EXT3 f...
829
  			return PTR_ERR(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
  		}
  	}
  
  	if ((err = verify_group_input(sb, input)))
  		goto exit_put;
  
  	if ((err = setup_new_group_blocks(sb, input)))
  		goto exit_put;
  
  	/*
  	 * We will always be modifying at least the superblock and a GDT
  	 * block.  If we are adding a group past the last current GDT block,
  	 * we will also modify the inode and the dindirect block.  If we
  	 * are adding a group with superblock/GDT backups  we will also
  	 * modify each of the reserved GDT dindirect blocks.
  	 */
  	handle = ext3_journal_start_sb(sb,
  				       ext3_bg_has_super(sb, input->group) ?
  				       3 + reserved_gdb : 4);
  	if (IS_ERR(handle)) {
  		err = PTR_ERR(handle);
  		goto exit_put;
  	}
96d2a495c   Eric Sandeen   ext3: Replace loc...
853
  	mutex_lock(&sbi->s_resize_lock);
29ba17231   Glauber de Oliveira Costa   [PATCH] ext3: use...
854
  	if (input->group != sbi->s_groups_count) {
e05b6b524   Harvey Harrison   ext3: replace rem...
855
  		ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
856
  			     "multiple resizers run on filesystem!");
aa877b3dc   Glauber de Oliveira Costa   [PATCH] ext3: Wro...
857
  		err = -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
  		goto exit_journal;
  	}
  
  	if ((err = ext3_journal_get_write_access(handle, sbi->s_sbh)))
  		goto exit_journal;
  
  	/*
  	 * We will only either add reserved group blocks to a backup group
  	 * or remove reserved blocks for the first group in a new group block.
  	 * Doing both would be mean more complex code, and sane people don't
  	 * use non-sparse filesystems anymore.  This is already checked above.
  	 */
  	if (gdb_off) {
  		primary = sbi->s_group_desc[gdb_num];
  		if ((err = ext3_journal_get_write_access(handle, primary)))
  			goto exit_journal;
  
  		if (reserved_gdb && ext3_bg_num_gdb(sb, input->group) &&
  		    (err = reserve_backup_gdb(handle, inode, input)))
  			goto exit_journal;
  	} else if ((err = add_new_gdb(handle, inode, input, &primary)))
  		goto exit_journal;
  
  	/*
  	 * OK, now we've set up the new group.  Time to make it active.
  	 *
96d2a495c   Eric Sandeen   ext3: Replace loc...
884
  	 * We do not lock all allocations via s_resize_lock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
887
888
  	 * so we have to be safe wrt. concurrent accesses the group
  	 * data.  So we need to be careful to set all of the relevant
  	 * group descriptor data etc. *before* we enable the group.
  	 *
29ba17231   Glauber de Oliveira Costa   [PATCH] ext3: use...
889
  	 * The key field here is sbi->s_groups_count: as long as
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
  	 * that retains its old value, nobody is going to access the new
  	 * group.
  	 *
  	 * So first we update all the descriptor metadata for the new
  	 * group; then we update the total disk blocks count; then we
  	 * update the groups count to enable the group; then finally we
  	 * update the free space counts so that the system can start
  	 * using the new disk blocks.
  	 */
  
  	/* Update group descriptor block for new group */
  	gdp = (struct ext3_group_desc *)primary->b_data + gdb_off;
  
  	gdp->bg_block_bitmap = cpu_to_le32(input->block_bitmap);
  	gdp->bg_inode_bitmap = cpu_to_le32(input->inode_bitmap);
  	gdp->bg_inode_table = cpu_to_le32(input->inode_table);
  	gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count);
  	gdp->bg_free_inodes_count = cpu_to_le16(EXT3_INODES_PER_GROUP(sb));
  
  	/*
  	 * Make the new blocks and inodes valid next.  We do this before
  	 * increasing the group count so that once the group is enabled,
  	 * all of its blocks and inodes are already valid.
  	 *
  	 * We always allocate group-by-group, then block-by-block or
  	 * inode-by-inode within a group, so enabling these
  	 * blocks/inodes before the group is live won't actually let us
  	 * allocate the new space yet.
  	 */
50e8a2890   Marcin Slusarz   ext3: replace all...
919
920
  	le32_add_cpu(&es->s_blocks_count, input->blocks_count);
  	le32_add_cpu(&es->s_inodes_count, EXT3_INODES_PER_GROUP(sb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
923
924
925
926
927
  
  	/*
  	 * We need to protect s_groups_count against other CPUs seeing
  	 * inconsistent state in the superblock.
  	 *
  	 * The precise rules we use are:
  	 *
96d2a495c   Eric Sandeen   ext3: Replace loc...
928
  	 * * Writers of s_groups_count *must* hold s_resize_lock
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
931
932
  	 * AND
  	 * * Writers must perform a smp_wmb() after updating all dependent
  	 *   data and before modifying the groups count
  	 *
96d2a495c   Eric Sandeen   ext3: Replace loc...
933
  	 * * Readers must hold s_resize_lock over the access
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
937
938
939
940
941
942
943
944
945
946
  	 * OR
  	 * * Readers must perform an smp_rmb() after reading the groups count
  	 *   and before reading any dependent data.
  	 *
  	 * NB. These rules can be relaxed when checking the group count
  	 * while freeing data, as we can only allocate from a block
  	 * group after serialising against the group count, and we can
  	 * only then free after serialising in turn against that
  	 * allocation.
  	 */
  	smp_wmb();
  
  	/* Update the global fs size fields */
29ba17231   Glauber de Oliveira Costa   [PATCH] ext3: use...
947
  	sbi->s_groups_count++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948

41dc6385b   Namhyung Kim   ext3: Add journal...
949
950
951
  	err = ext3_journal_dirty_metadata(handle, primary);
  	if (err)
  		goto exit_journal;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
954
  
  	/* Update the reserved block counts only once the new group is
  	 * active. */
50e8a2890   Marcin Slusarz   ext3: replace all...
955
  	le32_add_cpu(&es->s_r_blocks_count, input->reserved_blocks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
957
  
  	/* Update the free space counts */
aa0dff2d0   Peter Zijlstra   lib: percpu_count...
958
  	percpu_counter_add(&sbi->s_freeblocks_counter,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
  			   input->free_blocks_count);
aa0dff2d0   Peter Zijlstra   lib: percpu_count...
960
  	percpu_counter_add(&sbi->s_freeinodes_counter,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
  			   EXT3_INODES_PER_GROUP(sb));
41dc6385b   Namhyung Kim   ext3: Add journal...
962
  	err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
  
  exit_journal:
96d2a495c   Eric Sandeen   ext3: Replace loc...
965
  	mutex_unlock(&sbi->s_resize_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
  	if ((err2 = ext3_journal_stop(handle)) && !err)
  		err = err2;
  	if (!err) {
  		update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
  			       sizeof(struct ext3_super_block));
  		update_backups(sb, primary->b_blocknr, primary->b_data,
  			       primary->b_size);
  	}
  exit_put:
  	iput(inode);
  	return err;
  } /* ext3_group_add */
  
  /* Extend the filesystem to the new number of blocks specified.  This entry
   * point is only used to extend the current filesystem to the end of the last
   * existing group.  It can be accessed via ioctl, or by "remount,resize=<size>"
   * for emergencies (because it has no dependencies on reserved blocks).
   *
   * If we _really_ wanted, we could use default values to call ext3_group_add()
   * allow the "remount" trick to work for arbitrary resizing, assuming enough
   * GDT blocks are reserved to grow to the desired size.
   */
  int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
989
  		      ext3_fsblk_t n_blocks_count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
  {
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
991
  	ext3_fsblk_t o_blocks_count;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
992
993
  	ext3_grpblk_t last;
  	ext3_grpblk_t add;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
  	struct buffer_head * bh;
  	handle_t *handle;
1c2bf374a   Mingming Cao   [PATCH] ext3_fsbl...
996
997
  	int err;
  	unsigned long freed_blocks;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
998
999
1000
  
  	/* We don't need to worry about locking wrt other resizers just
  	 * yet: we're going to revalidate es->s_blocks_count after
96d2a495c   Eric Sandeen   ext3: Replace loc...
1001
  	 * taking the s_resize_lock below. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  	o_blocks_count = le32_to_cpu(es->s_blocks_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
1004
  
  	if (test_opt(sb, DEBUG))
db50d20b1   Namhyung Kim   ext3: Fix debug m...
1005
  		printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK
25985edce   Lucas De Marchi   Fix common misspe...
1006
1007
  		       " up to "E3FSBLK" blocks
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
1010
1011
  		       o_blocks_count, n_blocks_count);
  
  	if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
  		return 0;
fcd5df358   Mingming Cao   [PATCH] Avoid dis...
1012
1013
  	if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
  		printk(KERN_ERR "EXT3-fs: filesystem on %s:"
db50d20b1   Namhyung Kim   ext3: Fix debug m...
1014
1015
  			" too large to resize to "E3FSBLK" blocks safely
  ",
fcd5df358   Mingming Cao   [PATCH] Avoid dis...
1016
1017
  			sb->s_id, n_blocks_count);
  		if (sizeof(sector_t) < 8)
e05b6b524   Harvey Harrison   ext3: replace rem...
1018
  			ext3_warning(sb, __func__,
90c699a9e   Bartlomiej Zolnierkiewicz   block: rename CON...
1019
1020
  			"CONFIG_LBDAF not enabled
  ");
fcd5df358   Mingming Cao   [PATCH] Avoid dis...
1021
1022
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  	if (n_blocks_count < o_blocks_count) {
e05b6b524   Harvey Harrison   ext3: replace rem...
1024
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
1027
1028
1029
1030
1031
1032
1033
  			     "can't shrink FS - resize aborted");
  		return -EBUSY;
  	}
  
  	/* Handle the remaining blocks in the last group only. */
  	last = (o_blocks_count - le32_to_cpu(es->s_first_data_block)) %
  		EXT3_BLOCKS_PER_GROUP(sb);
  
  	if (last == 0) {
e05b6b524   Harvey Harrison   ext3: replace rem...
1034
  		ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
1035
  			     "need to use ext2online to resize further");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
1038
1039
  		return -EPERM;
  	}
  
  	add = EXT3_BLOCKS_PER_GROUP(sb) - last;
32c2d2bc4   Eric Sandeen   [PATCH] more ext3...
1040
  	if (o_blocks_count + add < o_blocks_count) {
e05b6b524   Harvey Harrison   ext3: replace rem...
1041
  		ext3_warning(sb, __func__, "blocks_count overflow");
32c2d2bc4   Eric Sandeen   [PATCH] more ext3...
1042
1043
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044
1045
1046
1047
  	if (o_blocks_count + add > n_blocks_count)
  		add = n_blocks_count - o_blocks_count;
  
  	if (o_blocks_count + add < n_blocks_count)
e05b6b524   Harvey Harrison   ext3: replace rem...
1048
  		ext3_warning(sb, __func__,
43d23f903   Mingming Cao   [PATCH] ext3_fsbl...
1049
1050
  			     "will only finish group ("E3FSBLK
  			     " blocks, %u new)",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
1053
1054
1055
  			     o_blocks_count + add, add);
  
  	/* See if the device is actually as big as what was requested */
  	bh = sb_bread(sb, o_blocks_count + add -1);
  	if (!bh) {
e05b6b524   Harvey Harrison   ext3: replace rem...
1056
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  			     "can't read last block, resize aborted");
  		return -ENOSPC;
  	}
  	brelse(bh);
  
  	/* We will update the superblock, one block bitmap, and
  	 * one group descriptor via ext3_free_blocks().
  	 */
  	handle = ext3_journal_start_sb(sb, 3);
  	if (IS_ERR(handle)) {
  		err = PTR_ERR(handle);
e05b6b524   Harvey Harrison   ext3: replace rem...
1068
  		ext3_warning(sb, __func__, "error %d on journal start",err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1069
1070
  		goto exit_put;
  	}
96d2a495c   Eric Sandeen   ext3: Replace loc...
1071
  	mutex_lock(&EXT3_SB(sb)->s_resize_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1072
  	if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
e05b6b524   Harvey Harrison   ext3: replace rem...
1073
  		ext3_warning(sb, __func__,
9f40668d7   Glauber de Oliveira Costa   [PATCH] ext3: rem...
1074
  			     "multiple resizers run on filesystem!");
96d2a495c   Eric Sandeen   ext3: Replace loc...
1075
  		mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
22a5daf53   Akinobu Mita   ext3: add missing...
1076
  		ext3_journal_stop(handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
1078
1079
1080
1081
1082
  		err = -EBUSY;
  		goto exit_put;
  	}
  
  	if ((err = ext3_journal_get_write_access(handle,
  						 EXT3_SB(sb)->s_sbh))) {
e05b6b524   Harvey Harrison   ext3: replace rem...
1083
  		ext3_warning(sb, __func__,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
  			     "error %d on journal write access", err);
96d2a495c   Eric Sandeen   ext3: Replace loc...
1085
  		mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1086
1087
1088
1089
  		ext3_journal_stop(handle);
  		goto exit_put;
  	}
  	es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
41dc6385b   Namhyung Kim   ext3: Add journal...
1090
  	err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
96d2a495c   Eric Sandeen   ext3: Replace loc...
1091
  	mutex_unlock(&EXT3_SB(sb)->s_resize_lock);
41dc6385b   Namhyung Kim   ext3: Add journal...
1092
1093
1094
1095
1096
1097
  	if (err) {
  		ext3_warning(sb, __func__,
  			     "error %d on journal dirty metadata", err);
  		ext3_journal_stop(handle);
  		goto exit_put;
  	}
db50d20b1   Namhyung Kim   ext3: Fix debug m...
1098
1099
1100
  	ext3_debug("freeing blocks "E3FSBLK" through "E3FSBLK"
  ",
  		   o_blocks_count, o_blocks_count + add);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  	ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
db50d20b1   Namhyung Kim   ext3: Fix debug m...
1102
1103
1104
  	ext3_debug("freed blocks "E3FSBLK" through "E3FSBLK"
  ",
  		   o_blocks_count, o_blocks_count + add);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  	if ((err = ext3_journal_stop(handle)))
  		goto exit_put;
  	if (test_opt(sb, DEBUG))
  		printk(KERN_DEBUG "EXT3-fs: extended group to %u blocks
  ",
  		       le32_to_cpu(es->s_blocks_count));
  	update_backups(sb, EXT3_SB(sb)->s_sbh->b_blocknr, (char *)es,
  		       sizeof(struct ext3_super_block));
  exit_put:
  	return err;
  } /* ext3_group_extend */