diff options
Diffstat (limited to 'fs/ext4/resize.c')
| -rw-r--r-- | fs/ext4/resize.c | 102 |
1 files changed, 38 insertions, 64 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3b2c5541d8a6..5692c48754a0 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -48,65 +48,54 @@ static int verify_group_input(struct super_block *sb, | |||
| 48 | 48 | ||
| 49 | ext4_get_group_no_and_offset(sb, start, NULL, &offset); | 49 | ext4_get_group_no_and_offset(sb, start, NULL, &offset); |
| 50 | if (group != sbi->s_groups_count) | 50 | if (group != sbi->s_groups_count) |
| 51 | ext4_warning(sb, __func__, | 51 | ext4_warning(sb, "Cannot add at group %u (only %u groups)", |
| 52 | "Cannot add at group %u (only %u groups)", | ||
| 53 | input->group, sbi->s_groups_count); | 52 | input->group, sbi->s_groups_count); |
| 54 | else if (offset != 0) | 53 | else if (offset != 0) |
| 55 | ext4_warning(sb, __func__, "Last group not full"); | 54 | ext4_warning(sb, "Last group not full"); |
| 56 | else if (input->reserved_blocks > input->blocks_count / 5) | 55 | else if (input->reserved_blocks > input->blocks_count / 5) |
| 57 | ext4_warning(sb, __func__, "Reserved blocks too high (%u)", | 56 | ext4_warning(sb, "Reserved blocks too high (%u)", |
| 58 | input->reserved_blocks); | 57 | input->reserved_blocks); |
| 59 | else if (free_blocks_count < 0) | 58 | else if (free_blocks_count < 0) |
| 60 | ext4_warning(sb, __func__, "Bad blocks count %u", | 59 | ext4_warning(sb, "Bad blocks count %u", |
| 61 | input->blocks_count); | 60 | input->blocks_count); |
| 62 | else if (!(bh = sb_bread(sb, end - 1))) | 61 | else if (!(bh = sb_bread(sb, end - 1))) |
| 63 | ext4_warning(sb, __func__, | 62 | ext4_warning(sb, "Cannot read last block (%llu)", |
| 64 | "Cannot read last block (%llu)", | ||
| 65 | end - 1); | 63 | end - 1); |
| 66 | else if (outside(input->block_bitmap, start, end)) | 64 | else if (outside(input->block_bitmap, start, end)) |
| 67 | ext4_warning(sb, __func__, | 65 | ext4_warning(sb, "Block bitmap not in group (block %llu)", |
| 68 | "Block bitmap not in group (block %llu)", | ||
| 69 | (unsigned long long)input->block_bitmap); | 66 | (unsigned long long)input->block_bitmap); |
| 70 | else if (outside(input->inode_bitmap, start, end)) | 67 | else if (outside(input->inode_bitmap, start, end)) |
| 71 | ext4_warning(sb, __func__, | 68 | ext4_warning(sb, "Inode bitmap not in group (block %llu)", |
| 72 | "Inode bitmap not in group (block %llu)", | ||
| 73 | (unsigned long long)input->inode_bitmap); | 69 | (unsigned long long)input->inode_bitmap); |
| 74 | else if (outside(input->inode_table, start, end) || | 70 | else if (outside(input->inode_table, start, end) || |
| 75 | outside(itend - 1, start, end)) | 71 | outside(itend - 1, start, end)) |
| 76 | ext4_warning(sb, __func__, | 72 | ext4_warning(sb, "Inode table not in group (blocks %llu-%llu)", |
| 77 | "Inode table not in group (blocks %llu-%llu)", | ||
| 78 | (unsigned long long)input->inode_table, itend - 1); | 73 | (unsigned long long)input->inode_table, itend - 1); |
| 79 | else if (input->inode_bitmap == input->block_bitmap) | 74 | else if (input->inode_bitmap == input->block_bitmap) |
| 80 | ext4_warning(sb, __func__, | 75 | ext4_warning(sb, "Block bitmap same as inode bitmap (%llu)", |
| 81 | "Block bitmap same as inode bitmap (%llu)", | ||
| 82 | (unsigned long long)input->block_bitmap); | 76 | (unsigned long long)input->block_bitmap); |
| 83 | else if (inside(input->block_bitmap, input->inode_table, itend)) | 77 | else if (inside(input->block_bitmap, input->inode_table, itend)) |
| 84 | ext4_warning(sb, __func__, | 78 | ext4_warning(sb, "Block bitmap (%llu) in inode table " |
| 85 | "Block bitmap (%llu) in inode table (%llu-%llu)", | 79 | "(%llu-%llu)", |
| 86 | (unsigned long long)input->block_bitmap, | 80 | (unsigned long long)input->block_bitmap, |
| 87 | (unsigned long long)input->inode_table, itend - 1); | 81 | (unsigned long long)input->inode_table, itend - 1); |
| 88 | else if (inside(input->inode_bitmap, input->inode_table, itend)) | 82 | else if (inside(input->inode_bitmap, input->inode_table, itend)) |
| 89 | ext4_warning(sb, __func__, | 83 | ext4_warning(sb, "Inode bitmap (%llu) in inode table " |
| 90 | "Inode bitmap (%llu) in inode table (%llu-%llu)", | 84 | "(%llu-%llu)", |
| 91 | (unsigned long long)input->inode_bitmap, | 85 | (unsigned long long)input->inode_bitmap, |
| 92 | (unsigned long long)input->inode_table, itend - 1); | 86 | (unsigned long long)input->inode_table, itend - 1); |
| 93 | else if (inside(input->block_bitmap, start, metaend)) | 87 | else if (inside(input->block_bitmap, start, metaend)) |
| 94 | ext4_warning(sb, __func__, | 88 | ext4_warning(sb, "Block bitmap (%llu) in GDT table (%llu-%llu)", |
| 95 | "Block bitmap (%llu) in GDT table" | ||
| 96 | " (%llu-%llu)", | ||
| 97 | (unsigned long long)input->block_bitmap, | 89 | (unsigned long long)input->block_bitmap, |
| 98 | start, metaend - 1); | 90 | start, metaend - 1); |
| 99 | else if (inside(input->inode_bitmap, start, metaend)) | 91 | else if (inside(input->inode_bitmap, start, metaend)) |
| 100 | ext4_warning(sb, __func__, | 92 | ext4_warning(sb, "Inode bitmap (%llu) in GDT table (%llu-%llu)", |
| 101 | "Inode bitmap (%llu) in GDT table" | ||
| 102 | " (%llu-%llu)", | ||
| 103 | (unsigned long long)input->inode_bitmap, | 93 | (unsigned long long)input->inode_bitmap, |
| 104 | start, metaend - 1); | 94 | start, metaend - 1); |
| 105 | else if (inside(input->inode_table, start, metaend) || | 95 | else if (inside(input->inode_table, start, metaend) || |
| 106 | inside(itend - 1, start, metaend)) | 96 | inside(itend - 1, start, metaend)) |
| 107 | ext4_warning(sb, __func__, | 97 | ext4_warning(sb, "Inode table (%llu-%llu) overlaps GDT table " |
| 108 | "Inode table (%llu-%llu) overlaps" | 98 | "(%llu-%llu)", |
| 109 | "GDT table (%llu-%llu)", | ||
| 110 | (unsigned long long)input->inode_table, | 99 | (unsigned long long)input->inode_table, |
| 111 | itend - 1, start, metaend - 1); | 100 | itend - 1, start, metaend - 1); |
| 112 | else | 101 | else |
| @@ -364,8 +353,7 @@ static int verify_reserved_gdb(struct super_block *sb, | |||
| 364 | while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) { | 353 | while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) { |
| 365 | if (le32_to_cpu(*p++) != | 354 | if (le32_to_cpu(*p++) != |
| 366 | grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){ | 355 | grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){ |
| 367 | ext4_warning(sb, __func__, | 356 | ext4_warning(sb, "reserved GDT %llu" |
| 368 | "reserved GDT %llu" | ||
| 369 | " missing grp %d (%llu)", | 357 | " missing grp %d (%llu)", |
| 370 | blk, grp, | 358 | blk, grp, |
| 371 | grp * | 359 | grp * |
| @@ -420,8 +408,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
| 420 | */ | 408 | */ |
| 421 | if (EXT4_SB(sb)->s_sbh->b_blocknr != | 409 | if (EXT4_SB(sb)->s_sbh->b_blocknr != |
| 422 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) { | 410 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) { |
| 423 | ext4_warning(sb, __func__, | 411 | ext4_warning(sb, "won't resize using backup superblock at %llu", |
| 424 | "won't resize using backup superblock at %llu", | ||
| 425 | (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr); | 412 | (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr); |
| 426 | return -EPERM; | 413 | return -EPERM; |
| 427 | } | 414 | } |
| @@ -444,8 +431,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
| 444 | 431 | ||
| 445 | data = (__le32 *)dind->b_data; | 432 | data = (__le32 *)dind->b_data; |
| 446 | if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) { | 433 | if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) { |
| 447 | ext4_warning(sb, __func__, | 434 | ext4_warning(sb, "new group %u GDT block %llu not reserved", |
| 448 | "new group %u GDT block %llu not reserved", | ||
| 449 | input->group, gdblock); | 435 | input->group, gdblock); |
| 450 | err = -EINVAL; | 436 | err = -EINVAL; |
| 451 | goto exit_dind; | 437 | goto exit_dind; |
| @@ -468,7 +454,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
| 468 | GFP_NOFS); | 454 | GFP_NOFS); |
| 469 | if (!n_group_desc) { | 455 | if (!n_group_desc) { |
| 470 | err = -ENOMEM; | 456 | err = -ENOMEM; |
| 471 | ext4_warning(sb, __func__, | 457 | ext4_warning(sb, |
| 472 | "not enough memory for %lu groups", gdb_num + 1); | 458 | "not enough memory for %lu groups", gdb_num + 1); |
| 473 | goto exit_inode; | 459 | goto exit_inode; |
| 474 | } | 460 | } |
| @@ -567,8 +553,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, | |||
| 567 | /* Get each reserved primary GDT block and verify it holds backups */ | 553 | /* Get each reserved primary GDT block and verify it holds backups */ |
| 568 | for (res = 0; res < reserved_gdb; res++, blk++) { | 554 | for (res = 0; res < reserved_gdb; res++, blk++) { |
| 569 | if (le32_to_cpu(*data) != blk) { | 555 | if (le32_to_cpu(*data) != blk) { |
| 570 | ext4_warning(sb, __func__, | 556 | ext4_warning(sb, "reserved block %llu" |
| 571 | "reserved block %llu" | ||
| 572 | " not at offset %ld", | 557 | " not at offset %ld", |
| 573 | blk, | 558 | blk, |
| 574 | (long)(data - (__le32 *)dind->b_data)); | 559 | (long)(data - (__le32 *)dind->b_data)); |
| @@ -713,8 +698,7 @@ static void update_backups(struct super_block *sb, | |||
| 713 | */ | 698 | */ |
| 714 | exit_err: | 699 | exit_err: |
| 715 | if (err) { | 700 | if (err) { |
| 716 | ext4_warning(sb, __func__, | 701 | ext4_warning(sb, "can't update backup for group %u (err %d), " |
| 717 | "can't update backup for group %u (err %d), " | ||
| 718 | "forcing fsck on next reboot", group, err); | 702 | "forcing fsck on next reboot", group, err); |
| 719 | sbi->s_mount_state &= ~EXT4_VALID_FS; | 703 | sbi->s_mount_state &= ~EXT4_VALID_FS; |
| 720 | sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); | 704 | sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); |
| @@ -753,20 +737,19 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
| 753 | 737 | ||
| 754 | if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb, | 738 | if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb, |
| 755 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) { | 739 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) { |
| 756 | ext4_warning(sb, __func__, | 740 | ext4_warning(sb, "Can't resize non-sparse filesystem further"); |
| 757 | "Can't resize non-sparse filesystem further"); | ||
| 758 | return -EPERM; | 741 | return -EPERM; |
| 759 | } | 742 | } |
| 760 | 743 | ||
| 761 | if (ext4_blocks_count(es) + input->blocks_count < | 744 | if (ext4_blocks_count(es) + input->blocks_count < |
| 762 | ext4_blocks_count(es)) { | 745 | ext4_blocks_count(es)) { |
| 763 | ext4_warning(sb, __func__, "blocks_count overflow"); | 746 | ext4_warning(sb, "blocks_count overflow"); |
| 764 | return -EINVAL; | 747 | return -EINVAL; |
| 765 | } | 748 | } |
| 766 | 749 | ||
| 767 | if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) < | 750 | if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) < |
| 768 | le32_to_cpu(es->s_inodes_count)) { | 751 | le32_to_cpu(es->s_inodes_count)) { |
| 769 | ext4_warning(sb, __func__, "inodes_count overflow"); | 752 | ext4_warning(sb, "inodes_count overflow"); |
| 770 | return -EINVAL; | 753 | return -EINVAL; |
| 771 | } | 754 | } |
| 772 | 755 | ||
| @@ -774,14 +757,13 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
| 774 | if (!EXT4_HAS_COMPAT_FEATURE(sb, | 757 | if (!EXT4_HAS_COMPAT_FEATURE(sb, |
| 775 | EXT4_FEATURE_COMPAT_RESIZE_INODE) | 758 | EXT4_FEATURE_COMPAT_RESIZE_INODE) |
| 776 | || !le16_to_cpu(es->s_reserved_gdt_blocks)) { | 759 | || !le16_to_cpu(es->s_reserved_gdt_blocks)) { |
| 777 | ext4_warning(sb, __func__, | 760 | ext4_warning(sb, |
| 778 | "No reserved GDT blocks, can't resize"); | 761 | "No reserved GDT blocks, can't resize"); |
| 779 | return -EPERM; | 762 | return -EPERM; |
| 780 | } | 763 | } |
| 781 | inode = ext4_iget(sb, EXT4_RESIZE_INO); | 764 | inode = ext4_iget(sb, EXT4_RESIZE_INO); |
| 782 | if (IS_ERR(inode)) { | 765 | if (IS_ERR(inode)) { |
| 783 | ext4_warning(sb, __func__, | 766 | ext4_warning(sb, "Error opening resize inode"); |
| 784 | "Error opening resize inode"); | ||
| 785 | return PTR_ERR(inode); | 767 | return PTR_ERR(inode); |
| 786 | } | 768 | } |
| 787 | } | 769 | } |
| @@ -810,8 +792,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
| 810 | 792 | ||
| 811 | mutex_lock(&sbi->s_resize_lock); | 793 | mutex_lock(&sbi->s_resize_lock); |
| 812 | if (input->group != sbi->s_groups_count) { | 794 | if (input->group != sbi->s_groups_count) { |
| 813 | ext4_warning(sb, __func__, | 795 | ext4_warning(sb, "multiple resizers run on filesystem!"); |
| 814 | "multiple resizers run on filesystem!"); | ||
| 815 | err = -EBUSY; | 796 | err = -EBUSY; |
| 816 | goto exit_journal; | 797 | goto exit_journal; |
| 817 | } | 798 | } |
| @@ -997,13 +978,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
| 997 | " too large to resize to %llu blocks safely\n", | 978 | " too large to resize to %llu blocks safely\n", |
| 998 | sb->s_id, n_blocks_count); | 979 | sb->s_id, n_blocks_count); |
| 999 | if (sizeof(sector_t) < 8) | 980 | if (sizeof(sector_t) < 8) |
| 1000 | ext4_warning(sb, __func__, "CONFIG_LBDAF not enabled"); | 981 | ext4_warning(sb, "CONFIG_LBDAF not enabled"); |
| 1001 | return -EINVAL; | 982 | return -EINVAL; |
| 1002 | } | 983 | } |
| 1003 | 984 | ||
| 1004 | if (n_blocks_count < o_blocks_count) { | 985 | if (n_blocks_count < o_blocks_count) { |
| 1005 | ext4_warning(sb, __func__, | 986 | ext4_warning(sb, "can't shrink FS - resize aborted"); |
| 1006 | "can't shrink FS - resize aborted"); | ||
| 1007 | return -EBUSY; | 987 | return -EBUSY; |
| 1008 | } | 988 | } |
| 1009 | 989 | ||
| @@ -1011,15 +991,14 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
| 1011 | ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last); | 991 | ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last); |
| 1012 | 992 | ||
| 1013 | if (last == 0) { | 993 | if (last == 0) { |
| 1014 | ext4_warning(sb, __func__, | 994 | ext4_warning(sb, "need to use ext2online to resize further"); |
| 1015 | "need to use ext2online to resize further"); | ||
| 1016 | return -EPERM; | 995 | return -EPERM; |
| 1017 | } | 996 | } |
| 1018 | 997 | ||
| 1019 | add = EXT4_BLOCKS_PER_GROUP(sb) - last; | 998 | add = EXT4_BLOCKS_PER_GROUP(sb) - last; |
| 1020 | 999 | ||
| 1021 | if (o_blocks_count + add < o_blocks_count) { | 1000 | if (o_blocks_count + add < o_blocks_count) { |
| 1022 | ext4_warning(sb, __func__, "blocks_count overflow"); | 1001 | ext4_warning(sb, "blocks_count overflow"); |
| 1023 | return -EINVAL; | 1002 | return -EINVAL; |
| 1024 | } | 1003 | } |
| 1025 | 1004 | ||
| @@ -1027,16 +1006,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
| 1027 | add = n_blocks_count - o_blocks_count; | 1006 | add = n_blocks_count - o_blocks_count; |
| 1028 | 1007 | ||
| 1029 | if (o_blocks_count + add < n_blocks_count) | 1008 | if (o_blocks_count + add < n_blocks_count) |
| 1030 | ext4_warning(sb, __func__, | 1009 | ext4_warning(sb, "will only finish group (%llu blocks, %u new)", |
| 1031 | "will only finish group (%llu" | ||
| 1032 | " blocks, %u new)", | ||
| 1033 | o_blocks_count + add, add); | 1010 | o_blocks_count + add, add); |
| 1034 | 1011 | ||
| 1035 | /* See if the device is actually as big as what was requested */ | 1012 | /* See if the device is actually as big as what was requested */ |
| 1036 | bh = sb_bread(sb, o_blocks_count + add - 1); | 1013 | bh = sb_bread(sb, o_blocks_count + add - 1); |
| 1037 | if (!bh) { | 1014 | if (!bh) { |
| 1038 | ext4_warning(sb, __func__, | 1015 | ext4_warning(sb, "can't read last block, resize aborted"); |
| 1039 | "can't read last block, resize aborted"); | ||
| 1040 | return -ENOSPC; | 1016 | return -ENOSPC; |
| 1041 | } | 1017 | } |
| 1042 | brelse(bh); | 1018 | brelse(bh); |
| @@ -1047,14 +1023,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
| 1047 | handle = ext4_journal_start_sb(sb, 3); | 1023 | handle = ext4_journal_start_sb(sb, 3); |
| 1048 | if (IS_ERR(handle)) { | 1024 | if (IS_ERR(handle)) { |
| 1049 | err = PTR_ERR(handle); | 1025 | err = PTR_ERR(handle); |
| 1050 | ext4_warning(sb, __func__, "error %d on journal start", err); | 1026 | ext4_warning(sb, "error %d on journal start", err); |
| 1051 | goto exit_put; | 1027 | goto exit_put; |
| 1052 | } | 1028 | } |
| 1053 | 1029 | ||
| 1054 | mutex_lock(&EXT4_SB(sb)->s_resize_lock); | 1030 | mutex_lock(&EXT4_SB(sb)->s_resize_lock); |
| 1055 | if (o_blocks_count != ext4_blocks_count(es)) { | 1031 | if (o_blocks_count != ext4_blocks_count(es)) { |
| 1056 | ext4_warning(sb, __func__, | 1032 | ext4_warning(sb, "multiple resizers run on filesystem!"); |
| 1057 | "multiple resizers run on filesystem!"); | ||
| 1058 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); | 1033 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); |
| 1059 | ext4_journal_stop(handle); | 1034 | ext4_journal_stop(handle); |
| 1060 | err = -EBUSY; | 1035 | err = -EBUSY; |
| @@ -1063,8 +1038,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
| 1063 | 1038 | ||
| 1064 | if ((err = ext4_journal_get_write_access(handle, | 1039 | if ((err = ext4_journal_get_write_access(handle, |
| 1065 | EXT4_SB(sb)->s_sbh))) { | 1040 | EXT4_SB(sb)->s_sbh))) { |
| 1066 | ext4_warning(sb, __func__, | 1041 | ext4_warning(sb, "error %d on journal write access", err); |
| 1067 | "error %d on journal write access", err); | ||
| 1068 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); | 1042 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); |
| 1069 | ext4_journal_stop(handle); | 1043 | ext4_journal_stop(handle); |
| 1070 | goto exit_put; | 1044 | goto exit_put; |
