aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/resize.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r--fs/ext4/resize.c125
1 files changed, 69 insertions, 56 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index ca5c8aa00a2f..80bbc9c60c24 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -220,29 +220,25 @@ static int setup_new_group_blocks(struct super_block *sb,
220 memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); 220 memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size);
221 set_buffer_uptodate(gdb); 221 set_buffer_uptodate(gdb);
222 unlock_buffer(gdb); 222 unlock_buffer(gdb);
223 ext4_handle_dirty_metadata(handle, NULL, gdb); 223 err = ext4_handle_dirty_metadata(handle, NULL, gdb);
224 if (unlikely(err)) {
225 brelse(gdb);
226 goto exit_bh;
227 }
224 ext4_set_bit(bit, bh->b_data); 228 ext4_set_bit(bit, bh->b_data);
225 brelse(gdb); 229 brelse(gdb);
226 } 230 }
227 231
228 /* Zero out all of the reserved backup group descriptor table blocks */ 232 /* Zero out all of the reserved backup group descriptor table blocks */
229 for (i = 0, bit = gdblocks + 1, block = start + bit; 233 ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",
230 i < reserved_gdb; i++, block++, bit++) { 234 block, sbi->s_itb_per_group);
231 struct buffer_head *gdb; 235 err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb,
232 236 GFP_NOFS);
233 ext4_debug("clear reserved block %#04llx (+%d)\n", block, bit); 237 if (err)
234 238 goto exit_bh;
235 if ((err = extend_or_restart_transaction(handle, 1, bh))) 239 for (i = 0, bit = gdblocks + 1; i < reserved_gdb; i++, bit++)
236 goto exit_bh;
237
238 if (IS_ERR(gdb = bclean(handle, sb, block))) {
239 err = PTR_ERR(gdb);
240 goto exit_bh;
241 }
242 ext4_handle_dirty_metadata(handle, NULL, gdb);
243 ext4_set_bit(bit, bh->b_data); 240 ext4_set_bit(bit, bh->b_data);
244 brelse(gdb); 241
245 }
246 ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap, 242 ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,
247 input->block_bitmap - start); 243 input->block_bitmap - start);
248 ext4_set_bit(input->block_bitmap - start, bh->b_data); 244 ext4_set_bit(input->block_bitmap - start, bh->b_data);
@@ -251,29 +247,26 @@ static int setup_new_group_blocks(struct super_block *sb,
251 ext4_set_bit(input->inode_bitmap - start, bh->b_data); 247 ext4_set_bit(input->inode_bitmap - start, bh->b_data);
252 248
253 /* Zero out all of the inode table blocks */ 249 /* Zero out all of the inode table blocks */
254 for (i = 0, block = input->inode_table, bit = block - start; 250 block = input->inode_table;
255 i < sbi->s_itb_per_group; i++, bit++, block++) { 251 ext4_debug("clear inode table blocks %#04llx -> %#04lx\n",
256 struct buffer_head *it; 252 block, sbi->s_itb_per_group);
257 253 err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);
258 ext4_debug("clear inode block %#04llx (+%d)\n", block, bit); 254 if (err)
259 255 goto exit_bh;
260 if ((err = extend_or_restart_transaction(handle, 1, bh))) 256 for (i = 0, bit = input->inode_table - start;
261 goto exit_bh; 257 i < sbi->s_itb_per_group; i++, bit++)
262
263 if (IS_ERR(it = bclean(handle, sb, block))) {
264 err = PTR_ERR(it);
265 goto exit_bh;
266 }
267 ext4_handle_dirty_metadata(handle, NULL, it);
268 brelse(it);
269 ext4_set_bit(bit, bh->b_data); 258 ext4_set_bit(bit, bh->b_data);
270 }
271 259
272 if ((err = extend_or_restart_transaction(handle, 2, bh))) 260 if ((err = extend_or_restart_transaction(handle, 2, bh)))
273 goto exit_bh; 261 goto exit_bh;
274 262
275 mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8, bh->b_data); 263 ext4_mark_bitmap_end(input->blocks_count, sb->s_blocksize * 8,
276 ext4_handle_dirty_metadata(handle, NULL, bh); 264 bh->b_data);
265 err = ext4_handle_dirty_metadata(handle, NULL, bh);
266 if (unlikely(err)) {
267 ext4_std_error(sb, err);
268 goto exit_bh;
269 }
277 brelse(bh); 270 brelse(bh);
278 /* Mark unused entries in inode bitmap used */ 271 /* Mark unused entries in inode bitmap used */
279 ext4_debug("clear inode bitmap %#04llx (+%llu)\n", 272 ext4_debug("clear inode bitmap %#04llx (+%llu)\n",
@@ -283,9 +276,11 @@ static int setup_new_group_blocks(struct super_block *sb,
283 goto exit_journal; 276 goto exit_journal;
284 } 277 }
285 278
286 mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, 279 ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8,
287 bh->b_data); 280 bh->b_data);
288 ext4_handle_dirty_metadata(handle, NULL, bh); 281 err = ext4_handle_dirty_metadata(handle, NULL, bh);
282 if (unlikely(err))
283 ext4_std_error(sb, err);
289exit_bh: 284exit_bh:
290 brelse(bh); 285 brelse(bh);
291 286
@@ -437,17 +432,21 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
437 goto exit_dind; 432 goto exit_dind;
438 } 433 }
439 434
440 if ((err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh))) 435 err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh);
436 if (unlikely(err))
441 goto exit_dind; 437 goto exit_dind;
442 438
443 if ((err = ext4_journal_get_write_access(handle, *primary))) 439 err = ext4_journal_get_write_access(handle, *primary);
440 if (unlikely(err))
444 goto exit_sbh; 441 goto exit_sbh;
445 442
446 if ((err = ext4_journal_get_write_access(handle, dind))) 443 err = ext4_journal_get_write_access(handle, dind);
447 goto exit_primary; 444 if (unlikely(err))
445 ext4_std_error(sb, err);
448 446
449 /* ext4_reserve_inode_write() gets a reference on the iloc */ 447 /* ext4_reserve_inode_write() gets a reference on the iloc */
450 if ((err = ext4_reserve_inode_write(handle, inode, &iloc))) 448 err = ext4_reserve_inode_write(handle, inode, &iloc);
449 if (unlikely(err))
451 goto exit_dindj; 450 goto exit_dindj;
452 451
453 n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *), 452 n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
@@ -469,12 +468,20 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
469 * reserved inode, and will become GDT blocks (primary and backup). 468 * reserved inode, and will become GDT blocks (primary and backup).
470 */ 469 */
471 data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0; 470 data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)] = 0;
472 ext4_handle_dirty_metadata(handle, NULL, dind); 471 err = ext4_handle_dirty_metadata(handle, NULL, dind);
473 brelse(dind); 472 if (unlikely(err)) {
473 ext4_std_error(sb, err);
474 goto exit_inode;
475 }
474 inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; 476 inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
475 ext4_mark_iloc_dirty(handle, inode, &iloc); 477 ext4_mark_iloc_dirty(handle, inode, &iloc);
476 memset((*primary)->b_data, 0, sb->s_blocksize); 478 memset((*primary)->b_data, 0, sb->s_blocksize);
477 ext4_handle_dirty_metadata(handle, NULL, *primary); 479 err = ext4_handle_dirty_metadata(handle, NULL, *primary);
480 if (unlikely(err)) {
481 ext4_std_error(sb, err);
482 goto exit_inode;
483 }
484 brelse(dind);
478 485
479 o_group_desc = EXT4_SB(sb)->s_group_desc; 486 o_group_desc = EXT4_SB(sb)->s_group_desc;
480 memcpy(n_group_desc, o_group_desc, 487 memcpy(n_group_desc, o_group_desc,
@@ -485,19 +492,19 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
485 kfree(o_group_desc); 492 kfree(o_group_desc);
486 493
487 le16_add_cpu(&es->s_reserved_gdt_blocks, -1); 494 le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
488 ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); 495 err = ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh);
496 if (err)
497 ext4_std_error(sb, err);
489 498
490 return 0; 499 return err;
491 500
492exit_inode: 501exit_inode:
493 /* ext4_journal_release_buffer(handle, iloc.bh); */ 502 /* ext4_handle_release_buffer(handle, iloc.bh); */
494 brelse(iloc.bh); 503 brelse(iloc.bh);
495exit_dindj: 504exit_dindj:
496 /* ext4_journal_release_buffer(handle, dind); */ 505 /* ext4_handle_release_buffer(handle, dind); */
497exit_primary:
498 /* ext4_journal_release_buffer(handle, *primary); */
499exit_sbh: 506exit_sbh:
500 /* ext4_journal_release_buffer(handle, *primary); */ 507 /* ext4_handle_release_buffer(handle, EXT4_SB(sb)->s_sbh); */
501exit_dind: 508exit_dind:
502 brelse(dind); 509 brelse(dind);
503exit_bh: 510exit_bh:
@@ -579,7 +586,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
579 /* 586 /*
580 int j; 587 int j;
581 for (j = 0; j < i; j++) 588 for (j = 0; j < i; j++)
582 ext4_journal_release_buffer(handle, primary[j]); 589 ext4_handle_release_buffer(handle, primary[j]);
583 */ 590 */
584 goto exit_bh; 591 goto exit_bh;
585 } 592 }
@@ -680,7 +687,9 @@ static void update_backups(struct super_block *sb,
680 memset(bh->b_data + size, 0, rest); 687 memset(bh->b_data + size, 0, rest);
681 set_buffer_uptodate(bh); 688 set_buffer_uptodate(bh);
682 unlock_buffer(bh); 689 unlock_buffer(bh);
683 ext4_handle_dirty_metadata(handle, NULL, bh); 690 err = ext4_handle_dirty_metadata(handle, NULL, bh);
691 if (unlikely(err))
692 ext4_std_error(sb, err);
684 brelse(bh); 693 brelse(bh);
685 } 694 }
686 if ((err2 = ext4_journal_stop(handle)) && !err) 695 if ((err2 = ext4_journal_stop(handle)) && !err)
@@ -898,7 +907,11 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
898 /* Update the global fs size fields */ 907 /* Update the global fs size fields */
899 sbi->s_groups_count++; 908 sbi->s_groups_count++;
900 909
901 ext4_handle_dirty_metadata(handle, NULL, primary); 910 err = ext4_handle_dirty_metadata(handle, NULL, primary);
911 if (unlikely(err)) {
912 ext4_std_error(sb, err);
913 goto exit_journal;
914 }
902 915
903 /* Update the reserved block counts only once the new group is 916 /* Update the reserved block counts only once the new group is
904 * active. */ 917 * active. */