aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ioctl.c15
-rw-r--r--fs/ext4/resize.c215
2 files changed, 165 insertions, 65 deletions
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 7f7dad787603..8b84fe28ccaf 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -365,26 +365,11 @@ group_add_out:
365 return -EOPNOTSUPP; 365 return -EOPNOTSUPP;
366 } 366 }
367 367
368 if (EXT4_HAS_INCOMPAT_FEATURE(sb,
369 EXT4_FEATURE_INCOMPAT_META_BG)) {
370 ext4_msg(sb, KERN_ERR,
371 "Online resizing not (yet) supported with meta_bg");
372 return -EOPNOTSUPP;
373 }
374
375 if (copy_from_user(&n_blocks_count, (__u64 __user *)arg, 368 if (copy_from_user(&n_blocks_count, (__u64 __user *)arg,
376 sizeof(__u64))) { 369 sizeof(__u64))) {
377 return -EFAULT; 370 return -EFAULT;
378 } 371 }
379 372
380 if (n_blocks_count > MAX_32_NUM &&
381 !EXT4_HAS_INCOMPAT_FEATURE(sb,
382 EXT4_FEATURE_INCOMPAT_64BIT)) {
383 ext4_msg(sb, KERN_ERR,
384 "File system only supports 32-bit block numbers");
385 return -EOPNOTSUPP;
386 }
387
388 err = ext4_resize_begin(sb); 373 err = ext4_resize_begin(sb);
389 if (err) 374 if (err)
390 return err; 375 return err;
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index f288933bf4c0..7adc08854588 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -45,6 +45,28 @@ void ext4_resize_end(struct super_block *sb)
45 smp_mb__after_clear_bit(); 45 smp_mb__after_clear_bit();
46} 46}
47 47
48static ext4_group_t ext4_meta_bg_first_group(struct super_block *sb,
49 ext4_group_t group) {
50 return (group >> EXT4_DESC_PER_BLOCK_BITS(sb)) <<
51 EXT4_DESC_PER_BLOCK_BITS(sb);
52}
53
54static ext4_fsblk_t ext4_meta_bg_first_block_no(struct super_block *sb,
55 ext4_group_t group) {
56 group = ext4_meta_bg_first_group(sb, group);
57 return ext4_group_first_block_no(sb, group);
58}
59
60static ext4_grpblk_t ext4_group_overhead_blocks(struct super_block *sb,
61 ext4_group_t group) {
62 ext4_grpblk_t overhead;
63 overhead = ext4_bg_num_gdb(sb, group);
64 if (ext4_bg_has_super(sb, group))
65 overhead += 1 +
66 le16_to_cpu(EXT4_SB(sb)->s_es->s_reserved_gdt_blocks);
67 return overhead;
68}
69
48#define outside(b, first, last) ((b) < (first) || (b) >= (last)) 70#define outside(b, first, last) ((b) < (first) || (b) >= (last))
49#define inside(b, first, last) ((b) >= (first) && (b) < (last)) 71#define inside(b, first, last) ((b) >= (first) && (b) < (last))
50 72
@@ -57,9 +79,7 @@ static int verify_group_input(struct super_block *sb,
57 ext4_fsblk_t end = start + input->blocks_count; 79 ext4_fsblk_t end = start + input->blocks_count;
58 ext4_group_t group = input->group; 80 ext4_group_t group = input->group;
59 ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group; 81 ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
60 unsigned overhead = ext4_bg_has_super(sb, group) ? 82 unsigned overhead = ext4_group_overhead_blocks(sb, group);
61 (1 + ext4_bg_num_gdb(sb, group) +
62 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
63 ext4_fsblk_t metaend = start + overhead; 83 ext4_fsblk_t metaend = start + overhead;
64 struct buffer_head *bh = NULL; 84 struct buffer_head *bh = NULL;
65 ext4_grpblk_t free_blocks_count, offset; 85 ext4_grpblk_t free_blocks_count, offset;
@@ -209,7 +229,6 @@ static int ext4_alloc_group_tables(struct super_block *sb,
209 int flexbg_size) 229 int flexbg_size)
210{ 230{
211 struct ext4_new_group_data *group_data = flex_gd->groups; 231 struct ext4_new_group_data *group_data = flex_gd->groups;
212 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
213 ext4_fsblk_t start_blk; 232 ext4_fsblk_t start_blk;
214 ext4_fsblk_t last_blk; 233 ext4_fsblk_t last_blk;
215 ext4_group_t src_group; 234 ext4_group_t src_group;
@@ -234,19 +253,19 @@ next_group:
234 start_blk = ext4_group_first_block_no(sb, src_group); 253 start_blk = ext4_group_first_block_no(sb, src_group);
235 last_blk = start_blk + group_data[src_group - group].blocks_count; 254 last_blk = start_blk + group_data[src_group - group].blocks_count;
236 255
237 overhead = ext4_bg_has_super(sb, src_group) ? 256 overhead = ext4_group_overhead_blocks(sb, src_group);
238 (1 + ext4_bg_num_gdb(sb, src_group) +
239 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
240 257
241 start_blk += overhead; 258 start_blk += overhead;
242 259
243 /* We collect contiguous blocks as much as possible. */ 260 /* We collect contiguous blocks as much as possible. */
244 src_group++; 261 src_group++;
245 for (; src_group <= last_group; src_group++) 262 for (; src_group <= last_group; src_group++) {
246 if (!ext4_bg_has_super(sb, src_group)) 263 overhead = ext4_group_overhead_blocks(sb, src_group);
264 if (overhead != 0)
247 last_blk += group_data[src_group - group].blocks_count; 265 last_blk += group_data[src_group - group].blocks_count;
248 else 266 else
249 break; 267 break;
268 }
250 269
251 /* Allocate block bitmaps */ 270 /* Allocate block bitmaps */
252 for (; bb_index < flex_gd->count; bb_index++) { 271 for (; bb_index < flex_gd->count; bb_index++) {
@@ -438,11 +457,13 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
438 ext4_group_t group, count; 457 ext4_group_t group, count;
439 struct buffer_head *bh = NULL; 458 struct buffer_head *bh = NULL;
440 int reserved_gdb, i, j, err = 0, err2; 459 int reserved_gdb, i, j, err = 0, err2;
460 int meta_bg;
441 461
442 BUG_ON(!flex_gd->count || !group_data || 462 BUG_ON(!flex_gd->count || !group_data ||
443 group_data[0].group != sbi->s_groups_count); 463 group_data[0].group != sbi->s_groups_count);
444 464
445 reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks); 465 reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks);
466 meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG);
446 467
447 /* This transaction may be extended/restarted along the way */ 468 /* This transaction may be extended/restarted along the way */
448 handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA); 469 handle = ext4_journal_start_sb(sb, EXT4_MAX_TRANS_DATA);
@@ -452,15 +473,25 @@ static int setup_new_flex_group_blocks(struct super_block *sb,
452 group = group_data[0].group; 473 group = group_data[0].group;
453 for (i = 0; i < flex_gd->count; i++, group++) { 474 for (i = 0; i < flex_gd->count; i++, group++) {
454 unsigned long gdblocks; 475 unsigned long gdblocks;
476 ext4_grpblk_t overhead;
455 477
456 gdblocks = ext4_bg_num_gdb(sb, group); 478 gdblocks = ext4_bg_num_gdb(sb, group);
457 start = ext4_group_first_block_no(sb, group); 479 start = ext4_group_first_block_no(sb, group);
458 480
459 if (!ext4_bg_has_super(sb, group)) 481 if (meta_bg == 0 && !ext4_bg_has_super(sb, group))
460 goto handle_itb; 482 goto handle_itb;
461 483
484 if (meta_bg == 1) {
485 ext4_group_t first_group;
486 first_group = ext4_meta_bg_first_group(sb, group);
487 if (first_group != group + 1 &&
488 first_group != group + EXT4_DESC_PER_BLOCK(sb) - 1)
489 goto handle_itb;
490 }
491
492 block = start + ext4_bg_has_super(sb, group);
462 /* Copy all of the GDT blocks into the backup in this group */ 493 /* Copy all of the GDT blocks into the backup in this group */
463 for (j = 0, block = start + 1; j < gdblocks; j++, block++) { 494 for (j = 0; j < gdblocks; j++, block++) {
464 struct buffer_head *gdb; 495 struct buffer_head *gdb;
465 496
466 ext4_debug("update backup group %#04llx\n", block); 497 ext4_debug("update backup group %#04llx\n", block);
@@ -530,11 +561,11 @@ handle_bb:
530 err = PTR_ERR(bh); 561 err = PTR_ERR(bh);
531 goto out; 562 goto out;
532 } 563 }
533 if (ext4_bg_has_super(sb, group)) { 564 overhead = ext4_group_overhead_blocks(sb, group);
565 if (overhead != 0) {
534 ext4_debug("mark backup superblock %#04llx (+0)\n", 566 ext4_debug("mark backup superblock %#04llx (+0)\n",
535 start); 567 start);
536 ext4_set_bits(bh->b_data, 0, gdblocks + reserved_gdb + 568 ext4_set_bits(bh->b_data, 0, overhead);
537 1);
538 } 569 }
539 ext4_mark_bitmap_end(group_data[i].blocks_count, 570 ext4_mark_bitmap_end(group_data[i].blocks_count,
540 sb->s_blocksize * 8, bh->b_data); 571 sb->s_blocksize * 8, bh->b_data);
@@ -831,6 +862,45 @@ exit_bh:
831} 862}
832 863
833/* 864/*
865 * add_new_gdb_meta_bg is the sister of add_new_gdb.
866 */
867static int add_new_gdb_meta_bg(struct super_block *sb,
868 handle_t *handle, ext4_group_t group) {
869 ext4_fsblk_t gdblock;
870 struct buffer_head *gdb_bh;
871 struct buffer_head **o_group_desc, **n_group_desc;
872 unsigned long gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
873 int err;
874
875 gdblock = ext4_meta_bg_first_block_no(sb, group) +
876 ext4_bg_has_super(sb, group);
877 gdb_bh = sb_bread(sb, gdblock);
878 if (!gdb_bh)
879 return -EIO;
880 n_group_desc = ext4_kvmalloc((gdb_num + 1) *
881 sizeof(struct buffer_head *),
882 GFP_NOFS);
883 if (!n_group_desc) {
884 err = -ENOMEM;
885 ext4_warning(sb, "not enough memory for %lu groups",
886 gdb_num + 1);
887 return err;
888 }
889
890 o_group_desc = EXT4_SB(sb)->s_group_desc;
891 memcpy(n_group_desc, o_group_desc,
892 EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
893 n_group_desc[gdb_num] = gdb_bh;
894 EXT4_SB(sb)->s_group_desc = n_group_desc;
895 EXT4_SB(sb)->s_gdb_count++;
896 ext4_kvfree(o_group_desc);
897 err = ext4_journal_get_write_access(handle, gdb_bh);
898 if (unlikely(err))
899 brelse(gdb_bh);
900 return err;
901}
902
903/*
834 * Called when we are adding a new group which has a backup copy of each of 904 * Called when we are adding a new group which has a backup copy of each of
835 * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks. 905 * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks.
836 * We need to add these reserved backup GDT blocks to the resize inode, so 906 * We need to add these reserved backup GDT blocks to the resize inode, so
@@ -958,16 +1028,16 @@ exit_free:
958 * do not copy the full number of backups at this time. The resize 1028 * do not copy the full number of backups at this time. The resize
959 * which changed s_groups_count will backup again. 1029 * which changed s_groups_count will backup again.
960 */ 1030 */
961static void update_backups(struct super_block *sb, 1031static void update_backups(struct super_block *sb, int blk_off, char *data,
962 int blk_off, char *data, int size) 1032 int size, int meta_bg)
963{ 1033{
964 struct ext4_sb_info *sbi = EXT4_SB(sb); 1034 struct ext4_sb_info *sbi = EXT4_SB(sb);
965 const ext4_group_t last = sbi->s_groups_count; 1035 ext4_group_t last;
966 const int bpg = EXT4_BLOCKS_PER_GROUP(sb); 1036 const int bpg = EXT4_BLOCKS_PER_GROUP(sb);
967 unsigned three = 1; 1037 unsigned three = 1;
968 unsigned five = 5; 1038 unsigned five = 5;
969 unsigned seven = 7; 1039 unsigned seven = 7;
970 ext4_group_t group; 1040 ext4_group_t group = 0;
971 int rest = sb->s_blocksize - size; 1041 int rest = sb->s_blocksize - size;
972 handle_t *handle; 1042 handle_t *handle;
973 int err = 0, err2; 1043 int err = 0, err2;
@@ -981,8 +1051,17 @@ static void update_backups(struct super_block *sb,
981 1051
982 ext4_superblock_csum_set(sb, (struct ext4_super_block *)data); 1052 ext4_superblock_csum_set(sb, (struct ext4_super_block *)data);
983 1053
984 while ((group = ext4_list_backups(sb, &three, &five, &seven)) < last) { 1054 if (meta_bg == 0) {
1055 group = ext4_list_backups(sb, &three, &five, &seven);
1056 last = sbi->s_groups_count;
1057 } else {
1058 group = ext4_meta_bg_first_group(sb, group) + 1;
1059 last = (ext4_group_t)(group + EXT4_DESC_PER_BLOCK(sb) - 2);
1060 }
1061
1062 while (group < sbi->s_groups_count) {
985 struct buffer_head *bh; 1063 struct buffer_head *bh;
1064 ext4_fsblk_t backup_block;
986 1065
987 /* Out of journal space, and can't get more - abort - so sad */ 1066 /* Out of journal space, and can't get more - abort - so sad */
988 if (ext4_handle_valid(handle) && 1067 if (ext4_handle_valid(handle) &&
@@ -991,13 +1070,20 @@ static void update_backups(struct super_block *sb,
991 (err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA))) 1070 (err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA)))
992 break; 1071 break;
993 1072
994 bh = sb_getblk(sb, group * bpg + blk_off); 1073 if (meta_bg == 0)
1074 backup_block = group * bpg + blk_off;
1075 else
1076 backup_block = (ext4_group_first_block_no(sb, group) +
1077 ext4_bg_has_super(sb, group));
1078
1079 bh = sb_getblk(sb, backup_block);
995 if (!bh) { 1080 if (!bh) {
996 err = -EIO; 1081 err = -EIO;
997 break; 1082 break;
998 } 1083 }
999 ext4_debug("update metadata backup %#04lx\n", 1084 ext4_debug("update metadata backup %llu(+%llu)\n",
1000 (unsigned long)bh->b_blocknr); 1085 backup_block, backup_block -
1086 ext4_group_first_block_no(sb, group));
1001 if ((err = ext4_journal_get_write_access(handle, bh))) 1087 if ((err = ext4_journal_get_write_access(handle, bh)))
1002 break; 1088 break;
1003 lock_buffer(bh); 1089 lock_buffer(bh);
@@ -1010,6 +1096,13 @@ static void update_backups(struct super_block *sb,
1010 if (unlikely(err)) 1096 if (unlikely(err))
1011 ext4_std_error(sb, err); 1097 ext4_std_error(sb, err);
1012 brelse(bh); 1098 brelse(bh);
1099
1100 if (meta_bg == 0)
1101 group = ext4_list_backups(sb, &three, &five, &seven);
1102 else if (group == last)
1103 break;
1104 else
1105 group = last;
1013 } 1106 }
1014 if ((err2 = ext4_journal_stop(handle)) && !err) 1107 if ((err2 = ext4_journal_stop(handle)) && !err)
1015 err = err2; 1108 err = err2;
@@ -1052,7 +1145,9 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
1052 struct ext4_super_block *es = sbi->s_es; 1145 struct ext4_super_block *es = sbi->s_es;
1053 struct buffer_head *gdb_bh; 1146 struct buffer_head *gdb_bh;
1054 int i, gdb_off, gdb_num, err = 0; 1147 int i, gdb_off, gdb_num, err = 0;
1148 int meta_bg;
1055 1149
1150 meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG);
1056 for (i = 0; i < count; i++, group++) { 1151 for (i = 0; i < count; i++, group++) {
1057 int reserved_gdb = ext4_bg_has_super(sb, group) ? 1152 int reserved_gdb = ext4_bg_has_super(sb, group) ?
1058 le16_to_cpu(es->s_reserved_gdt_blocks) : 0; 1153 le16_to_cpu(es->s_reserved_gdt_blocks) : 0;
@@ -1072,8 +1167,11 @@ static int ext4_add_new_descs(handle_t *handle, struct super_block *sb,
1072 1167
1073 if (!err && reserved_gdb && ext4_bg_num_gdb(sb, group)) 1168 if (!err && reserved_gdb && ext4_bg_num_gdb(sb, group))
1074 err = reserve_backup_gdb(handle, resize_inode, group); 1169 err = reserve_backup_gdb(handle, resize_inode, group);
1075 } else 1170 } else if (meta_bg != 0) {
1171 err = add_new_gdb_meta_bg(sb, handle, group);
1172 } else {
1076 err = add_new_gdb(handle, resize_inode, group); 1173 err = add_new_gdb(handle, resize_inode, group);
1174 }
1077 if (err) 1175 if (err)
1078 break; 1176 break;
1079 } 1177 }
@@ -1225,7 +1323,7 @@ static void ext4_update_super(struct super_block *sb,
1225 } 1323 }
1226 1324
1227 reserved_blocks = ext4_r_blocks_count(es) * 100; 1325 reserved_blocks = ext4_r_blocks_count(es) * 100;
1228 do_div(reserved_blocks, ext4_blocks_count(es)); 1326 reserved_blocks = div64_u64(reserved_blocks, ext4_blocks_count(es));
1229 reserved_blocks *= blocks_count; 1327 reserved_blocks *= blocks_count;
1230 do_div(reserved_blocks, 100); 1328 do_div(reserved_blocks, 100);
1231 1329
@@ -1236,6 +1334,7 @@ static void ext4_update_super(struct super_block *sb,
1236 le32_add_cpu(&es->s_free_inodes_count, EXT4_INODES_PER_GROUP(sb) * 1334 le32_add_cpu(&es->s_free_inodes_count, EXT4_INODES_PER_GROUP(sb) *
1237 flex_gd->count); 1335 flex_gd->count);
1238 1336
1337 ext4_debug("free blocks count %llu", ext4_free_blocks_count(es));
1239 /* 1338 /*
1240 * We need to protect s_groups_count against other CPUs seeing 1339 * We need to protect s_groups_count against other CPUs seeing
1241 * inconsistent state in the superblock. 1340 * inconsistent state in the superblock.
@@ -1270,6 +1369,8 @@ static void ext4_update_super(struct super_block *sb,
1270 percpu_counter_add(&sbi->s_freeinodes_counter, 1369 percpu_counter_add(&sbi->s_freeinodes_counter,
1271 EXT4_INODES_PER_GROUP(sb) * flex_gd->count); 1370 EXT4_INODES_PER_GROUP(sb) * flex_gd->count);
1272 1371
1372 ext4_debug("free blocks count %llu",
1373 percpu_counter_read(&sbi->s_freeclusters_counter));
1273 if (EXT4_HAS_INCOMPAT_FEATURE(sb, 1374 if (EXT4_HAS_INCOMPAT_FEATURE(sb,
1274 EXT4_FEATURE_INCOMPAT_FLEX_BG) && 1375 EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
1275 sbi->s_log_groups_per_flex) { 1376 sbi->s_log_groups_per_flex) {
@@ -1361,15 +1462,17 @@ exit_journal:
1361 int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); 1462 int gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
1362 int gdb_num_end = ((group + flex_gd->count - 1) / 1463 int gdb_num_end = ((group + flex_gd->count - 1) /
1363 EXT4_DESC_PER_BLOCK(sb)); 1464 EXT4_DESC_PER_BLOCK(sb));
1465 int meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb,
1466 EXT4_FEATURE_INCOMPAT_META_BG);
1364 1467
1365 update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, 1468 update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
1366 sizeof(struct ext4_super_block)); 1469 sizeof(struct ext4_super_block), 0);
1367 for (; gdb_num <= gdb_num_end; gdb_num++) { 1470 for (; gdb_num <= gdb_num_end; gdb_num++) {
1368 struct buffer_head *gdb_bh; 1471 struct buffer_head *gdb_bh;
1369 1472
1370 gdb_bh = sbi->s_group_desc[gdb_num]; 1473 gdb_bh = sbi->s_group_desc[gdb_num];
1371 update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, 1474 update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
1372 gdb_bh->b_size); 1475 gdb_bh->b_size, meta_bg);
1373 } 1476 }
1374 } 1477 }
1375exit: 1478exit:
@@ -1413,9 +1516,7 @@ static int ext4_setup_next_flex_gd(struct super_block *sb,
1413 1516
1414 group_data[i].group = group + i; 1517 group_data[i].group = group + i;
1415 group_data[i].blocks_count = blocks_per_group; 1518 group_data[i].blocks_count = blocks_per_group;
1416 overhead = ext4_bg_has_super(sb, group + i) ? 1519 overhead = ext4_group_overhead_blocks(sb, group + i);
1417 (1 + ext4_bg_num_gdb(sb, group + i) +
1418 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
1419 group_data[i].free_blocks_count = blocks_per_group - overhead; 1520 group_data[i].free_blocks_count = blocks_per_group - overhead;
1420 if (ext4_has_group_desc_csum(sb)) 1521 if (ext4_has_group_desc_csum(sb))
1421 flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT | 1522 flex_gd->bg_flags[i] = EXT4_BG_BLOCK_UNINIT |
@@ -1563,11 +1664,13 @@ errout:
1563 err = err2; 1664 err = err2;
1564 1665
1565 if (!err) { 1666 if (!err) {
1667 ext4_fsblk_t first_block;
1668 first_block = ext4_group_first_block_no(sb, 0);
1566 if (test_opt(sb, DEBUG)) 1669 if (test_opt(sb, DEBUG))
1567 printk(KERN_DEBUG "EXT4-fs: extended group to %llu " 1670 printk(KERN_DEBUG "EXT4-fs: extended group to %llu "
1568 "blocks\n", ext4_blocks_count(es)); 1671 "blocks\n", ext4_blocks_count(es));
1569 update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, (char *)es, 1672 update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr - first_block,
1570 sizeof(struct ext4_super_block)); 1673 (char *)es, sizeof(struct ext4_super_block), 0);
1571 } 1674 }
1572 return err; 1675 return err;
1573} 1676}
@@ -1662,15 +1765,16 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
1662 struct ext4_sb_info *sbi = EXT4_SB(sb); 1765 struct ext4_sb_info *sbi = EXT4_SB(sb);
1663 struct ext4_super_block *es = sbi->s_es; 1766 struct ext4_super_block *es = sbi->s_es;
1664 struct buffer_head *bh; 1767 struct buffer_head *bh;
1665 struct inode *resize_inode; 1768 struct inode *resize_inode = NULL;
1666 ext4_fsblk_t o_blocks_count; 1769 ext4_grpblk_t add, offset;
1667 ext4_group_t o_group;
1668 ext4_group_t n_group;
1669 ext4_grpblk_t offset, add;
1670 unsigned long n_desc_blocks; 1770 unsigned long n_desc_blocks;
1671 unsigned long o_desc_blocks; 1771 unsigned long o_desc_blocks;
1672 unsigned long desc_blocks; 1772 unsigned long desc_blocks;
1773 ext4_group_t o_group;
1774 ext4_group_t n_group;
1775 ext4_fsblk_t o_blocks_count;
1673 int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex; 1776 int err = 0, flexbg_size = 1 << sbi->s_log_groups_per_flex;
1777 int meta_bg;
1674 1778
1675 o_blocks_count = ext4_blocks_count(es); 1779 o_blocks_count = ext4_blocks_count(es);
1676 1780
@@ -1692,22 +1796,33 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
1692 ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset); 1796 ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset);
1693 1797
1694 n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) / 1798 n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) /
1695 EXT4_DESC_PER_BLOCK(sb); 1799 EXT4_DESC_PER_BLOCK(sb);
1696 o_desc_blocks = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) / 1800 o_desc_blocks = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
1697 EXT4_DESC_PER_BLOCK(sb); 1801 EXT4_DESC_PER_BLOCK(sb);
1698 desc_blocks = n_desc_blocks - o_desc_blocks; 1802 desc_blocks = n_desc_blocks - o_desc_blocks;
1699 1803
1700 if (desc_blocks && 1804 meta_bg = EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG);
1701 (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE) ||
1702 le16_to_cpu(es->s_reserved_gdt_blocks) < desc_blocks)) {
1703 ext4_warning(sb, "No reserved GDT blocks, can't resize");
1704 return -EPERM;
1705 }
1706 1805
1707 resize_inode = ext4_iget(sb, EXT4_RESIZE_INO); 1806 if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_RESIZE_INODE)) {
1708 if (IS_ERR(resize_inode)) { 1807 if (meta_bg) {
1709 ext4_warning(sb, "Error opening resize inode"); 1808 ext4_error(sb, "resize_inode and meta_bg enabled "
1710 return PTR_ERR(resize_inode); 1809 "simultaneously");
1810 return -EINVAL;
1811 }
1812 if (le16_to_cpu(es->s_reserved_gdt_blocks) < desc_blocks) {
1813 ext4_warning(sb,
1814 "No reserved GDT blocks, can't resize");
1815 return -EPERM;
1816 }
1817 resize_inode = ext4_iget(sb, EXT4_RESIZE_INO);
1818 if (IS_ERR(resize_inode)) {
1819 ext4_warning(sb, "Error opening resize inode");
1820 return PTR_ERR(resize_inode);
1821 }
1822 } else if (!meta_bg) {
1823 ext4_warning(sb, "File system features do not permit "
1824 "online resize");
1825 return -EPERM;
1711 } 1826 }
1712 1827
1713 /* See if the device is actually as big as what was requested */ 1828 /* See if the device is actually as big as what was requested */
@@ -1761,8 +1876,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
1761out: 1876out:
1762 if (flex_gd) 1877 if (flex_gd)
1763 free_flex_gd(flex_gd); 1878 free_flex_gd(flex_gd);
1764 1879 if (resize_inode != NULL)
1765 iput(resize_inode); 1880 iput(resize_inode);
1766 if (test_opt(sb, DEBUG)) 1881 if (test_opt(sb, DEBUG))
1767 ext4_msg(sb, KERN_DEBUG, "resized filesystem from %llu " 1882 ext4_msg(sb, KERN_DEBUG, "resized filesystem from %llu "
1768 "upto %llu blocks", o_blocks_count, n_blocks_count); 1883 "upto %llu blocks", o_blocks_count, n_blocks_count);