aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/resize.c39
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 */
396static int add_new_gdb(handle_t *handle, struct inode *inode, 396static 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:
525exit_dind: 526exit_dind:
526 brelse(dind); 527 brelse(dind);
527exit_bh: 528exit_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)
944exit_journal: 953exit_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,