diff options
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r-- | fs/ext4/resize.c | 125 |
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); | ||
289 | exit_bh: | 284 | exit_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 | ||
492 | exit_inode: | 501 | exit_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); |
495 | exit_dindj: | 504 | exit_dindj: |
496 | /* ext4_journal_release_buffer(handle, dind); */ | 505 | /* ext4_handle_release_buffer(handle, dind); */ |
497 | exit_primary: | ||
498 | /* ext4_journal_release_buffer(handle, *primary); */ | ||
499 | exit_sbh: | 506 | exit_sbh: |
500 | /* ext4_journal_release_buffer(handle, *primary); */ | 507 | /* ext4_handle_release_buffer(handle, EXT4_SB(sb)->s_sbh); */ |
501 | exit_dind: | 508 | exit_dind: |
502 | brelse(dind); | 509 | brelse(dind); |
503 | exit_bh: | 510 | exit_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. */ |