resize2fs.c revision 2215293c7e85c88d2fbc06f9e9438fca9a25213c
1/* 2 * resize2fs.c --- ext2 main routine 3 * 4 * Copyright (C) 1997, 1998 by Theodore Ts'o and 5 * PowerQuest, Inc. 6 * 7 * Copyright (C) 1999, 2000 by Theosore Ts'o 8 * 9 * %Begin-Header% 10 * This file may be redistributed under the terms of the GNU Public 11 * License. 12 * %End-Header% 13 */ 14 15/* 16 * Resizing a filesystem consists of the following phases: 17 * 18 * 1. Adjust superblock and write out new parts of the inode 19 * table 20 * 2. Determine blocks which need to be relocated, and copy the 21 * contents of blocks from their old locations to the new ones. 22 * 3. Scan the inode table, doing the following: 23 * a. If blocks have been moved, update the block 24 * pointers in the inodes and indirect blocks to 25 * point at the new block locations. 26 * b. If parts of the inode table need to be evacuated, 27 * copy inodes from their old locations to their 28 * new ones. 29 * c. If (b) needs to be done, note which blocks contain 30 * directory information, since we will need to 31 * update the directory information. 32 * 4. Update the directory blocks with the new inode locations. 33 * 5. Move the inode tables, if necessary. 34 */ 35 36#include "config.h" 37#include "resize2fs.h" 38#include <time.h> 39 40#ifdef __linux__ /* Kludge for debugging */ 41#define RESIZE2FS_DEBUG 42#endif 43 44static void fix_uninit_block_bitmaps(ext2_filsys fs); 45static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size); 46static errcode_t blocks_to_move(ext2_resize_t rfs); 47static errcode_t block_mover(ext2_resize_t rfs); 48static errcode_t inode_scan_and_fix(ext2_resize_t rfs); 49static errcode_t inode_ref_fix(ext2_resize_t rfs); 50static errcode_t move_itables(ext2_resize_t rfs); 51static errcode_t fix_resize_inode(ext2_filsys fs); 52static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs); 53static errcode_t fix_sb_journal_backup(ext2_filsys fs); 54static errcode_t mark_table_blocks(ext2_filsys fs, 55 ext2fs_block_bitmap bmap); 56 57/* 58 * Some helper CPP macros 59 */ 60#define IS_BLOCK_BM(fs, i, blk) ((blk) == ext2fs_block_bitmap_loc((fs),(i))) 61#define IS_INODE_BM(fs, i, blk) ((blk) == ext2fs_inode_bitmap_loc((fs),(i))) 62 63#define IS_INODE_TB(fs, i, blk) (((blk) >= ext2fs_inode_table_loc((fs), (i))) && \ 64 ((blk) < (ext2fs_inode_table_loc((fs), (i)) + \ 65 (fs)->inode_blocks_per_group))) 66 67/* Some bigalloc helper macros which are more succint... */ 68#define B2C(x) EXT2FS_B2C(fs, (x)) 69#define C2B(x) EXT2FS_C2B(fs, (x)) 70#define EQ_CLSTR(x, y) (B2C(x) == B2C(y)) 71#define LE_CLSTR(x, y) (B2C(x) <= B2C(y)) 72#define LT_CLSTR(x, y) (B2C(x) < B2C(y)) 73#define GE_CLSTR(x, y) (B2C(x) >= B2C(y)) 74#define GT_CLSTR(x, y) (B2C(x) > B2C(y)) 75 76int lazy_itable_init; 77 78/* 79 * This is the top-level routine which does the dirty deed.... 80 */ 81errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags, 82 errcode_t (*progress)(ext2_resize_t rfs, int pass, 83 unsigned long cur, 84 unsigned long max_val)) 85{ 86 ext2_resize_t rfs; 87 errcode_t retval; 88 struct resource_track rtrack, overall_track; 89 90 /* 91 * Create the data structure 92 */ 93 retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs); 94 if (retval) 95 return retval; 96 97 memset(rfs, 0, sizeof(struct ext2_resize_struct)); 98 fs->priv_data = rfs; 99 rfs->old_fs = fs; 100 rfs->flags = flags; 101 rfs->itable_buf = 0; 102 rfs->progress = progress; 103 104 init_resource_track(&overall_track, "overall resize2fs", fs->io); 105 init_resource_track(&rtrack, "read_bitmaps", fs->io); 106 retval = ext2fs_read_bitmaps(fs); 107 if (retval) 108 goto errout; 109 print_resource_track(rfs, &rtrack, fs->io); 110 111 fs->super->s_state |= EXT2_ERROR_FS; 112 ext2fs_mark_super_dirty(fs); 113 ext2fs_flush(fs); 114 115 init_resource_track(&rtrack, "fix_uninit_block_bitmaps 1", fs->io); 116 fix_uninit_block_bitmaps(fs); 117 print_resource_track(rfs, &rtrack, fs->io); 118 retval = ext2fs_dup_handle(fs, &rfs->new_fs); 119 if (retval) 120 goto errout; 121 122 init_resource_track(&rtrack, "adjust_superblock", fs->io); 123 retval = adjust_superblock(rfs, *new_size); 124 if (retval) 125 goto errout; 126 print_resource_track(rfs, &rtrack, fs->io); 127 128 129 init_resource_track(&rtrack, "fix_uninit_block_bitmaps 2", fs->io); 130 fix_uninit_block_bitmaps(rfs->new_fs); 131 print_resource_track(rfs, &rtrack, fs->io); 132 /* Clear the block bitmap uninit flag for the last block group */ 133 ext2fs_bg_flags_clear(rfs->new_fs, rfs->new_fs->group_desc_count - 1, 134 EXT2_BG_BLOCK_UNINIT); 135 136 *new_size = ext2fs_blocks_count(rfs->new_fs->super); 137 138 init_resource_track(&rtrack, "blocks_to_move", fs->io); 139 retval = blocks_to_move(rfs); 140 if (retval) 141 goto errout; 142 print_resource_track(rfs, &rtrack, fs->io); 143 144#ifdef RESIZE2FS_DEBUG 145 if (rfs->flags & RESIZE_DEBUG_BMOVE) 146 printf("Number of free blocks: %llu/%llu, Needed: %llu\n", 147 ext2fs_free_blocks_count(rfs->old_fs->super), 148 ext2fs_free_blocks_count(rfs->new_fs->super), 149 rfs->needed_blocks); 150#endif 151 152 init_resource_track(&rtrack, "block_mover", fs->io); 153 retval = block_mover(rfs); 154 if (retval) 155 goto errout; 156 print_resource_track(rfs, &rtrack, fs->io); 157 158 init_resource_track(&rtrack, "inode_scan_and_fix", fs->io); 159 retval = inode_scan_and_fix(rfs); 160 if (retval) 161 goto errout; 162 print_resource_track(rfs, &rtrack, fs->io); 163 164 init_resource_track(&rtrack, "inode_ref_fix", fs->io); 165 retval = inode_ref_fix(rfs); 166 if (retval) 167 goto errout; 168 print_resource_track(rfs, &rtrack, fs->io); 169 170 init_resource_track(&rtrack, "move_itables", fs->io); 171 retval = move_itables(rfs); 172 if (retval) 173 goto errout; 174 print_resource_track(rfs, &rtrack, fs->io); 175 176 init_resource_track(&rtrack, "calculate_summary_stats", fs->io); 177 retval = ext2fs_calculate_summary_stats(rfs->new_fs); 178 if (retval) 179 goto errout; 180 print_resource_track(rfs, &rtrack, fs->io); 181 182 init_resource_track(&rtrack, "fix_resize_inode", fs->io); 183 retval = fix_resize_inode(rfs->new_fs); 184 if (retval) 185 goto errout; 186 print_resource_track(rfs, &rtrack, fs->io); 187 188 init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io); 189 retval = fix_sb_journal_backup(rfs->new_fs); 190 if (retval) 191 goto errout; 192 print_resource_track(rfs, &rtrack, fs->io); 193 194 rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS; 195 rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 196 197 print_resource_track(rfs, &overall_track, fs->io); 198 retval = ext2fs_close(rfs->new_fs); 199 if (retval) 200 goto errout; 201 202 rfs->flags = flags; 203 204 ext2fs_free(rfs->old_fs); 205 if (rfs->itable_buf) 206 ext2fs_free_mem(&rfs->itable_buf); 207 if (rfs->reserve_blocks) 208 ext2fs_free_block_bitmap(rfs->reserve_blocks); 209 if (rfs->move_blocks) 210 ext2fs_free_block_bitmap(rfs->move_blocks); 211 ext2fs_free_mem(&rfs); 212 213 return 0; 214 215errout: 216 if (rfs->new_fs) 217 ext2fs_free(rfs->new_fs); 218 if (rfs->itable_buf) 219 ext2fs_free_mem(&rfs->itable_buf); 220 ext2fs_free_mem(&rfs); 221 return retval; 222} 223 224/* 225 * Clean up the bitmaps for unitialized bitmaps 226 */ 227static void fix_uninit_block_bitmaps(ext2_filsys fs) 228{ 229 blk64_t blk, lblk; 230 dgrp_t g; 231 int i; 232 233 if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 234 EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) 235 return; 236 237 for (g=0; g < fs->group_desc_count; g++) { 238 if (!(ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT))) 239 continue; 240 241 blk = ext2fs_group_first_block2(fs, g); 242 lblk = ext2fs_group_last_block2(fs, g); 243 ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, 244 lblk - blk + 1); 245 246 ext2fs_reserve_super_and_bgd(fs, g, fs->block_map); 247 ext2fs_mark_block_bitmap2(fs->block_map, 248 ext2fs_block_bitmap_loc(fs, g)); 249 ext2fs_mark_block_bitmap2(fs->block_map, 250 ext2fs_inode_bitmap_loc(fs, g)); 251 for (i = 0, blk = ext2fs_inode_table_loc(fs, g); 252 i < (unsigned int) fs->inode_blocks_per_group; 253 i++, blk++) 254 ext2fs_mark_block_bitmap2(fs->block_map, blk); 255 } 256} 257 258/* -------------------------------------------------------------------- 259 * 260 * Resize processing, phase 1. 261 * 262 * In this phase we adjust the in-memory superblock information, and 263 * initialize any new parts of the inode table. The new parts of the 264 * inode table are created in virgin disk space, so we can abort here 265 * without any side effects. 266 * -------------------------------------------------------------------- 267 */ 268 269/* 270 * If the group descriptor's bitmap and inode table blocks are valid, 271 * release them in the new filesystem data structure, and mark them as 272 * reserved so the old inode table blocks don't get overwritten. 273 */ 274static void free_gdp_blocks(ext2_filsys fs, 275 ext2fs_block_bitmap reserve_blocks, 276 ext2_filsys old_fs, 277 dgrp_t group) 278{ 279 blk64_t blk; 280 int j; 281 282 blk = ext2fs_block_bitmap_loc(old_fs, group); 283 if (blk && 284 (blk < ext2fs_blocks_count(fs->super))) { 285 ext2fs_block_alloc_stats2(fs, blk, -1); 286 ext2fs_mark_block_bitmap2(reserve_blocks, blk); 287 } 288 289 blk = ext2fs_inode_bitmap_loc(old_fs, group); 290 if (blk && 291 (blk < ext2fs_blocks_count(fs->super))) { 292 ext2fs_block_alloc_stats2(fs, blk, -1); 293 ext2fs_mark_block_bitmap2(reserve_blocks, blk); 294 } 295 296 blk = ext2fs_inode_table_loc(old_fs, group); 297 if (blk == 0 || 298 (blk >= ext2fs_blocks_count(fs->super))) 299 return; 300 301 for (j = 0; 302 j < fs->inode_blocks_per_group; j++, blk++) { 303 if (blk >= ext2fs_blocks_count(fs->super)) 304 break; 305 ext2fs_block_alloc_stats2(fs, blk, -1); 306 ext2fs_mark_block_bitmap2(reserve_blocks, blk); 307 } 308} 309 310/* 311 * This routine is shared by the online and offline resize routines. 312 * All of the information which is adjusted in memory is done here. 313 */ 314errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, 315 ext2fs_block_bitmap reserve_blocks, blk64_t new_size) 316{ 317 errcode_t retval; 318 blk64_t overhead = 0; 319 blk64_t rem; 320 blk64_t blk, group_block; 321 blk64_t real_end; 322 blk64_t old_numblocks, numblocks, adjblocks; 323 unsigned long i, j, old_desc_blocks; 324 unsigned int meta_bg, meta_bg_size; 325 int has_super, csum_flag; 326 unsigned long long new_inodes; /* u64 to check for overflow */ 327 double percent; 328 329 ext2fs_blocks_count_set(fs->super, new_size); 330 331retry: 332 fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) - 333 fs->super->s_first_data_block, 334 EXT2_BLOCKS_PER_GROUP(fs->super)); 335 if (fs->group_desc_count == 0) 336 return EXT2_ET_TOOSMALL; 337 fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, 338 EXT2_DESC_PER_BLOCK(fs->super)); 339 340 /* 341 * Overhead is the number of bookkeeping blocks per group. It 342 * includes the superblock backup, the group descriptor 343 * backups, the inode bitmap, the block bitmap, and the inode 344 * table. 345 */ 346 overhead = (int) (2 + fs->inode_blocks_per_group); 347 348 if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) 349 overhead += 1 + fs->desc_blocks + 350 fs->super->s_reserved_gdt_blocks; 351 352 /* 353 * See if the last group is big enough to support the 354 * necessary data structures. If not, we need to get rid of 355 * it. 356 */ 357 rem = (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) % 358 fs->super->s_blocks_per_group; 359 if ((fs->group_desc_count == 1) && rem && (rem < overhead)) 360 return EXT2_ET_TOOSMALL; 361 if ((fs->group_desc_count > 1) && rem && (rem < overhead+50)) { 362 ext2fs_blocks_count_set(fs->super, 363 ext2fs_blocks_count(fs->super) - rem); 364 goto retry; 365 } 366 /* 367 * Adjust the number of inodes 368 */ 369 new_inodes =(unsigned long long) fs->super->s_inodes_per_group * fs->group_desc_count; 370 if (new_inodes > ~0U) { 371 fprintf(stderr, _("inodes (%llu) must be less than %u"), 372 new_inodes, ~0U); 373 return EXT2_ET_TOO_MANY_INODES; 374 } 375 fs->super->s_inodes_count = fs->super->s_inodes_per_group * 376 fs->group_desc_count; 377 378 /* 379 * Adjust the number of free blocks 380 */ 381 blk = ext2fs_blocks_count(old_fs->super); 382 if (blk > ext2fs_blocks_count(fs->super)) 383 ext2fs_free_blocks_count_set(fs->super, 384 ext2fs_free_blocks_count(fs->super) - 385 (blk - ext2fs_blocks_count(fs->super))); 386 else 387 ext2fs_free_blocks_count_set(fs->super, 388 ext2fs_free_blocks_count(fs->super) + 389 (ext2fs_blocks_count(fs->super) - blk)); 390 391 /* 392 * Adjust the number of reserved blocks 393 */ 394 percent = (ext2fs_r_blocks_count(old_fs->super) * 100.0) / 395 ext2fs_blocks_count(old_fs->super); 396 ext2fs_r_blocks_count_set(fs->super, 397 (percent * ext2fs_blocks_count(fs->super) / 398 100.0)); 399 400 /* 401 * Adjust the bitmaps for size 402 */ 403 retval = ext2fs_resize_inode_bitmap2(fs->super->s_inodes_count, 404 fs->super->s_inodes_count, 405 fs->inode_map); 406 if (retval) goto errout; 407 408 real_end = (((blk64_t) EXT2_BLOCKS_PER_GROUP(fs->super) * 409 fs->group_desc_count)) - 1 + 410 fs->super->s_first_data_block; 411 retval = ext2fs_resize_block_bitmap2(new_size - 1, 412 real_end, fs->block_map); 413 if (retval) goto errout; 414 415 /* 416 * If we are growing the file system, also grow the size of 417 * the reserve_blocks bitmap 418 */ 419 if (reserve_blocks && new_size > ext2fs_blocks_count(old_fs->super)) { 420 retval = ext2fs_resize_block_bitmap2(new_size - 1, 421 real_end, reserve_blocks); 422 if (retval) goto errout; 423 } 424 425 /* 426 * Reallocate the group descriptors as necessary. 427 */ 428 if (old_fs->desc_blocks != fs->desc_blocks) { 429 retval = ext2fs_resize_mem(old_fs->desc_blocks * 430 fs->blocksize, 431 fs->desc_blocks * fs->blocksize, 432 &fs->group_desc); 433 if (retval) 434 goto errout; 435 if (fs->desc_blocks > old_fs->desc_blocks) 436 memset((char *) fs->group_desc + 437 (old_fs->desc_blocks * fs->blocksize), 0, 438 (fs->desc_blocks - old_fs->desc_blocks) * 439 fs->blocksize); 440 } 441 442 /* 443 * If the resize_inode feature is set, and we are changing the 444 * number of descriptor blocks, then adjust 445 * s_reserved_gdt_blocks if possible to avoid needing to move 446 * the inode table either now or in the future. 447 */ 448 if ((fs->super->s_feature_compat & 449 EXT2_FEATURE_COMPAT_RESIZE_INODE) && 450 (old_fs->desc_blocks != fs->desc_blocks)) { 451 int new; 452 453 new = ((int) fs->super->s_reserved_gdt_blocks) + 454 (old_fs->desc_blocks - fs->desc_blocks); 455 if (new < 0) 456 new = 0; 457 if (new > (int) fs->blocksize/4) 458 new = fs->blocksize/4; 459 fs->super->s_reserved_gdt_blocks = new; 460 } 461 462 /* 463 * If we are shrinking the number of block groups, we're done 464 * and can exit now. 465 */ 466 if (old_fs->group_desc_count > fs->group_desc_count) { 467 /* 468 * Check the block groups that we are chopping off 469 * and free any blocks associated with their metadata 470 */ 471 for (i = fs->group_desc_count; 472 i < old_fs->group_desc_count; i++) 473 free_gdp_blocks(fs, reserve_blocks, old_fs, i); 474 retval = 0; 475 goto errout; 476 } 477 478 /* 479 * Fix the count of the last (old) block group 480 */ 481 old_numblocks = (ext2fs_blocks_count(old_fs->super) - 482 old_fs->super->s_first_data_block) % 483 old_fs->super->s_blocks_per_group; 484 if (!old_numblocks) 485 old_numblocks = old_fs->super->s_blocks_per_group; 486 if (old_fs->group_desc_count == fs->group_desc_count) { 487 numblocks = (ext2fs_blocks_count(fs->super) - 488 fs->super->s_first_data_block) % 489 fs->super->s_blocks_per_group; 490 if (!numblocks) 491 numblocks = fs->super->s_blocks_per_group; 492 } else 493 numblocks = fs->super->s_blocks_per_group; 494 i = old_fs->group_desc_count - 1; 495 ext2fs_bg_free_blocks_count_set(fs, i, ext2fs_bg_free_blocks_count(fs, i) + (numblocks - old_numblocks)); 496 ext2fs_group_desc_csum_set(fs, i); 497 498 /* 499 * If the number of block groups is staying the same, we're 500 * done and can exit now. (If the number block groups is 501 * shrinking, we had exited earlier.) 502 */ 503 if (old_fs->group_desc_count >= fs->group_desc_count) { 504 retval = 0; 505 goto errout; 506 } 507 508 /* 509 * Initialize the new block group descriptors 510 */ 511 group_block = ext2fs_group_first_block2(fs, 512 old_fs->group_desc_count); 513 csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 514 EXT4_FEATURE_RO_COMPAT_GDT_CSUM); 515 if (access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0) 516 lazy_itable_init = 1; 517 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 518 old_desc_blocks = fs->super->s_first_meta_bg; 519 else 520 old_desc_blocks = fs->desc_blocks + 521 fs->super->s_reserved_gdt_blocks; 522 523 /* 524 * If we changed the number of block_group descriptor blocks, 525 * we need to make sure they are all marked as reserved in the 526 * file systems's block allocation map. 527 */ 528 for (i = 0; i < old_fs->group_desc_count; i++) 529 ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); 530 531 for (i = old_fs->group_desc_count; 532 i < fs->group_desc_count; i++) { 533 memset(ext2fs_group_desc(fs, fs->group_desc, i), 0, 534 sizeof(struct ext2_group_desc)); 535 adjblocks = 0; 536 537 ext2fs_bg_flags_zap(fs, i); 538 if (csum_flag) { 539 ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); 540 if (!lazy_itable_init) 541 ext2fs_bg_flags_set(fs, i, 542 EXT2_BG_INODE_ZEROED); 543 ext2fs_bg_itable_unused_set(fs, i, 544 fs->super->s_inodes_per_group); 545 } 546 547 numblocks = ext2fs_group_blocks_count(fs, i); 548 if ((i < fs->group_desc_count - 1) && csum_flag) 549 ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT); 550 551 has_super = ext2fs_bg_has_super(fs, i); 552 if (has_super) { 553 ext2fs_block_alloc_stats2(fs, group_block, +1); 554 adjblocks++; 555 } 556 meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); 557 meta_bg = i / meta_bg_size; 558 if (!(fs->super->s_feature_incompat & 559 EXT2_FEATURE_INCOMPAT_META_BG) || 560 (meta_bg < fs->super->s_first_meta_bg)) { 561 if (has_super) { 562 for (j=0; j < old_desc_blocks; j++) 563 ext2fs_block_alloc_stats2(fs, 564 group_block + 1 + j, +1); 565 adjblocks += old_desc_blocks; 566 } 567 } else { 568 if (has_super) 569 has_super = 1; 570 if (((i % meta_bg_size) == 0) || 571 ((i % meta_bg_size) == 1) || 572 ((i % meta_bg_size) == (meta_bg_size-1))) 573 ext2fs_block_alloc_stats2(fs, 574 group_block + has_super, +1); 575 } 576 577 adjblocks += 2 + fs->inode_blocks_per_group; 578 579 numblocks -= adjblocks; 580 ext2fs_free_blocks_count_set(fs->super, 581 ext2fs_free_blocks_count(fs->super) - adjblocks); 582 fs->super->s_free_inodes_count += 583 fs->super->s_inodes_per_group; 584 ext2fs_bg_free_blocks_count_set(fs, i, numblocks); 585 ext2fs_bg_free_inodes_count_set(fs, i, 586 fs->super->s_inodes_per_group); 587 ext2fs_bg_used_dirs_count_set(fs, i, 0); 588 ext2fs_group_desc_csum_set(fs, i); 589 590 retval = ext2fs_allocate_group_table(fs, i, 0); 591 if (retval) goto errout; 592 593 group_block += fs->super->s_blocks_per_group; 594 } 595 retval = 0; 596 597 /* 598 * Mark all of the metadata blocks as reserved so they won't 599 * get allocated by the call to ext2fs_allocate_group_table() 600 * in blocks_to_move(), where we allocate new blocks to 601 * replace those allocation bitmap and inode table blocks 602 * which have to get relocated to make space for an increased 603 * number of the block group descriptors. 604 */ 605 if (reserve_blocks) 606 mark_table_blocks(fs, reserve_blocks); 607 608errout: 609 return (retval); 610} 611 612/* 613 * This routine adjusts the superblock and other data structures, both 614 * in disk as well as in memory... 615 */ 616static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size) 617{ 618 ext2_filsys fs; 619 int adj = 0; 620 errcode_t retval; 621 blk64_t group_block; 622 unsigned long i; 623 unsigned long max_group; 624 625 fs = rfs->new_fs; 626 ext2fs_mark_super_dirty(fs); 627 ext2fs_mark_bb_dirty(fs); 628 ext2fs_mark_ib_dirty(fs); 629 630 retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"), 631 &rfs->reserve_blocks); 632 if (retval) 633 return retval; 634 635 retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size); 636 if (retval) 637 goto errout; 638 639 /* 640 * Check to make sure there are enough inodes 641 */ 642 if ((rfs->old_fs->super->s_inodes_count - 643 rfs->old_fs->super->s_free_inodes_count) > 644 rfs->new_fs->super->s_inodes_count) { 645 retval = ENOSPC; 646 goto errout; 647 } 648 649 /* 650 * If we are shrinking the number block groups, we're done and 651 * can exit now. 652 */ 653 if (rfs->old_fs->group_desc_count > fs->group_desc_count) { 654 retval = 0; 655 goto errout; 656 } 657 658 /* 659 * If the number of block groups is staying the same, we're 660 * done and can exit now. (If the number block groups is 661 * shrinking, we had exited earlier.) 662 */ 663 if (rfs->old_fs->group_desc_count >= fs->group_desc_count) { 664 retval = 0; 665 goto errout; 666 } 667 668 /* 669 * If we are using uninit_bg (aka GDT_CSUM) and the kernel 670 * supports lazy inode initialization, we can skip 671 * initializing the inode table. 672 */ 673 if (lazy_itable_init && 674 EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 675 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 676 retval = 0; 677 goto errout; 678 } 679 680 /* 681 * Initialize the inode table 682 */ 683 retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group, 684 &rfs->itable_buf); 685 if (retval) 686 goto errout; 687 688 memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group); 689 group_block = ext2fs_group_first_block2(fs, 690 rfs->old_fs->group_desc_count); 691 adj = rfs->old_fs->group_desc_count; 692 max_group = fs->group_desc_count - adj; 693 if (rfs->progress) { 694 retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 695 0, max_group); 696 if (retval) 697 goto errout; 698 } 699 for (i = rfs->old_fs->group_desc_count; 700 i < fs->group_desc_count; i++) { 701 /* 702 * Write out the new inode table 703 */ 704 retval = io_channel_write_blk64(fs->io, 705 ext2fs_inode_table_loc(fs, i), 706 fs->inode_blocks_per_group, 707 rfs->itable_buf); 708 if (retval) goto errout; 709 710 io_channel_flush(fs->io); 711 if (rfs->progress) { 712 retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 713 i - adj + 1, max_group); 714 if (retval) 715 goto errout; 716 } 717 group_block += fs->super->s_blocks_per_group; 718 } 719 io_channel_flush(fs->io); 720 retval = 0; 721 722errout: 723 return retval; 724} 725 726/* -------------------------------------------------------------------- 727 * 728 * Resize processing, phase 2. 729 * 730 * In this phase we adjust determine which blocks need to be moved, in 731 * blocks_to_move(). We then copy the blocks to their ultimate new 732 * destinations using block_mover(). Since we are copying blocks to 733 * their new locations, again during this pass we can abort without 734 * any problems. 735 * -------------------------------------------------------------------- 736 */ 737 738/* 739 * This helper function creates a block bitmap with all of the 740 * filesystem meta-data blocks. 741 */ 742static errcode_t mark_table_blocks(ext2_filsys fs, 743 ext2fs_block_bitmap bmap) 744{ 745 dgrp_t i; 746 blk64_t blk; 747 748 for (i = 0; i < fs->group_desc_count; i++) { 749 ext2fs_reserve_super_and_bgd(fs, i, bmap); 750 751 /* 752 * Mark the blocks used for the inode table 753 */ 754 blk = ext2fs_inode_table_loc(fs, i); 755 if (blk) 756 ext2fs_mark_block_bitmap_range2(bmap, blk, 757 fs->inode_blocks_per_group); 758 759 /* 760 * Mark block used for the block bitmap 761 */ 762 blk = ext2fs_block_bitmap_loc(fs, i); 763 if (blk) 764 ext2fs_mark_block_bitmap2(bmap, blk); 765 766 /* 767 * Mark block used for the inode bitmap 768 */ 769 blk = ext2fs_inode_bitmap_loc(fs, i); 770 if (blk) 771 ext2fs_mark_block_bitmap2(bmap, blk); 772 } 773 return 0; 774} 775 776/* 777 * This function checks to see if a particular block (either a 778 * superblock or a block group descriptor) overlaps with an inode or 779 * block bitmap block, or with the inode table. 780 */ 781static void mark_fs_metablock(ext2_resize_t rfs, 782 ext2fs_block_bitmap meta_bmap, 783 int group, blk64_t blk) 784{ 785 ext2_filsys fs = rfs->new_fs; 786 787 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 788 ext2fs_block_alloc_stats2(fs, blk, +1); 789 790 /* 791 * Check to see if we overlap with the inode or block bitmap, 792 * or the inode tables. If not, and the block is in use, then 793 * mark it as a block to be moved. 794 */ 795 if (IS_BLOCK_BM(fs, group, blk)) { 796 ext2fs_block_bitmap_loc_set(fs, group, 0); 797 rfs->needed_blocks++; 798 return; 799 } 800 if (IS_INODE_BM(fs, group, blk)) { 801 ext2fs_inode_bitmap_loc_set(fs, group, 0); 802 rfs->needed_blocks++; 803 return; 804 } 805 if (IS_INODE_TB(fs, group, blk)) { 806 ext2fs_inode_table_loc_set(fs, group, 0); 807 rfs->needed_blocks++; 808 return; 809 } 810 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 811 dgrp_t i; 812 813 for (i=0; i < rfs->old_fs->group_desc_count; i++) { 814 if (IS_BLOCK_BM(fs, i, blk)) { 815 ext2fs_block_bitmap_loc_set(fs, i, 0); 816 rfs->needed_blocks++; 817 return; 818 } 819 if (IS_INODE_BM(fs, i, blk)) { 820 ext2fs_inode_bitmap_loc_set(fs, i, 0); 821 rfs->needed_blocks++; 822 return; 823 } 824 if (IS_INODE_TB(fs, i, blk)) { 825 ext2fs_inode_table_loc_set(fs, i, 0); 826 rfs->needed_blocks++; 827 return; 828 } 829 } 830 } 831 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 832 EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && 833 (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) { 834 /* 835 * If the block bitmap is uninitialized, which means 836 * nothing other than standard metadata in use. 837 */ 838 return; 839 } else if (ext2fs_test_block_bitmap2(rfs->old_fs->block_map, blk) && 840 !ext2fs_test_block_bitmap2(meta_bmap, blk)) { 841 ext2fs_mark_block_bitmap2(rfs->move_blocks, blk); 842 rfs->needed_blocks++; 843 } 844} 845 846 847/* 848 * This routine marks and unmarks reserved blocks in the new block 849 * bitmap. It also determines which blocks need to be moved and 850 * places this information into the move_blocks bitmap. 851 */ 852static errcode_t blocks_to_move(ext2_resize_t rfs) 853{ 854 int j, has_super; 855 dgrp_t i, max_groups, g; 856 blk64_t blk, group_blk; 857 blk64_t old_blocks, new_blocks; 858 blk64_t new_size; 859 unsigned int meta_bg, meta_bg_size; 860 errcode_t retval; 861 ext2_filsys fs, old_fs; 862 ext2fs_block_bitmap meta_bmap; 863 int flex_bg; 864 865 fs = rfs->new_fs; 866 old_fs = rfs->old_fs; 867 if (ext2fs_blocks_count(old_fs->super) > ext2fs_blocks_count(fs->super)) 868 fs = rfs->old_fs; 869 870 retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"), 871 &rfs->move_blocks); 872 if (retval) 873 return retval; 874 875 retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"), 876 &meta_bmap); 877 if (retval) 878 return retval; 879 880 retval = mark_table_blocks(old_fs, meta_bmap); 881 if (retval) 882 return retval; 883 884 fs = rfs->new_fs; 885 886 /* 887 * If we're shrinking the filesystem, we need to move any group's 888 * bitmaps which are beyond the end of the new filesystem. 889 */ 890 new_size = ext2fs_blocks_count(fs->super); 891 if (new_size < ext2fs_blocks_count(old_fs->super)) { 892 for (g = 0; g < fs->group_desc_count; g++) { 893 /* 894 * ext2fs_allocate_group_table re-allocates bitmaps 895 * which are set to block 0. 896 */ 897 if (ext2fs_block_bitmap_loc(fs, g) >= new_size) { 898 ext2fs_block_bitmap_loc_set(fs, g, 0); 899 retval = ext2fs_allocate_group_table(fs, g, 0); 900 if (retval) 901 return retval; 902 } 903 if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) { 904 ext2fs_inode_bitmap_loc_set(fs, g, 0); 905 retval = ext2fs_allocate_group_table(fs, g, 0); 906 if (retval) 907 return retval; 908 } 909 } 910 } 911 912 /* 913 * If we're shrinking the filesystem, we need to move all of 914 * the blocks that don't fit any more 915 */ 916 for (blk = ext2fs_blocks_count(fs->super); 917 blk < ext2fs_blocks_count(old_fs->super); blk++) { 918 g = ext2fs_group_of_blk2(fs, blk); 919 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 920 EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && 921 ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) { 922 /* 923 * The block bitmap is uninitialized, so skip 924 * to the next block group. 925 */ 926 blk = ext2fs_group_first_block2(fs, g+1) - 1; 927 continue; 928 } 929 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 930 !ext2fs_test_block_bitmap2(meta_bmap, blk)) { 931 ext2fs_mark_block_bitmap2(rfs->move_blocks, blk); 932 rfs->needed_blocks++; 933 } 934 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 935 } 936 937 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) { 938 old_blocks = old_fs->super->s_first_meta_bg; 939 new_blocks = fs->super->s_first_meta_bg; 940 } else { 941 old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks; 942 new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks; 943 } 944 945 if (old_blocks == new_blocks) { 946 retval = 0; 947 goto errout; 948 } 949 950 max_groups = fs->group_desc_count; 951 if (max_groups > old_fs->group_desc_count) 952 max_groups = old_fs->group_desc_count; 953 group_blk = old_fs->super->s_first_data_block; 954 /* 955 * If we're reducing the number of descriptor blocks, this 956 * makes life easy. :-) We just have to mark some extra 957 * blocks as free. 958 */ 959 if (old_blocks > new_blocks) { 960 for (i = 0; i < max_groups; i++) { 961 if (!ext2fs_bg_has_super(fs, i)) { 962 group_blk += fs->super->s_blocks_per_group; 963 continue; 964 } 965 for (blk = group_blk+1+new_blocks; 966 blk < group_blk+1+old_blocks; blk++) { 967 ext2fs_block_alloc_stats2(fs, blk, -1); 968 rfs->needed_blocks--; 969 } 970 group_blk += fs->super->s_blocks_per_group; 971 } 972 retval = 0; 973 goto errout; 974 } 975 /* 976 * If we're increasing the number of descriptor blocks, life 977 * gets interesting.... 978 */ 979 meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); 980 flex_bg = fs->super->s_feature_incompat & 981 EXT4_FEATURE_INCOMPAT_FLEX_BG; 982 /* first reserve all of the existing fs meta blocks */ 983 for (i = 0; i < max_groups; i++) { 984 has_super = ext2fs_bg_has_super(fs, i); 985 if (has_super) 986 mark_fs_metablock(rfs, meta_bmap, i, group_blk); 987 988 meta_bg = i / meta_bg_size; 989 if (!(fs->super->s_feature_incompat & 990 EXT2_FEATURE_INCOMPAT_META_BG) || 991 (meta_bg < fs->super->s_first_meta_bg)) { 992 if (has_super) { 993 for (blk = group_blk+1; 994 blk < group_blk + 1 + new_blocks; blk++) 995 mark_fs_metablock(rfs, meta_bmap, 996 i, blk); 997 } 998 } else { 999 if (has_super) 1000 has_super = 1; 1001 if (((i % meta_bg_size) == 0) || 1002 ((i % meta_bg_size) == 1) || 1003 ((i % meta_bg_size) == (meta_bg_size-1))) 1004 mark_fs_metablock(rfs, meta_bmap, i, 1005 group_blk + has_super); 1006 } 1007 1008 /* 1009 * Reserve the existing meta blocks that we know 1010 * aren't to be moved. 1011 * 1012 * For flex_bg file systems, in order to avoid 1013 * overwriting fs metadata (especially inode table 1014 * blocks) belonging to a different block group when 1015 * we are relocating the inode tables, we need to 1016 * reserve all existing fs metadata blocks. 1017 */ 1018 if (ext2fs_block_bitmap_loc(fs, i)) 1019 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1020 ext2fs_block_bitmap_loc(fs, i)); 1021 else if (flex_bg && i < old_fs->group_desc_count) 1022 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1023 ext2fs_block_bitmap_loc(old_fs, i)); 1024 1025 if (ext2fs_inode_bitmap_loc(fs, i)) 1026 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1027 ext2fs_inode_bitmap_loc(fs, i)); 1028 else if (flex_bg && i < old_fs->group_desc_count) 1029 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1030 ext2fs_inode_bitmap_loc(old_fs, i)); 1031 1032 if (ext2fs_inode_table_loc(fs, i)) 1033 ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks, 1034 ext2fs_inode_table_loc(fs, i), 1035 fs->inode_blocks_per_group); 1036 else if (flex_bg && i < old_fs->group_desc_count) 1037 ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks, 1038 ext2fs_inode_table_loc(old_fs, i), 1039 old_fs->inode_blocks_per_group); 1040 1041 group_blk += rfs->new_fs->super->s_blocks_per_group; 1042 } 1043 1044 /* Allocate the missing data structures */ 1045 for (i = 0; i < max_groups; i++) { 1046 if (ext2fs_inode_table_loc(fs, i) && 1047 ext2fs_inode_bitmap_loc(fs, i) && 1048 ext2fs_block_bitmap_loc(fs, i)) 1049 continue; 1050 1051 retval = ext2fs_allocate_group_table(fs, i, 1052 rfs->reserve_blocks); 1053 if (retval) 1054 goto errout; 1055 1056 /* 1057 * For those structures that have changed, we need to 1058 * do bookkeepping. 1059 */ 1060 if (ext2fs_block_bitmap_loc(old_fs, i) != 1061 (blk = ext2fs_block_bitmap_loc(fs, i))) { 1062 ext2fs_block_alloc_stats2(fs, blk, +1); 1063 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1064 !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1065 ext2fs_mark_block_bitmap2(rfs->move_blocks, 1066 blk); 1067 } 1068 if (ext2fs_inode_bitmap_loc(old_fs, i) != 1069 (blk = ext2fs_inode_bitmap_loc(fs, i))) { 1070 ext2fs_block_alloc_stats2(fs, blk, +1); 1071 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1072 !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1073 ext2fs_mark_block_bitmap2(rfs->move_blocks, 1074 blk); 1075 } 1076 1077 /* 1078 * The inode table, if we need to relocate it, is 1079 * handled specially. We have to reserve the blocks 1080 * for both the old and the new inode table, since we 1081 * can't have the inode table be destroyed during the 1082 * block relocation phase. 1083 */ 1084 if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i)) 1085 continue; /* inode table not moved */ 1086 1087 rfs->needed_blocks += fs->inode_blocks_per_group; 1088 1089 /* 1090 * Mark the new inode table as in use in the new block 1091 * allocation bitmap, and move any blocks that might 1092 * be necessary. 1093 */ 1094 for (blk = ext2fs_inode_table_loc(fs, i), j=0; 1095 j < fs->inode_blocks_per_group ; j++, blk++) { 1096 ext2fs_block_alloc_stats2(fs, blk, +1); 1097 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1098 !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1099 ext2fs_mark_block_bitmap2(rfs->move_blocks, 1100 blk); 1101 } 1102 1103 /* 1104 * Make sure the old inode table is reserved in the 1105 * block reservation bitmap. 1106 */ 1107 for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; 1108 j < fs->inode_blocks_per_group ; j++, blk++) 1109 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 1110 } 1111 retval = 0; 1112 1113errout: 1114 if (meta_bmap) 1115 ext2fs_free_block_bitmap(meta_bmap); 1116 1117 return retval; 1118} 1119 1120/* 1121 * This helper function tries to allocate a new block. We try to 1122 * avoid hitting the original group descriptor blocks at least at 1123 * first, since we want to make it possible to recover from a badly 1124 * aborted resize operation as much as possible. 1125 * 1126 * In the future, I may further modify this routine to balance out 1127 * where we get the new blocks across the various block groups. 1128 * Ideally we would allocate blocks that corresponded with the block 1129 * group of the containing inode, and keep contiguous blocks 1130 * together. However, this very difficult to do efficiently, since we 1131 * don't have the necessary information up front. 1132 */ 1133 1134#define AVOID_OLD 1 1135#define DESPERATION 2 1136 1137static void init_block_alloc(ext2_resize_t rfs) 1138{ 1139 rfs->alloc_state = AVOID_OLD; 1140 rfs->new_blk = rfs->new_fs->super->s_first_data_block; 1141#if 0 1142 /* HACK for testing */ 1143 if (ext2fs_blocks_count(rfs->new_fs->super) > 1144 ext2fs_blocks_count(rfs->old_fs->super)) 1145 rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super); 1146#endif 1147} 1148 1149static blk64_t get_new_block(ext2_resize_t rfs) 1150{ 1151 ext2_filsys fs = rfs->new_fs; 1152 1153 while (1) { 1154 if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) { 1155 if (rfs->alloc_state == DESPERATION) 1156 return 0; 1157 1158#ifdef RESIZE2FS_DEBUG 1159 if (rfs->flags & RESIZE_DEBUG_BMOVE) 1160 printf("Going into desperation mode " 1161 "for block allocations\n"); 1162#endif 1163 rfs->alloc_state = DESPERATION; 1164 rfs->new_blk = fs->super->s_first_data_block; 1165 continue; 1166 } 1167 if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) || 1168 ext2fs_test_block_bitmap2(rfs->reserve_blocks, 1169 rfs->new_blk) || 1170 ((rfs->alloc_state == AVOID_OLD) && 1171 (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) && 1172 ext2fs_test_block_bitmap2(rfs->old_fs->block_map, 1173 rfs->new_blk))) { 1174 rfs->new_blk++; 1175 continue; 1176 } 1177 return rfs->new_blk; 1178 } 1179} 1180 1181static errcode_t resize2fs_get_alloc_block(ext2_filsys fs, blk64_t goal, 1182 blk64_t *ret) 1183{ 1184 ext2_resize_t rfs = (ext2_resize_t) fs->priv_data; 1185 blk64_t blk; 1186 1187 blk = get_new_block(rfs); 1188 if (!blk) 1189 return ENOSPC; 1190 1191#ifdef RESIZE2FS_DEBUG 1192 if (rfs->flags & 0xF) 1193 printf("get_alloc_block allocating %llu\n", blk); 1194#endif 1195 1196 ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk); 1197 ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk); 1198 *ret = (blk64_t) blk; 1199 return 0; 1200} 1201 1202static errcode_t block_mover(ext2_resize_t rfs) 1203{ 1204 blk64_t blk, old_blk, new_blk; 1205 ext2_filsys fs = rfs->new_fs; 1206 ext2_filsys old_fs = rfs->old_fs; 1207 errcode_t retval; 1208 __u64 size; 1209 int c; 1210 int to_move, moved; 1211 ext2_badblocks_list badblock_list = 0; 1212 int bb_modified = 0; 1213 1214 fs->get_alloc_block = resize2fs_get_alloc_block; 1215 old_fs->get_alloc_block = resize2fs_get_alloc_block; 1216 1217 retval = ext2fs_read_bb_inode(old_fs, &badblock_list); 1218 if (retval) 1219 return retval; 1220 1221 new_blk = fs->super->s_first_data_block; 1222 if (!rfs->itable_buf) { 1223 retval = ext2fs_get_array(fs->blocksize, 1224 fs->inode_blocks_per_group, 1225 &rfs->itable_buf); 1226 if (retval) 1227 return retval; 1228 } 1229 retval = ext2fs_create_extent_table(&rfs->bmap, 0); 1230 if (retval) 1231 return retval; 1232 1233 /* 1234 * The first step is to figure out where all of the blocks 1235 * will go. 1236 */ 1237 to_move = moved = 0; 1238 init_block_alloc(rfs); 1239 for (blk = B2C(old_fs->super->s_first_data_block); 1240 blk < ext2fs_blocks_count(old_fs->super); 1241 blk += EXT2FS_CLUSTER_RATIO(fs)) { 1242 if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk)) 1243 continue; 1244 if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk)) 1245 continue; 1246 if (ext2fs_badblocks_list_test(badblock_list, blk)) { 1247 ext2fs_badblocks_list_del(badblock_list, blk); 1248 bb_modified++; 1249 continue; 1250 } 1251 1252 new_blk = get_new_block(rfs); 1253 if (!new_blk) { 1254 retval = ENOSPC; 1255 goto errout; 1256 } 1257 ext2fs_block_alloc_stats2(fs, new_blk, +1); 1258 ext2fs_add_extent_entry(rfs->bmap, B2C(blk), B2C(new_blk)); 1259 to_move++; 1260 } 1261 1262 if (to_move == 0) { 1263 if (rfs->bmap) { 1264 ext2fs_free_extent_table(rfs->bmap); 1265 rfs->bmap = 0; 1266 } 1267 retval = 0; 1268 goto errout; 1269 } 1270 1271 /* 1272 * Step two is to actually move the blocks 1273 */ 1274 retval = ext2fs_iterate_extent(rfs->bmap, 0, 0, 0); 1275 if (retval) goto errout; 1276 1277 if (rfs->progress) { 1278 retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS, 1279 0, to_move); 1280 if (retval) 1281 goto errout; 1282 } 1283 while (1) { 1284 retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size); 1285 if (retval) goto errout; 1286 if (!size) 1287 break; 1288 old_blk = C2B(old_blk); 1289 new_blk = C2B(new_blk); 1290 size = C2B(size); 1291#ifdef RESIZE2FS_DEBUG 1292 if (rfs->flags & RESIZE_DEBUG_BMOVE) 1293 printf("Moving %llu blocks %llu->%llu\n", 1294 size, old_blk, new_blk); 1295#endif 1296 do { 1297 c = size; 1298 if (c > fs->inode_blocks_per_group) 1299 c = fs->inode_blocks_per_group; 1300 retval = io_channel_read_blk64(fs->io, old_blk, c, 1301 rfs->itable_buf); 1302 if (retval) goto errout; 1303 retval = io_channel_write_blk64(fs->io, new_blk, c, 1304 rfs->itable_buf); 1305 if (retval) goto errout; 1306 size -= c; 1307 new_blk += c; 1308 old_blk += c; 1309 moved += c; 1310 if (rfs->progress) { 1311 io_channel_flush(fs->io); 1312 retval = (rfs->progress)(rfs, 1313 E2_RSZ_BLOCK_RELOC_PASS, 1314 moved, to_move); 1315 if (retval) 1316 goto errout; 1317 } 1318 } while (size > 0); 1319 io_channel_flush(fs->io); 1320 } 1321 1322errout: 1323 if (badblock_list) { 1324 if (!retval && bb_modified) 1325 retval = ext2fs_update_bb_inode(old_fs, 1326 badblock_list); 1327 ext2fs_badblocks_list_free(badblock_list); 1328 } 1329 return retval; 1330} 1331 1332 1333/* -------------------------------------------------------------------- 1334 * 1335 * Resize processing, phase 3 1336 * 1337 * -------------------------------------------------------------------- 1338 */ 1339 1340 1341/* 1342 * The extent translation table is stored in clusters so we need to 1343 * take special care when mapping a source block number to its 1344 * destination block number. 1345 */ 1346__u64 extent_translate(ext2_filsys fs, ext2_extent extent, __u64 old_loc) 1347{ 1348 __u64 new_block = C2B(ext2fs_extent_translate(extent, B2C(old_loc))); 1349 1350 if (new_block != 0) 1351 new_block += old_loc & (EXT2FS_CLUSTER_RATIO(fs) - 1); 1352 return new_block; 1353} 1354 1355struct process_block_struct { 1356 ext2_resize_t rfs; 1357 ext2_ino_t ino; 1358 struct ext2_inode * inode; 1359 errcode_t error; 1360 int is_dir; 1361 int changed; 1362}; 1363 1364static int process_block(ext2_filsys fs, blk64_t *block_nr, 1365 e2_blkcnt_t blockcnt, 1366 blk64_t ref_block EXT2FS_ATTR((unused)), 1367 int ref_offset EXT2FS_ATTR((unused)), void *priv_data) 1368{ 1369 struct process_block_struct *pb; 1370 errcode_t retval; 1371 blk64_t block, new_block; 1372 int ret = 0; 1373 1374 pb = (struct process_block_struct *) priv_data; 1375 block = *block_nr; 1376 if (pb->rfs->bmap) { 1377 new_block = extent_translate(fs, pb->rfs->bmap, block); 1378 if (new_block) { 1379 *block_nr = new_block; 1380 ret |= BLOCK_CHANGED; 1381 pb->changed = 1; 1382#ifdef RESIZE2FS_DEBUG 1383 if (pb->rfs->flags & RESIZE_DEBUG_BMOVE) 1384 printf("ino=%u, blockcnt=%lld, %llu->%llu\n", 1385 pb->ino, blockcnt, block, new_block); 1386#endif 1387 block = new_block; 1388 } 1389 } 1390 if (pb->is_dir) { 1391 retval = ext2fs_add_dir_block2(fs->dblist, pb->ino, 1392 block, (int) blockcnt); 1393 if (retval) { 1394 pb->error = retval; 1395 ret |= BLOCK_ABORT; 1396 } 1397 } 1398 return ret; 1399} 1400 1401/* 1402 * Progress callback 1403 */ 1404static errcode_t progress_callback(ext2_filsys fs, 1405 ext2_inode_scan scan EXT2FS_ATTR((unused)), 1406 dgrp_t group, void * priv_data) 1407{ 1408 ext2_resize_t rfs = (ext2_resize_t) priv_data; 1409 errcode_t retval; 1410 1411 /* 1412 * This check is to protect against old ext2 libraries. It 1413 * shouldn't be needed against new libraries. 1414 */ 1415 if ((group+1) == 0) 1416 return 0; 1417 1418 if (rfs->progress) { 1419 io_channel_flush(fs->io); 1420 retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 1421 group+1, fs->group_desc_count); 1422 if (retval) 1423 return retval; 1424 } 1425 1426 return 0; 1427} 1428 1429static errcode_t inode_scan_and_fix(ext2_resize_t rfs) 1430{ 1431 struct process_block_struct pb; 1432 ext2_ino_t ino, new_inode; 1433 struct ext2_inode *inode = NULL; 1434 ext2_inode_scan scan = NULL; 1435 errcode_t retval; 1436 char *block_buf = 0; 1437 ext2_ino_t start_to_move; 1438 blk64_t orig_size; 1439 blk64_t new_block; 1440 int inode_size; 1441 1442 if ((rfs->old_fs->group_desc_count <= 1443 rfs->new_fs->group_desc_count) && 1444 !rfs->bmap) 1445 return 0; 1446 1447 /* 1448 * Save the original size of the old filesystem, and 1449 * temporarily set the size to be the new size if the new size 1450 * is larger. We need to do this to avoid catching an error 1451 * by the block iterator routines 1452 */ 1453 orig_size = ext2fs_blocks_count(rfs->old_fs->super); 1454 if (orig_size < ext2fs_blocks_count(rfs->new_fs->super)) 1455 ext2fs_blocks_count_set(rfs->old_fs->super, 1456 ext2fs_blocks_count(rfs->new_fs->super)); 1457 1458 retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan); 1459 if (retval) goto errout; 1460 1461 retval = ext2fs_init_dblist(rfs->old_fs, 0); 1462 if (retval) goto errout; 1463 retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf); 1464 if (retval) goto errout; 1465 1466 start_to_move = (rfs->new_fs->group_desc_count * 1467 rfs->new_fs->super->s_inodes_per_group); 1468 1469 if (rfs->progress) { 1470 retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 1471 0, rfs->old_fs->group_desc_count); 1472 if (retval) 1473 goto errout; 1474 } 1475 ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs); 1476 pb.rfs = rfs; 1477 pb.inode = inode; 1478 pb.error = 0; 1479 new_inode = EXT2_FIRST_INODE(rfs->new_fs->super); 1480 inode_size = EXT2_INODE_SIZE(rfs->new_fs->super); 1481 inode = malloc(inode_size); 1482 if (!inode) { 1483 retval = ENOMEM; 1484 goto errout; 1485 } 1486 /* 1487 * First, copy all of the inodes that need to be moved 1488 * elsewhere in the inode table 1489 */ 1490 while (1) { 1491 retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size); 1492 if (retval) goto errout; 1493 if (!ino) 1494 break; 1495 1496 if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO) 1497 continue; /* inode not in use */ 1498 1499 pb.is_dir = LINUX_S_ISDIR(inode->i_mode); 1500 pb.changed = 0; 1501 1502 if (ext2fs_file_acl_block(rfs->old_fs, inode) && rfs->bmap) { 1503 new_block = extent_translate(rfs->old_fs, rfs->bmap, 1504 ext2fs_file_acl_block(rfs->old_fs, inode)); 1505 if (new_block) { 1506 ext2fs_file_acl_block_set(rfs->old_fs, inode, 1507 new_block); 1508 retval = ext2fs_write_inode_full(rfs->old_fs, 1509 ino, inode, inode_size); 1510 if (retval) goto errout; 1511 } 1512 } 1513 1514 if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) && 1515 (rfs->bmap || pb.is_dir)) { 1516 pb.ino = ino; 1517 retval = ext2fs_block_iterate3(rfs->old_fs, 1518 ino, 0, block_buf, 1519 process_block, &pb); 1520 if (retval) 1521 goto errout; 1522 if (pb.error) { 1523 retval = pb.error; 1524 goto errout; 1525 } 1526 } 1527 1528 if (ino <= start_to_move) 1529 continue; /* Don't need to move it. */ 1530 1531 /* 1532 * Find a new inode 1533 */ 1534 retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode); 1535 if (retval) 1536 goto errout; 1537 1538 ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1, 1539 pb.is_dir); 1540 if (pb.changed) { 1541 /* Get the new version of the inode */ 1542 retval = ext2fs_read_inode_full(rfs->old_fs, ino, 1543 inode, inode_size); 1544 if (retval) goto errout; 1545 } 1546 inode->i_ctime = time(0); 1547 retval = ext2fs_write_inode_full(rfs->old_fs, new_inode, 1548 inode, inode_size); 1549 if (retval) goto errout; 1550 1551#ifdef RESIZE2FS_DEBUG 1552 if (rfs->flags & RESIZE_DEBUG_INODEMAP) 1553 printf("Inode moved %u->%u\n", ino, new_inode); 1554#endif 1555 if (!rfs->imap) { 1556 retval = ext2fs_create_extent_table(&rfs->imap, 0); 1557 if (retval) 1558 goto errout; 1559 } 1560 ext2fs_add_extent_entry(rfs->imap, ino, new_inode); 1561 } 1562 io_channel_flush(rfs->old_fs->io); 1563 1564errout: 1565 ext2fs_blocks_count_set(rfs->old_fs->super, orig_size); 1566 if (rfs->bmap) { 1567 ext2fs_free_extent_table(rfs->bmap); 1568 rfs->bmap = 0; 1569 } 1570 if (scan) 1571 ext2fs_close_inode_scan(scan); 1572 if (block_buf) 1573 ext2fs_free_mem(&block_buf); 1574 free(inode); 1575 return retval; 1576} 1577 1578/* -------------------------------------------------------------------- 1579 * 1580 * Resize processing, phase 4. 1581 * 1582 * -------------------------------------------------------------------- 1583 */ 1584 1585struct istruct { 1586 ext2_resize_t rfs; 1587 errcode_t err; 1588 unsigned int max_dirs; 1589 unsigned int num; 1590}; 1591 1592static int check_and_change_inodes(ext2_ino_t dir, 1593 int entry EXT2FS_ATTR((unused)), 1594 struct ext2_dir_entry *dirent, int offset, 1595 int blocksize EXT2FS_ATTR((unused)), 1596 char *buf EXT2FS_ATTR((unused)), 1597 void *priv_data) 1598{ 1599 struct istruct *is = (struct istruct *) priv_data; 1600 struct ext2_inode inode; 1601 ext2_ino_t new_inode; 1602 errcode_t retval; 1603 1604 if (is->rfs->progress && offset == 0) { 1605 io_channel_flush(is->rfs->old_fs->io); 1606 is->err = (is->rfs->progress)(is->rfs, 1607 E2_RSZ_INODE_REF_UPD_PASS, 1608 ++is->num, is->max_dirs); 1609 if (is->err) 1610 return DIRENT_ABORT; 1611 } 1612 1613 if (!dirent->inode) 1614 return 0; 1615 1616 new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode); 1617 1618 if (!new_inode) 1619 return 0; 1620#ifdef RESIZE2FS_DEBUG 1621 if (is->rfs->flags & RESIZE_DEBUG_INODEMAP) 1622 printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n", 1623 dir, dirent->name_len&0xFF, dirent->name, 1624 dirent->inode, new_inode); 1625#endif 1626 1627 dirent->inode = new_inode; 1628 1629 /* Update the directory mtime and ctime */ 1630 retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode); 1631 if (retval == 0) { 1632 inode.i_mtime = inode.i_ctime = time(0); 1633 is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode); 1634 if (is->err) 1635 return DIRENT_ABORT; 1636 } 1637 1638 return DIRENT_CHANGED; 1639} 1640 1641static errcode_t inode_ref_fix(ext2_resize_t rfs) 1642{ 1643 errcode_t retval; 1644 struct istruct is; 1645 1646 if (!rfs->imap) 1647 return 0; 1648 1649 /* 1650 * Now, we iterate over all of the directories to update the 1651 * inode references 1652 */ 1653 is.num = 0; 1654 is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist); 1655 is.rfs = rfs; 1656 is.err = 0; 1657 1658 if (rfs->progress) { 1659 retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 1660 0, is.max_dirs); 1661 if (retval) 1662 goto errout; 1663 } 1664 1665 retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist, 1666 DIRENT_FLAG_INCLUDE_EMPTY, 0, 1667 check_and_change_inodes, &is); 1668 if (retval) 1669 goto errout; 1670 if (is.err) { 1671 retval = is.err; 1672 goto errout; 1673 } 1674 1675 if (rfs->progress && (is.num < is.max_dirs)) 1676 (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 1677 is.max_dirs, is.max_dirs); 1678 1679errout: 1680 ext2fs_free_extent_table(rfs->imap); 1681 rfs->imap = 0; 1682 return retval; 1683} 1684 1685 1686/* -------------------------------------------------------------------- 1687 * 1688 * Resize processing, phase 5. 1689 * 1690 * In this phase we actually move the inode table around, and then 1691 * update the summary statistics. This is scary, since aborting here 1692 * will potentially scramble the filesystem. (We are moving the 1693 * inode tables around in place, and so the potential for lost data, 1694 * or at the very least scrambling the mapping between filenames and 1695 * inode numbers is very high in case of a power failure here.) 1696 * -------------------------------------------------------------------- 1697 */ 1698 1699 1700/* 1701 * A very scary routine --- this one moves the inode table around!!! 1702 * 1703 * After this you have to use the rfs->new_fs file handle to read and 1704 * write inodes. 1705 */ 1706static errcode_t move_itables(ext2_resize_t rfs) 1707{ 1708 int n, num, size; 1709 long long diff; 1710 dgrp_t i, max_groups; 1711 ext2_filsys fs = rfs->new_fs; 1712 char *cp; 1713 blk64_t old_blk, new_blk, blk; 1714 errcode_t retval; 1715 int j, to_move, moved; 1716 1717 max_groups = fs->group_desc_count; 1718 if (max_groups > rfs->old_fs->group_desc_count) 1719 max_groups = rfs->old_fs->group_desc_count; 1720 1721 size = fs->blocksize * fs->inode_blocks_per_group; 1722 if (!rfs->itable_buf) { 1723 retval = ext2fs_get_mem(size, &rfs->itable_buf); 1724 if (retval) 1725 return retval; 1726 } 1727 1728 /* 1729 * Figure out how many inode tables we need to move 1730 */ 1731 to_move = moved = 0; 1732 for (i=0; i < max_groups; i++) 1733 if (ext2fs_inode_table_loc(rfs->old_fs, i) != 1734 ext2fs_inode_table_loc(fs, i)) 1735 to_move++; 1736 1737 if (to_move == 0) 1738 return 0; 1739 1740 if (rfs->progress) { 1741 retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 1742 0, to_move); 1743 if (retval) 1744 goto errout; 1745 } 1746 1747 rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1748 1749 for (i=0; i < max_groups; i++) { 1750 old_blk = ext2fs_inode_table_loc(rfs->old_fs, i); 1751 new_blk = ext2fs_inode_table_loc(fs, i); 1752 diff = new_blk - old_blk; 1753 1754#ifdef RESIZE2FS_DEBUG 1755 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1756 printf("Itable move group %d block %llu->%llu (diff %lld)\n", 1757 i, old_blk, new_blk, diff); 1758#endif 1759 1760 if (!diff) 1761 continue; 1762 1763 retval = io_channel_read_blk64(fs->io, old_blk, 1764 fs->inode_blocks_per_group, 1765 rfs->itable_buf); 1766 if (retval) 1767 goto errout; 1768 /* 1769 * The end of the inode table segment often contains 1770 * all zeros, and we're often only moving the inode 1771 * table down a block or two. If so, we can optimize 1772 * things by not rewriting blocks that we know to be zero 1773 * already. 1774 */ 1775 for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--) 1776 if (*cp) 1777 break; 1778 n = n >> EXT2_BLOCK_SIZE_BITS(fs->super); 1779#ifdef RESIZE2FS_DEBUG 1780 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1781 printf("%d blocks of zeros...\n", n); 1782#endif 1783 num = fs->inode_blocks_per_group; 1784 if (n > diff) 1785 num -= n; 1786 1787 retval = io_channel_write_blk64(fs->io, new_blk, 1788 num, rfs->itable_buf); 1789 if (retval) { 1790 io_channel_write_blk64(fs->io, old_blk, 1791 num, rfs->itable_buf); 1792 goto errout; 1793 } 1794 if (n > diff) { 1795 retval = io_channel_write_blk64(fs->io, 1796 old_blk + fs->inode_blocks_per_group, 1797 diff, (rfs->itable_buf + 1798 (fs->inode_blocks_per_group - diff) * 1799 fs->blocksize)); 1800 if (retval) 1801 goto errout; 1802 } 1803 1804 for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; 1805 j < fs->inode_blocks_per_group ; j++, blk++) 1806 ext2fs_block_alloc_stats2(fs, blk, -1); 1807 1808 ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk); 1809 ext2fs_group_desc_csum_set(rfs->old_fs, i); 1810 ext2fs_mark_super_dirty(rfs->old_fs); 1811 ext2fs_flush(rfs->old_fs); 1812 1813 if (rfs->progress) { 1814 retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 1815 ++moved, to_move); 1816 if (retval) 1817 goto errout; 1818 } 1819 } 1820 mark_table_blocks(fs, fs->block_map); 1821 ext2fs_flush(fs); 1822#ifdef RESIZE2FS_DEBUG 1823 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1824 printf("Inode table move finished.\n"); 1825#endif 1826 return 0; 1827 1828errout: 1829 return retval; 1830} 1831 1832/* 1833 * Fix the resize inode 1834 */ 1835static errcode_t fix_resize_inode(ext2_filsys fs) 1836{ 1837 struct ext2_inode inode; 1838 errcode_t retval; 1839 char *block_buf = NULL; 1840 1841 if (!(fs->super->s_feature_compat & 1842 EXT2_FEATURE_COMPAT_RESIZE_INODE)) 1843 return 0; 1844 1845 retval = ext2fs_get_mem(fs->blocksize, &block_buf); 1846 if (retval) goto errout; 1847 1848 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); 1849 if (retval) goto errout; 1850 1851 ext2fs_iblk_set(fs, &inode, 1); 1852 1853 retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); 1854 if (retval) goto errout; 1855 1856 if (!inode.i_block[EXT2_DIND_BLOCK]) { 1857 /* 1858 * Avoid zeroing out block #0; that's rude. This 1859 * should never happen anyway since the filesystem 1860 * should be fsck'ed and we assume it is consistent. 1861 */ 1862 fprintf(stderr, 1863 _("Should never happen: resize inode corrupt!\n")); 1864 exit(1); 1865 } 1866 1867 memset(block_buf, 0, fs->blocksize); 1868 1869 retval = io_channel_write_blk64(fs->io, inode.i_block[EXT2_DIND_BLOCK], 1870 1, block_buf); 1871 if (retval) goto errout; 1872 1873 retval = ext2fs_create_resize_inode(fs); 1874 if (retval) 1875 goto errout; 1876 1877errout: 1878 if (block_buf) 1879 ext2fs_free_mem(&block_buf); 1880 return retval; 1881} 1882 1883/* 1884 * Finally, recalculate the summary information 1885 */ 1886static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) 1887{ 1888 blk64_t blk; 1889 ext2_ino_t ino; 1890 unsigned int group = 0; 1891 unsigned int count = 0; 1892 blk64_t total_blocks_free = 0; 1893 int total_inodes_free = 0; 1894 int group_free = 0; 1895 int uninit = 0; 1896 blk64_t super_blk, old_desc_blk, new_desc_blk; 1897 int old_desc_blocks; 1898 1899 /* 1900 * First calculate the block statistics 1901 */ 1902 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); 1903 ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk, 1904 &new_desc_blk, 0); 1905 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 1906 old_desc_blocks = fs->super->s_first_meta_bg; 1907 else 1908 old_desc_blocks = fs->desc_blocks + 1909 fs->super->s_reserved_gdt_blocks; 1910 for (blk = B2C(fs->super->s_first_data_block); 1911 blk < ext2fs_blocks_count(fs->super); 1912 blk += EXT2FS_CLUSTER_RATIO(fs)) { 1913 if ((uninit && 1914 !(EQ_CLSTR(blk, super_blk) || 1915 ((old_desc_blk && old_desc_blocks && 1916 GE_CLSTR(blk, old_desc_blk) && 1917 LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) || 1918 ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) || 1919 EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) || 1920 EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) || 1921 ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) && 1922 LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group) 1923 + fs->inode_blocks_per_group))))) || 1924 (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) { 1925 group_free++; 1926 total_blocks_free++; 1927 } 1928 count++; 1929 if ((count == fs->super->s_clusters_per_group) || 1930 EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) { 1931 ext2fs_bg_free_blocks_count_set(fs, group, group_free); 1932 ext2fs_group_desc_csum_set(fs, group); 1933 group++; 1934 if (group >= fs->group_desc_count) 1935 break; 1936 count = 0; 1937 group_free = 0; 1938 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); 1939 ext2fs_super_and_bgd_loc2(fs, group, &super_blk, 1940 &old_desc_blk, 1941 &new_desc_blk, 0); 1942 if (fs->super->s_feature_incompat & 1943 EXT2_FEATURE_INCOMPAT_META_BG) 1944 old_desc_blocks = fs->super->s_first_meta_bg; 1945 else 1946 old_desc_blocks = fs->desc_blocks + 1947 fs->super->s_reserved_gdt_blocks; 1948 } 1949 } 1950 total_blocks_free = C2B(total_blocks_free); 1951 ext2fs_free_blocks_count_set(fs->super, total_blocks_free); 1952 1953 /* 1954 * Next, calculate the inode statistics 1955 */ 1956 group_free = 0; 1957 count = 0; 1958 group = 0; 1959 1960 /* Protect loop from wrap-around if s_inodes_count maxed */ 1961 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT); 1962 for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) { 1963 if (uninit || 1964 !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) { 1965 group_free++; 1966 total_inodes_free++; 1967 } 1968 count++; 1969 if ((count == fs->super->s_inodes_per_group) || 1970 (ino == fs->super->s_inodes_count)) { 1971 ext2fs_bg_free_inodes_count_set(fs, group, group_free); 1972 ext2fs_group_desc_csum_set(fs, group); 1973 group++; 1974 if (group >= fs->group_desc_count) 1975 break; 1976 count = 0; 1977 group_free = 0; 1978 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT); 1979 } 1980 } 1981 fs->super->s_free_inodes_count = total_inodes_free; 1982 ext2fs_mark_super_dirty(fs); 1983 return 0; 1984} 1985 1986/* 1987 * Journal may have been relocated; update the backup journal blocks 1988 * in the superblock. 1989 */ 1990static errcode_t fix_sb_journal_backup(ext2_filsys fs) 1991{ 1992 errcode_t retval; 1993 struct ext2_inode inode; 1994 1995 if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 1996 return 0; 1997 1998 /* External journal? Nothing to do. */ 1999 if (fs->super->s_journal_dev && !fs->super->s_journal_inum) 2000 return 0; 2001 2002 retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode); 2003 if (retval) 2004 return retval; 2005 memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); 2006 fs->super->s_jnl_blocks[15] = inode.i_size_high; 2007 fs->super->s_jnl_blocks[16] = inode.i_size; 2008 fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; 2009 ext2fs_mark_super_dirty(fs); 2010 return 0; 2011} 2012 2013static int calc_group_overhead(ext2_filsys fs, blk64_t grp, 2014 int old_desc_blocks) 2015{ 2016 blk64_t super_blk, old_desc_blk, new_desc_blk; 2017 int overhead; 2018 2019 /* inode table blocks plus allocation bitmaps */ 2020 overhead = fs->inode_blocks_per_group + 2; 2021 2022 ext2fs_super_and_bgd_loc2(fs, grp, &super_blk, 2023 &old_desc_blk, &new_desc_blk, 0); 2024 if ((grp == 0) || super_blk) 2025 overhead++; 2026 if (old_desc_blk) 2027 overhead += old_desc_blocks; 2028 else if (new_desc_blk) 2029 overhead++; 2030 return overhead; 2031} 2032 2033 2034/* 2035 * calcluate the minimum number of blocks the given fs can be resized to 2036 */ 2037blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags) 2038{ 2039 ext2_ino_t inode_count; 2040 dgrp_t groups; 2041 blk64_t blks_needed, data_blocks; 2042 blk64_t grp, data_needed, last_start; 2043 blk64_t overhead = 0; 2044 int old_desc_blocks; 2045 int extra_groups = 0; 2046 int flexbg_size = 1 << fs->super->s_log_groups_per_flex; 2047 2048 /* 2049 * first figure out how many group descriptors we need to 2050 * handle the number of inodes we have 2051 */ 2052 inode_count = fs->super->s_inodes_count - 2053 fs->super->s_free_inodes_count; 2054 blks_needed = ext2fs_div_ceil(inode_count, 2055 fs->super->s_inodes_per_group) * 2056 EXT2_BLOCKS_PER_GROUP(fs->super); 2057 groups = ext2fs_div64_ceil(blks_needed, 2058 EXT2_BLOCKS_PER_GROUP(fs->super)); 2059#ifdef RESIZE2FS_DEBUG 2060 if (flags & RESIZE_DEBUG_MIN_CALC) 2061 printf("fs has %d inodes, %d groups required.\n", 2062 inode_count, groups); 2063#endif 2064 2065 /* 2066 * number of old-style block group descriptor blocks 2067 */ 2068 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 2069 old_desc_blocks = fs->super->s_first_meta_bg; 2070 else 2071 old_desc_blocks = fs->desc_blocks + 2072 fs->super->s_reserved_gdt_blocks; 2073 2074 /* calculate how many blocks are needed for data */ 2075 data_needed = ext2fs_blocks_count(fs->super) - 2076 ext2fs_free_blocks_count(fs->super); 2077 2078 for (grp = 0; grp < fs->group_desc_count; grp++) 2079 data_needed -= calc_group_overhead(fs, grp, old_desc_blocks); 2080#ifdef RESIZE2FS_DEBUG 2081 if (flags & RESIZE_DEBUG_MIN_CALC) 2082 printf("fs requires %llu data blocks.\n", data_needed); 2083#endif 2084 2085 /* 2086 * For ext4 we need to allow for up to a flex_bg worth of 2087 * inode tables of slack space so the resize operation can be 2088 * guaranteed to finish. 2089 */ 2090 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 2091 extra_groups = flexbg_size - (groups & (flexbg_size - 1)); 2092 data_needed += fs->inode_blocks_per_group * extra_groups; 2093 extra_groups = groups % flexbg_size; 2094 } 2095 2096 /* 2097 * figure out how many data blocks we have given the number of groups 2098 * we need for our inodes 2099 */ 2100 data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super); 2101 last_start = 0; 2102 for (grp = 0; grp < groups; grp++) { 2103 overhead = calc_group_overhead(fs, grp, old_desc_blocks); 2104 2105 /* 2106 * we want to keep track of how much data we can store in 2107 * the groups leading up to the last group so we can determine 2108 * how big the last group needs to be 2109 */ 2110 if (grp != (groups - 1)) 2111 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - 2112 overhead; 2113 2114 data_blocks -= overhead; 2115 } 2116#ifdef RESIZE2FS_DEBUG 2117 if (flags & RESIZE_DEBUG_MIN_CALC) 2118 printf("With %d group(s), we have %llu blocks available.\n", 2119 groups, data_blocks); 2120#endif 2121 2122 /* 2123 * if we need more group descriptors in order to accomodate our data 2124 * then we need to add them here 2125 */ 2126 while (data_needed > data_blocks) { 2127 blk64_t remainder = data_needed - data_blocks; 2128 dgrp_t extra_grps; 2129 2130 /* figure out how many more groups we need for the data */ 2131 extra_grps = ext2fs_div64_ceil(remainder, 2132 EXT2_BLOCKS_PER_GROUP(fs->super)); 2133 2134 data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super); 2135 2136 /* ok we have to account for the last group */ 2137 overhead = calc_group_overhead(fs, groups-1, old_desc_blocks); 2138 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead; 2139 2140 for (grp = groups; grp < groups+extra_grps; grp++) { 2141 overhead = calc_group_overhead(fs, grp, 2142 old_desc_blocks); 2143 2144 /* 2145 * again, we need to see how much data we cram into 2146 * all of the groups leading up to the last group 2147 */ 2148 if (grp != (groups + extra_grps - 1)) 2149 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) 2150 - overhead; 2151 2152 data_blocks -= overhead; 2153 } 2154 2155 groups += extra_grps; 2156 extra_groups += extra_grps; 2157 if (fs->super->s_feature_incompat 2158 & EXT4_FEATURE_INCOMPAT_FLEX_BG 2159 && extra_groups > flexbg_size) { 2160 /* 2161 * For ext4 we need to allow for up to a flex_bg worth 2162 * of inode tables of slack space so the resize 2163 * operation can be guaranteed to finish. 2164 */ 2165 extra_groups = flexbg_size - 2166 (groups & (flexbg_size - 1)); 2167 data_needed += (fs->inode_blocks_per_group * 2168 extra_groups); 2169 extra_groups = groups % flexbg_size; 2170 } 2171#ifdef RESIZE2FS_DEBUG 2172 if (flags & RESIZE_DEBUG_MIN_CALC) 2173 printf("Added %d extra group(s), " 2174 "data_needed %llu, data_blocks %llu, " 2175 "last_start %llu\n", 2176 extra_grps, data_needed, data_blocks, 2177 last_start); 2178#endif 2179 } 2180 2181 /* now for the fun voodoo */ 2182 overhead = calc_group_overhead(fs, groups-1, old_desc_blocks); 2183#ifdef RESIZE2FS_DEBUG 2184 if (flags & RESIZE_DEBUG_MIN_CALC) 2185 printf("Last group's overhead is %llu\n", overhead); 2186#endif 2187 2188 /* 2189 * if this is the case then the last group is going to have data in it 2190 * so we need to adjust the size of the last group accordingly 2191 */ 2192 if (last_start < data_needed) { 2193 blk64_t remainder = data_needed - last_start; 2194 2195#ifdef RESIZE2FS_DEBUG 2196 if (flags & RESIZE_DEBUG_MIN_CALC) 2197 printf("Need %llu data blocks in last group\n", 2198 remainder); 2199#endif 2200 /* 2201 * 50 is a magic number that mkfs/resize uses to see if its 2202 * even worth making/resizing the fs. basically you need to 2203 * have at least 50 blocks in addition to the blocks needed 2204 * for the metadata in the last group 2205 */ 2206 if (remainder > 50) 2207 overhead += remainder; 2208 else 2209 overhead += 50; 2210 } else 2211 overhead += 50; 2212 2213 overhead += fs->super->s_first_data_block; 2214#ifdef RESIZE2FS_DEBUG 2215 if (flags & RESIZE_DEBUG_MIN_CALC) 2216 printf("Final size of last group is %lld\n", overhead); 2217#endif 2218 2219 /* 2220 * since our last group doesn't have to be BLOCKS_PER_GROUP large, we 2221 * only do groups-1, and then add the number of blocks needed to 2222 * handle the group descriptor metadata+data that we need 2223 */ 2224 blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super); 2225 blks_needed += overhead; 2226 2227 /* 2228 * Make sure blks_needed covers the end of the inode table in 2229 * the last block group. 2230 */ 2231 overhead = ext2fs_inode_table_loc(fs, groups-1) + 2232 fs->inode_blocks_per_group; 2233 if (blks_needed < overhead) 2234 blks_needed = overhead; 2235 2236#ifdef RESIZE2FS_DEBUG 2237 if (flags & RESIZE_DEBUG_MIN_CALC) 2238 printf("Estimated blocks needed: %llu\n", blks_needed); 2239#endif 2240 2241 /* 2242 * If at this point we've already added up more "needed" than 2243 * the current size, just return current size as minimum. 2244 */ 2245 if (blks_needed >= ext2fs_blocks_count(fs->super)) 2246 return ext2fs_blocks_count(fs->super); 2247 /* 2248 * We need to reserve a few extra blocks if extents are 2249 * enabled, in case we need to grow the extent tree. The more 2250 * we shrink the file system, the more space we need. 2251 */ 2252 if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { 2253 blk64_t safe_margin = (ext2fs_blocks_count(fs->super) - 2254 blks_needed)/500; 2255#ifdef RESIZE2FS_DEBUG 2256 if (flags & RESIZE_DEBUG_MIN_CALC) 2257 printf("Extents safety margin: %llu\n", safe_margin); 2258#endif 2259 blks_needed += safe_margin; 2260 } 2261 2262 return blks_needed; 2263} 2264