diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/resize.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 65e5cb6c094d..9e453552f10e 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -394,15 +394,15 @@ static int verify_reserved_gdb(struct super_block *sb, | |||
394 | * fail once we start modifying the data on disk, because JBD has no rollback. | 394 | * fail once we start modifying the data on disk, because JBD has no rollback. |
395 | */ | 395 | */ |
396 | static int add_new_gdb(handle_t *handle, struct inode *inode, | 396 | static int add_new_gdb(handle_t *handle, struct inode *inode, |
397 | struct ext4_new_group_data *input, | 397 | ext4_group_t group) |
398 | struct buffer_head **primary) | ||
399 | { | 398 | { |
400 | struct super_block *sb = inode->i_sb; | 399 | struct super_block *sb = inode->i_sb; |
401 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 400 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
402 | unsigned long gdb_num = input->group / EXT4_DESC_PER_BLOCK(sb); | 401 | unsigned long gdb_num = group / EXT4_DESC_PER_BLOCK(sb); |
403 | ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num; | 402 | ext4_fsblk_t gdblock = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num; |
404 | struct buffer_head **o_group_desc, **n_group_desc; | 403 | struct buffer_head **o_group_desc, **n_group_desc; |
405 | struct buffer_head *dind; | 404 | struct buffer_head *dind; |
405 | struct buffer_head *gdb_bh; | ||
406 | int gdbackups; | 406 | int gdbackups; |
407 | struct ext4_iloc iloc; | 407 | struct ext4_iloc iloc; |
408 | __le32 *data; | 408 | __le32 *data; |
@@ -425,11 +425,12 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
425 | return -EPERM; | 425 | return -EPERM; |
426 | } | 426 | } |
427 | 427 | ||
428 | *primary = sb_bread(sb, gdblock); | 428 | gdb_bh = sb_bread(sb, gdblock); |
429 | if (!*primary) | 429 | if (!gdb_bh) |
430 | return -EIO; | 430 | return -EIO; |
431 | 431 | ||
432 | if ((gdbackups = verify_reserved_gdb(sb, *primary)) < 0) { | 432 | gdbackups = verify_reserved_gdb(sb, gdb_bh); |
433 | if (gdbackups < 0) { | ||
433 | err = gdbackups; | 434 | err = gdbackups; |
434 | goto exit_bh; | 435 | goto exit_bh; |
435 | } | 436 | } |
@@ -444,7 +445,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
444 | data = (__le32 *)dind->b_data; | 445 | data = (__le32 *)dind->b_data; |
445 | if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) { | 446 | if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) { |
446 | ext4_warning(sb, "new group %u GDT block %llu not reserved", | 447 | ext4_warning(sb, "new group %u GDT block %llu not reserved", |
447 | input->group, gdblock); | 448 | group, gdblock); |
448 | err = -EINVAL; | 449 | err = -EINVAL; |
449 | goto exit_dind; | 450 | goto exit_dind; |
450 | } | 451 | } |
@@ -453,7 +454,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
453 | if (unlikely(err)) | 454 | if (unlikely(err)) |
454 | goto exit_dind; | 455 | goto exit_dind; |
455 | 456 | ||
456 | err = ext4_journal_get_write_access(handle, *primary); | 457 | err = ext4_journal_get_write_access(handle, gdb_bh); |
457 | if (unlikely(err)) | 458 | if (unlikely(err)) |
458 | goto exit_sbh; | 459 | goto exit_sbh; |
459 | 460 | ||
@@ -492,8 +493,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
492 | } | 493 | } |
493 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; | 494 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; |
494 | ext4_mark_iloc_dirty(handle, inode, &iloc); | 495 | ext4_mark_iloc_dirty(handle, inode, &iloc); |
495 | memset((*primary)->b_data, 0, sb->s_blocksize); | 496 | memset(gdb_bh->b_data, 0, sb->s_blocksize); |
496 | err = ext4_handle_dirty_metadata(handle, NULL, *primary); | 497 | err = ext4_handle_dirty_metadata(handle, NULL, gdb_bh); |
497 | if (unlikely(err)) { | 498 | if (unlikely(err)) { |
498 | ext4_std_error(sb, err); | 499 | ext4_std_error(sb, err); |
499 | goto exit_inode; | 500 | goto exit_inode; |
@@ -503,7 +504,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
503 | o_group_desc = EXT4_SB(sb)->s_group_desc; | 504 | o_group_desc = EXT4_SB(sb)->s_group_desc; |
504 | memcpy(n_group_desc, o_group_desc, | 505 | memcpy(n_group_desc, o_group_desc, |
505 | EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); | 506 | EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); |
506 | n_group_desc[gdb_num] = *primary; | 507 | n_group_desc[gdb_num] = gdb_bh; |
507 | EXT4_SB(sb)->s_group_desc = n_group_desc; | 508 | EXT4_SB(sb)->s_group_desc = n_group_desc; |
508 | EXT4_SB(sb)->s_gdb_count++; | 509 | EXT4_SB(sb)->s_gdb_count++; |
509 | kfree(o_group_desc); | 510 | kfree(o_group_desc); |
@@ -525,7 +526,7 @@ exit_sbh: | |||
525 | exit_dind: | 526 | exit_dind: |
526 | brelse(dind); | 527 | brelse(dind); |
527 | exit_bh: | 528 | exit_bh: |
528 | brelse(*primary); | 529 | brelse(gdb_bh); |
529 | 530 | ||
530 | ext4_debug("leaving with error %d\n", err); | 531 | ext4_debug("leaving with error %d\n", err); |
531 | return err; | 532 | return err; |
@@ -833,8 +834,16 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
833 | if (reserved_gdb && ext4_bg_num_gdb(sb, input->group) && | 834 | if (reserved_gdb && ext4_bg_num_gdb(sb, input->group) && |
834 | (err = reserve_backup_gdb(handle, inode, input))) | 835 | (err = reserve_backup_gdb(handle, inode, input))) |
835 | goto exit_journal; | 836 | goto exit_journal; |
836 | } else if ((err = add_new_gdb(handle, inode, input, &primary))) | 837 | } else { |
837 | goto exit_journal; | 838 | /* |
839 | * Note that we can access new group descriptor block safely | ||
840 | * only if add_new_gdb() succeeds. | ||
841 | */ | ||
842 | err = add_new_gdb(handle, inode, input->group); | ||
843 | if (err) | ||
844 | goto exit_journal; | ||
845 | primary = sbi->s_group_desc[gdb_num]; | ||
846 | } | ||
838 | 847 | ||
839 | /* | 848 | /* |
840 | * OK, now we've set up the new group. Time to make it active. | 849 | * OK, now we've set up the new group. Time to make it active. |
@@ -944,7 +953,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
944 | exit_journal: | 953 | exit_journal: |
945 | if ((err2 = ext4_journal_stop(handle)) && !err) | 954 | if ((err2 = ext4_journal_stop(handle)) && !err) |
946 | err = err2; | 955 | err = err2; |
947 | if (!err) { | 956 | if (!err && primary) { |
948 | update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, | 957 | update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, |
949 | sizeof(struct ext4_super_block)); | 958 | sizeof(struct ext4_super_block)); |
950 | update_backups(sb, primary->b_blocknr, primary->b_data, | 959 | update_backups(sb, primary->b_blocknr, primary->b_data, |