resize2fs.c revision 45ff69ffeb700012a7c052f5e45882557a40be7e
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 888 * group's metadata blocks (either allocation bitmaps or the 889 * inode table) which are beyond the end of the new 890 * filesystem. 891 */ 892 new_size = ext2fs_blocks_count(fs->super); 893 if (new_size < ext2fs_blocks_count(old_fs->super)) { 894 for (g = 0; g < fs->group_desc_count; g++) { 895 int realloc = 0; 896 /* 897 * ext2fs_allocate_group_table will re-allocate any 898 * metadata blocks whose location is set to zero. 899 */ 900 if (ext2fs_block_bitmap_loc(fs, g) >= new_size) { 901 ext2fs_block_bitmap_loc_set(fs, g, 0); 902 realloc = 1; 903 } 904 if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) { 905 ext2fs_inode_bitmap_loc_set(fs, g, 0); 906 realloc = 1; 907 } 908 if ((ext2fs_inode_table_loc(fs, g) + 909 fs->inode_blocks_per_group) > new_size) { 910 ext2fs_inode_table_loc_set(fs, g, 0); 911 realloc = 1; 912 } 913 914 if (realloc) { 915 retval = ext2fs_allocate_group_table(fs, g, 0); 916 if (retval) 917 return retval; 918 } 919 } 920 } 921 922 /* 923 * If we're shrinking the filesystem, we need to move all of 924 * the blocks that don't fit any more 925 */ 926 for (blk = ext2fs_blocks_count(fs->super); 927 blk < ext2fs_blocks_count(old_fs->super); blk++) { 928 g = ext2fs_group_of_blk2(fs, blk); 929 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 930 EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && 931 ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) { 932 /* 933 * The block bitmap is uninitialized, so skip 934 * to the next block group. 935 */ 936 blk = ext2fs_group_first_block2(fs, g+1) - 1; 937 continue; 938 } 939 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 940 !ext2fs_test_block_bitmap2(meta_bmap, blk)) { 941 ext2fs_mark_block_bitmap2(rfs->move_blocks, blk); 942 rfs->needed_blocks++; 943 } 944 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 945 } 946 947 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) { 948 old_blocks = old_fs->super->s_first_meta_bg; 949 new_blocks = fs->super->s_first_meta_bg; 950 } else { 951 old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks; 952 new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks; 953 } 954 955 if (old_blocks == new_blocks) { 956 retval = 0; 957 goto errout; 958 } 959 960 max_groups = fs->group_desc_count; 961 if (max_groups > old_fs->group_desc_count) 962 max_groups = old_fs->group_desc_count; 963 group_blk = old_fs->super->s_first_data_block; 964 /* 965 * If we're reducing the number of descriptor blocks, this 966 * makes life easy. :-) We just have to mark some extra 967 * blocks as free. 968 */ 969 if (old_blocks > new_blocks) { 970 for (i = 0; i < max_groups; i++) { 971 if (!ext2fs_bg_has_super(fs, i)) { 972 group_blk += fs->super->s_blocks_per_group; 973 continue; 974 } 975 for (blk = group_blk+1+new_blocks; 976 blk < group_blk+1+old_blocks; blk++) { 977 ext2fs_block_alloc_stats2(fs, blk, -1); 978 rfs->needed_blocks--; 979 } 980 group_blk += fs->super->s_blocks_per_group; 981 } 982 retval = 0; 983 goto errout; 984 } 985 /* 986 * If we're increasing the number of descriptor blocks, life 987 * gets interesting.... 988 */ 989 meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); 990 flex_bg = fs->super->s_feature_incompat & 991 EXT4_FEATURE_INCOMPAT_FLEX_BG; 992 /* first reserve all of the existing fs meta blocks */ 993 for (i = 0; i < max_groups; i++) { 994 has_super = ext2fs_bg_has_super(fs, i); 995 if (has_super) 996 mark_fs_metablock(rfs, meta_bmap, i, group_blk); 997 998 meta_bg = i / meta_bg_size; 999 if (!(fs->super->s_feature_incompat & 1000 EXT2_FEATURE_INCOMPAT_META_BG) || 1001 (meta_bg < fs->super->s_first_meta_bg)) { 1002 if (has_super) { 1003 for (blk = group_blk+1; 1004 blk < group_blk + 1 + new_blocks; blk++) 1005 mark_fs_metablock(rfs, meta_bmap, 1006 i, blk); 1007 } 1008 } else { 1009 if (has_super) 1010 has_super = 1; 1011 if (((i % meta_bg_size) == 0) || 1012 ((i % meta_bg_size) == 1) || 1013 ((i % meta_bg_size) == (meta_bg_size-1))) 1014 mark_fs_metablock(rfs, meta_bmap, i, 1015 group_blk + has_super); 1016 } 1017 1018 /* 1019 * Reserve the existing meta blocks that we know 1020 * aren't to be moved. 1021 * 1022 * For flex_bg file systems, in order to avoid 1023 * overwriting fs metadata (especially inode table 1024 * blocks) belonging to a different block group when 1025 * we are relocating the inode tables, we need to 1026 * reserve all existing fs metadata blocks. 1027 */ 1028 if (ext2fs_block_bitmap_loc(fs, i)) 1029 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1030 ext2fs_block_bitmap_loc(fs, i)); 1031 else if (flex_bg && i < old_fs->group_desc_count) 1032 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1033 ext2fs_block_bitmap_loc(old_fs, i)); 1034 1035 if (ext2fs_inode_bitmap_loc(fs, i)) 1036 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1037 ext2fs_inode_bitmap_loc(fs, i)); 1038 else if (flex_bg && i < old_fs->group_desc_count) 1039 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1040 ext2fs_inode_bitmap_loc(old_fs, i)); 1041 1042 if (ext2fs_inode_table_loc(fs, i)) 1043 ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks, 1044 ext2fs_inode_table_loc(fs, i), 1045 fs->inode_blocks_per_group); 1046 else if (flex_bg && i < old_fs->group_desc_count) 1047 ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks, 1048 ext2fs_inode_table_loc(old_fs, i), 1049 old_fs->inode_blocks_per_group); 1050 1051 group_blk += rfs->new_fs->super->s_blocks_per_group; 1052 } 1053 1054 /* Allocate the missing data structures */ 1055 for (i = 0; i < max_groups; i++) { 1056 if (ext2fs_inode_table_loc(fs, i) && 1057 ext2fs_inode_bitmap_loc(fs, i) && 1058 ext2fs_block_bitmap_loc(fs, i)) 1059 continue; 1060 1061 retval = ext2fs_allocate_group_table(fs, i, 1062 rfs->reserve_blocks); 1063 if (retval) 1064 goto errout; 1065 1066 /* 1067 * For those structures that have changed, we need to 1068 * do bookkeepping. 1069 */ 1070 if (ext2fs_block_bitmap_loc(old_fs, i) != 1071 (blk = ext2fs_block_bitmap_loc(fs, i))) { 1072 ext2fs_block_alloc_stats2(fs, blk, +1); 1073 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1074 !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1075 ext2fs_mark_block_bitmap2(rfs->move_blocks, 1076 blk); 1077 } 1078 if (ext2fs_inode_bitmap_loc(old_fs, i) != 1079 (blk = ext2fs_inode_bitmap_loc(fs, i))) { 1080 ext2fs_block_alloc_stats2(fs, blk, +1); 1081 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1082 !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1083 ext2fs_mark_block_bitmap2(rfs->move_blocks, 1084 blk); 1085 } 1086 1087 /* 1088 * The inode table, if we need to relocate it, is 1089 * handled specially. We have to reserve the blocks 1090 * for both the old and the new inode table, since we 1091 * can't have the inode table be destroyed during the 1092 * block relocation phase. 1093 */ 1094 if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i)) 1095 continue; /* inode table not moved */ 1096 1097 rfs->needed_blocks += fs->inode_blocks_per_group; 1098 1099 /* 1100 * Mark the new inode table as in use in the new block 1101 * allocation bitmap, and move any blocks that might 1102 * be necessary. 1103 */ 1104 for (blk = ext2fs_inode_table_loc(fs, i), j=0; 1105 j < fs->inode_blocks_per_group ; j++, blk++) { 1106 ext2fs_block_alloc_stats2(fs, blk, +1); 1107 if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1108 !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1109 ext2fs_mark_block_bitmap2(rfs->move_blocks, 1110 blk); 1111 } 1112 1113 /* 1114 * Make sure the old inode table is reserved in the 1115 * block reservation bitmap. 1116 */ 1117 for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; 1118 j < fs->inode_blocks_per_group ; j++, blk++) 1119 ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 1120 } 1121 retval = 0; 1122 1123errout: 1124 if (meta_bmap) 1125 ext2fs_free_block_bitmap(meta_bmap); 1126 1127 return retval; 1128} 1129 1130/* 1131 * This helper function tries to allocate a new block. We try to 1132 * avoid hitting the original group descriptor blocks at least at 1133 * first, since we want to make it possible to recover from a badly 1134 * aborted resize operation as much as possible. 1135 * 1136 * In the future, I may further modify this routine to balance out 1137 * where we get the new blocks across the various block groups. 1138 * Ideally we would allocate blocks that corresponded with the block 1139 * group of the containing inode, and keep contiguous blocks 1140 * together. However, this very difficult to do efficiently, since we 1141 * don't have the necessary information up front. 1142 */ 1143 1144#define AVOID_OLD 1 1145#define DESPERATION 2 1146 1147static void init_block_alloc(ext2_resize_t rfs) 1148{ 1149 rfs->alloc_state = AVOID_OLD; 1150 rfs->new_blk = rfs->new_fs->super->s_first_data_block; 1151#if 0 1152 /* HACK for testing */ 1153 if (ext2fs_blocks_count(rfs->new_fs->super) > 1154 ext2fs_blocks_count(rfs->old_fs->super)) 1155 rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super); 1156#endif 1157} 1158 1159static blk64_t get_new_block(ext2_resize_t rfs) 1160{ 1161 ext2_filsys fs = rfs->new_fs; 1162 1163 while (1) { 1164 if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) { 1165 if (rfs->alloc_state == DESPERATION) 1166 return 0; 1167 1168#ifdef RESIZE2FS_DEBUG 1169 if (rfs->flags & RESIZE_DEBUG_BMOVE) 1170 printf("Going into desperation mode " 1171 "for block allocations\n"); 1172#endif 1173 rfs->alloc_state = DESPERATION; 1174 rfs->new_blk = fs->super->s_first_data_block; 1175 continue; 1176 } 1177 if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) || 1178 ext2fs_test_block_bitmap2(rfs->reserve_blocks, 1179 rfs->new_blk) || 1180 ((rfs->alloc_state == AVOID_OLD) && 1181 (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) && 1182 ext2fs_test_block_bitmap2(rfs->old_fs->block_map, 1183 rfs->new_blk))) { 1184 rfs->new_blk++; 1185 continue; 1186 } 1187 return rfs->new_blk; 1188 } 1189} 1190 1191static errcode_t resize2fs_get_alloc_block(ext2_filsys fs, blk64_t goal, 1192 blk64_t *ret) 1193{ 1194 ext2_resize_t rfs = (ext2_resize_t) fs->priv_data; 1195 blk64_t blk; 1196 1197 blk = get_new_block(rfs); 1198 if (!blk) 1199 return ENOSPC; 1200 1201#ifdef RESIZE2FS_DEBUG 1202 if (rfs->flags & 0xF) 1203 printf("get_alloc_block allocating %llu\n", blk); 1204#endif 1205 1206 ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk); 1207 ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk); 1208 *ret = (blk64_t) blk; 1209 return 0; 1210} 1211 1212static errcode_t block_mover(ext2_resize_t rfs) 1213{ 1214 blk64_t blk, old_blk, new_blk; 1215 ext2_filsys fs = rfs->new_fs; 1216 ext2_filsys old_fs = rfs->old_fs; 1217 errcode_t retval; 1218 __u64 size; 1219 int c; 1220 int to_move, moved; 1221 ext2_badblocks_list badblock_list = 0; 1222 int bb_modified = 0; 1223 1224 fs->get_alloc_block = resize2fs_get_alloc_block; 1225 old_fs->get_alloc_block = resize2fs_get_alloc_block; 1226 1227 retval = ext2fs_read_bb_inode(old_fs, &badblock_list); 1228 if (retval) 1229 return retval; 1230 1231 new_blk = fs->super->s_first_data_block; 1232 if (!rfs->itable_buf) { 1233 retval = ext2fs_get_array(fs->blocksize, 1234 fs->inode_blocks_per_group, 1235 &rfs->itable_buf); 1236 if (retval) 1237 return retval; 1238 } 1239 retval = ext2fs_create_extent_table(&rfs->bmap, 0); 1240 if (retval) 1241 return retval; 1242 1243 /* 1244 * The first step is to figure out where all of the blocks 1245 * will go. 1246 */ 1247 to_move = moved = 0; 1248 init_block_alloc(rfs); 1249 for (blk = B2C(old_fs->super->s_first_data_block); 1250 blk < ext2fs_blocks_count(old_fs->super); 1251 blk += EXT2FS_CLUSTER_RATIO(fs)) { 1252 if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk)) 1253 continue; 1254 if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk)) 1255 continue; 1256 if (ext2fs_badblocks_list_test(badblock_list, blk)) { 1257 ext2fs_badblocks_list_del(badblock_list, blk); 1258 bb_modified++; 1259 continue; 1260 } 1261 1262 new_blk = get_new_block(rfs); 1263 if (!new_blk) { 1264 retval = ENOSPC; 1265 goto errout; 1266 } 1267 ext2fs_block_alloc_stats2(fs, new_blk, +1); 1268 ext2fs_add_extent_entry(rfs->bmap, B2C(blk), B2C(new_blk)); 1269 to_move++; 1270 } 1271 1272 if (to_move == 0) { 1273 if (rfs->bmap) { 1274 ext2fs_free_extent_table(rfs->bmap); 1275 rfs->bmap = 0; 1276 } 1277 retval = 0; 1278 goto errout; 1279 } 1280 1281 /* 1282 * Step two is to actually move the blocks 1283 */ 1284 retval = ext2fs_iterate_extent(rfs->bmap, 0, 0, 0); 1285 if (retval) goto errout; 1286 1287 if (rfs->progress) { 1288 retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS, 1289 0, to_move); 1290 if (retval) 1291 goto errout; 1292 } 1293 while (1) { 1294 retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size); 1295 if (retval) goto errout; 1296 if (!size) 1297 break; 1298 old_blk = C2B(old_blk); 1299 new_blk = C2B(new_blk); 1300 size = C2B(size); 1301#ifdef RESIZE2FS_DEBUG 1302 if (rfs->flags & RESIZE_DEBUG_BMOVE) 1303 printf("Moving %llu blocks %llu->%llu\n", 1304 size, old_blk, new_blk); 1305#endif 1306 do { 1307 c = size; 1308 if (c > fs->inode_blocks_per_group) 1309 c = fs->inode_blocks_per_group; 1310 retval = io_channel_read_blk64(fs->io, old_blk, c, 1311 rfs->itable_buf); 1312 if (retval) goto errout; 1313 retval = io_channel_write_blk64(fs->io, new_blk, c, 1314 rfs->itable_buf); 1315 if (retval) goto errout; 1316 size -= c; 1317 new_blk += c; 1318 old_blk += c; 1319 moved += c; 1320 if (rfs->progress) { 1321 io_channel_flush(fs->io); 1322 retval = (rfs->progress)(rfs, 1323 E2_RSZ_BLOCK_RELOC_PASS, 1324 moved, to_move); 1325 if (retval) 1326 goto errout; 1327 } 1328 } while (size > 0); 1329 io_channel_flush(fs->io); 1330 } 1331 1332errout: 1333 if (badblock_list) { 1334 if (!retval && bb_modified) 1335 retval = ext2fs_update_bb_inode(old_fs, 1336 badblock_list); 1337 ext2fs_badblocks_list_free(badblock_list); 1338 } 1339 return retval; 1340} 1341 1342 1343/* -------------------------------------------------------------------- 1344 * 1345 * Resize processing, phase 3 1346 * 1347 * -------------------------------------------------------------------- 1348 */ 1349 1350 1351/* 1352 * The extent translation table is stored in clusters so we need to 1353 * take special care when mapping a source block number to its 1354 * destination block number. 1355 */ 1356__u64 extent_translate(ext2_filsys fs, ext2_extent extent, __u64 old_loc) 1357{ 1358 __u64 new_block = C2B(ext2fs_extent_translate(extent, B2C(old_loc))); 1359 1360 if (new_block != 0) 1361 new_block += old_loc & (EXT2FS_CLUSTER_RATIO(fs) - 1); 1362 return new_block; 1363} 1364 1365struct process_block_struct { 1366 ext2_resize_t rfs; 1367 ext2_ino_t ino; 1368 struct ext2_inode * inode; 1369 errcode_t error; 1370 int is_dir; 1371 int changed; 1372}; 1373 1374static int process_block(ext2_filsys fs, blk64_t *block_nr, 1375 e2_blkcnt_t blockcnt, 1376 blk64_t ref_block EXT2FS_ATTR((unused)), 1377 int ref_offset EXT2FS_ATTR((unused)), void *priv_data) 1378{ 1379 struct process_block_struct *pb; 1380 errcode_t retval; 1381 blk64_t block, new_block; 1382 int ret = 0; 1383 1384 pb = (struct process_block_struct *) priv_data; 1385 block = *block_nr; 1386 if (pb->rfs->bmap) { 1387 new_block = extent_translate(fs, pb->rfs->bmap, block); 1388 if (new_block) { 1389 *block_nr = new_block; 1390 ret |= BLOCK_CHANGED; 1391 pb->changed = 1; 1392#ifdef RESIZE2FS_DEBUG 1393 if (pb->rfs->flags & RESIZE_DEBUG_BMOVE) 1394 printf("ino=%u, blockcnt=%lld, %llu->%llu\n", 1395 pb->ino, blockcnt, block, new_block); 1396#endif 1397 block = new_block; 1398 } 1399 } 1400 if (pb->is_dir) { 1401 retval = ext2fs_add_dir_block2(fs->dblist, pb->ino, 1402 block, (int) blockcnt); 1403 if (retval) { 1404 pb->error = retval; 1405 ret |= BLOCK_ABORT; 1406 } 1407 } 1408 return ret; 1409} 1410 1411/* 1412 * Progress callback 1413 */ 1414static errcode_t progress_callback(ext2_filsys fs, 1415 ext2_inode_scan scan EXT2FS_ATTR((unused)), 1416 dgrp_t group, void * priv_data) 1417{ 1418 ext2_resize_t rfs = (ext2_resize_t) priv_data; 1419 errcode_t retval; 1420 1421 /* 1422 * This check is to protect against old ext2 libraries. It 1423 * shouldn't be needed against new libraries. 1424 */ 1425 if ((group+1) == 0) 1426 return 0; 1427 1428 if (rfs->progress) { 1429 io_channel_flush(fs->io); 1430 retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 1431 group+1, fs->group_desc_count); 1432 if (retval) 1433 return retval; 1434 } 1435 1436 return 0; 1437} 1438 1439static errcode_t inode_scan_and_fix(ext2_resize_t rfs) 1440{ 1441 struct process_block_struct pb; 1442 ext2_ino_t ino, new_inode; 1443 struct ext2_inode *inode = NULL; 1444 ext2_inode_scan scan = NULL; 1445 errcode_t retval; 1446 char *block_buf = 0; 1447 ext2_ino_t start_to_move; 1448 blk64_t orig_size; 1449 blk64_t new_block; 1450 int inode_size; 1451 1452 if ((rfs->old_fs->group_desc_count <= 1453 rfs->new_fs->group_desc_count) && 1454 !rfs->bmap) 1455 return 0; 1456 1457 /* 1458 * Save the original size of the old filesystem, and 1459 * temporarily set the size to be the new size if the new size 1460 * is larger. We need to do this to avoid catching an error 1461 * by the block iterator routines 1462 */ 1463 orig_size = ext2fs_blocks_count(rfs->old_fs->super); 1464 if (orig_size < ext2fs_blocks_count(rfs->new_fs->super)) 1465 ext2fs_blocks_count_set(rfs->old_fs->super, 1466 ext2fs_blocks_count(rfs->new_fs->super)); 1467 1468 retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan); 1469 if (retval) goto errout; 1470 1471 retval = ext2fs_init_dblist(rfs->old_fs, 0); 1472 if (retval) goto errout; 1473 retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf); 1474 if (retval) goto errout; 1475 1476 start_to_move = (rfs->new_fs->group_desc_count * 1477 rfs->new_fs->super->s_inodes_per_group); 1478 1479 if (rfs->progress) { 1480 retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 1481 0, rfs->old_fs->group_desc_count); 1482 if (retval) 1483 goto errout; 1484 } 1485 ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs); 1486 pb.rfs = rfs; 1487 pb.inode = inode; 1488 pb.error = 0; 1489 new_inode = EXT2_FIRST_INODE(rfs->new_fs->super); 1490 inode_size = EXT2_INODE_SIZE(rfs->new_fs->super); 1491 inode = malloc(inode_size); 1492 if (!inode) { 1493 retval = ENOMEM; 1494 goto errout; 1495 } 1496 /* 1497 * First, copy all of the inodes that need to be moved 1498 * elsewhere in the inode table 1499 */ 1500 while (1) { 1501 retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size); 1502 if (retval) goto errout; 1503 if (!ino) 1504 break; 1505 1506 if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO) 1507 continue; /* inode not in use */ 1508 1509 pb.is_dir = LINUX_S_ISDIR(inode->i_mode); 1510 pb.changed = 0; 1511 1512 if (ext2fs_file_acl_block(rfs->old_fs, inode) && rfs->bmap) { 1513 new_block = extent_translate(rfs->old_fs, rfs->bmap, 1514 ext2fs_file_acl_block(rfs->old_fs, inode)); 1515 if (new_block) { 1516 ext2fs_file_acl_block_set(rfs->old_fs, inode, 1517 new_block); 1518 retval = ext2fs_write_inode_full(rfs->old_fs, 1519 ino, inode, inode_size); 1520 if (retval) goto errout; 1521 } 1522 } 1523 1524 if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) && 1525 (rfs->bmap || pb.is_dir)) { 1526 pb.ino = ino; 1527 retval = ext2fs_block_iterate3(rfs->old_fs, 1528 ino, 0, block_buf, 1529 process_block, &pb); 1530 if (retval) 1531 goto errout; 1532 if (pb.error) { 1533 retval = pb.error; 1534 goto errout; 1535 } 1536 } 1537 1538 if (ino <= start_to_move) 1539 continue; /* Don't need to move it. */ 1540 1541 /* 1542 * Find a new inode 1543 */ 1544 retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode); 1545 if (retval) 1546 goto errout; 1547 1548 ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1, 1549 pb.is_dir); 1550 if (pb.changed) { 1551 /* Get the new version of the inode */ 1552 retval = ext2fs_read_inode_full(rfs->old_fs, ino, 1553 inode, inode_size); 1554 if (retval) goto errout; 1555 } 1556 inode->i_ctime = time(0); 1557 retval = ext2fs_write_inode_full(rfs->old_fs, new_inode, 1558 inode, inode_size); 1559 if (retval) goto errout; 1560 1561#ifdef RESIZE2FS_DEBUG 1562 if (rfs->flags & RESIZE_DEBUG_INODEMAP) 1563 printf("Inode moved %u->%u\n", ino, new_inode); 1564#endif 1565 if (!rfs->imap) { 1566 retval = ext2fs_create_extent_table(&rfs->imap, 0); 1567 if (retval) 1568 goto errout; 1569 } 1570 ext2fs_add_extent_entry(rfs->imap, ino, new_inode); 1571 } 1572 io_channel_flush(rfs->old_fs->io); 1573 1574errout: 1575 ext2fs_blocks_count_set(rfs->old_fs->super, orig_size); 1576 if (rfs->bmap) { 1577 ext2fs_free_extent_table(rfs->bmap); 1578 rfs->bmap = 0; 1579 } 1580 if (scan) 1581 ext2fs_close_inode_scan(scan); 1582 if (block_buf) 1583 ext2fs_free_mem(&block_buf); 1584 free(inode); 1585 return retval; 1586} 1587 1588/* -------------------------------------------------------------------- 1589 * 1590 * Resize processing, phase 4. 1591 * 1592 * -------------------------------------------------------------------- 1593 */ 1594 1595struct istruct { 1596 ext2_resize_t rfs; 1597 errcode_t err; 1598 unsigned int max_dirs; 1599 unsigned int num; 1600}; 1601 1602static int check_and_change_inodes(ext2_ino_t dir, 1603 int entry EXT2FS_ATTR((unused)), 1604 struct ext2_dir_entry *dirent, int offset, 1605 int blocksize EXT2FS_ATTR((unused)), 1606 char *buf EXT2FS_ATTR((unused)), 1607 void *priv_data) 1608{ 1609 struct istruct *is = (struct istruct *) priv_data; 1610 struct ext2_inode inode; 1611 ext2_ino_t new_inode; 1612 errcode_t retval; 1613 1614 if (is->rfs->progress && offset == 0) { 1615 io_channel_flush(is->rfs->old_fs->io); 1616 is->err = (is->rfs->progress)(is->rfs, 1617 E2_RSZ_INODE_REF_UPD_PASS, 1618 ++is->num, is->max_dirs); 1619 if (is->err) 1620 return DIRENT_ABORT; 1621 } 1622 1623 if (!dirent->inode) 1624 return 0; 1625 1626 new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode); 1627 1628 if (!new_inode) 1629 return 0; 1630#ifdef RESIZE2FS_DEBUG 1631 if (is->rfs->flags & RESIZE_DEBUG_INODEMAP) 1632 printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n", 1633 dir, dirent->name_len&0xFF, dirent->name, 1634 dirent->inode, new_inode); 1635#endif 1636 1637 dirent->inode = new_inode; 1638 1639 /* Update the directory mtime and ctime */ 1640 retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode); 1641 if (retval == 0) { 1642 inode.i_mtime = inode.i_ctime = time(0); 1643 is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode); 1644 if (is->err) 1645 return DIRENT_ABORT; 1646 } 1647 1648 return DIRENT_CHANGED; 1649} 1650 1651static errcode_t inode_ref_fix(ext2_resize_t rfs) 1652{ 1653 errcode_t retval; 1654 struct istruct is; 1655 1656 if (!rfs->imap) 1657 return 0; 1658 1659 /* 1660 * Now, we iterate over all of the directories to update the 1661 * inode references 1662 */ 1663 is.num = 0; 1664 is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist); 1665 is.rfs = rfs; 1666 is.err = 0; 1667 1668 if (rfs->progress) { 1669 retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 1670 0, is.max_dirs); 1671 if (retval) 1672 goto errout; 1673 } 1674 1675 retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist, 1676 DIRENT_FLAG_INCLUDE_EMPTY, 0, 1677 check_and_change_inodes, &is); 1678 if (retval) 1679 goto errout; 1680 if (is.err) { 1681 retval = is.err; 1682 goto errout; 1683 } 1684 1685 if (rfs->progress && (is.num < is.max_dirs)) 1686 (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 1687 is.max_dirs, is.max_dirs); 1688 1689errout: 1690 ext2fs_free_extent_table(rfs->imap); 1691 rfs->imap = 0; 1692 return retval; 1693} 1694 1695 1696/* -------------------------------------------------------------------- 1697 * 1698 * Resize processing, phase 5. 1699 * 1700 * In this phase we actually move the inode table around, and then 1701 * update the summary statistics. This is scary, since aborting here 1702 * will potentially scramble the filesystem. (We are moving the 1703 * inode tables around in place, and so the potential for lost data, 1704 * or at the very least scrambling the mapping between filenames and 1705 * inode numbers is very high in case of a power failure here.) 1706 * -------------------------------------------------------------------- 1707 */ 1708 1709 1710/* 1711 * A very scary routine --- this one moves the inode table around!!! 1712 * 1713 * After this you have to use the rfs->new_fs file handle to read and 1714 * write inodes. 1715 */ 1716static errcode_t move_itables(ext2_resize_t rfs) 1717{ 1718 int n, num, size; 1719 long long diff; 1720 dgrp_t i, max_groups; 1721 ext2_filsys fs = rfs->new_fs; 1722 char *cp; 1723 blk64_t old_blk, new_blk, blk; 1724 errcode_t retval; 1725 int j, to_move, moved; 1726 1727 max_groups = fs->group_desc_count; 1728 if (max_groups > rfs->old_fs->group_desc_count) 1729 max_groups = rfs->old_fs->group_desc_count; 1730 1731 size = fs->blocksize * fs->inode_blocks_per_group; 1732 if (!rfs->itable_buf) { 1733 retval = ext2fs_get_mem(size, &rfs->itable_buf); 1734 if (retval) 1735 return retval; 1736 } 1737 1738 /* 1739 * Figure out how many inode tables we need to move 1740 */ 1741 to_move = moved = 0; 1742 for (i=0; i < max_groups; i++) 1743 if (ext2fs_inode_table_loc(rfs->old_fs, i) != 1744 ext2fs_inode_table_loc(fs, i)) 1745 to_move++; 1746 1747 if (to_move == 0) 1748 return 0; 1749 1750 if (rfs->progress) { 1751 retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 1752 0, to_move); 1753 if (retval) 1754 goto errout; 1755 } 1756 1757 rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1758 1759 for (i=0; i < max_groups; i++) { 1760 old_blk = ext2fs_inode_table_loc(rfs->old_fs, i); 1761 new_blk = ext2fs_inode_table_loc(fs, i); 1762 diff = new_blk - old_blk; 1763 1764#ifdef RESIZE2FS_DEBUG 1765 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1766 printf("Itable move group %d block %llu->%llu (diff %lld)\n", 1767 i, old_blk, new_blk, diff); 1768#endif 1769 1770 if (!diff) 1771 continue; 1772 1773 retval = io_channel_read_blk64(fs->io, old_blk, 1774 fs->inode_blocks_per_group, 1775 rfs->itable_buf); 1776 if (retval) 1777 goto errout; 1778 /* 1779 * The end of the inode table segment often contains 1780 * all zeros, and we're often only moving the inode 1781 * table down a block or two. If so, we can optimize 1782 * things by not rewriting blocks that we know to be zero 1783 * already. 1784 */ 1785 for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--) 1786 if (*cp) 1787 break; 1788 n = n >> EXT2_BLOCK_SIZE_BITS(fs->super); 1789#ifdef RESIZE2FS_DEBUG 1790 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1791 printf("%d blocks of zeros...\n", n); 1792#endif 1793 num = fs->inode_blocks_per_group; 1794 if (n > diff) 1795 num -= n; 1796 1797 retval = io_channel_write_blk64(fs->io, new_blk, 1798 num, rfs->itable_buf); 1799 if (retval) { 1800 io_channel_write_blk64(fs->io, old_blk, 1801 num, rfs->itable_buf); 1802 goto errout; 1803 } 1804 if (n > diff) { 1805 retval = io_channel_write_blk64(fs->io, 1806 old_blk + fs->inode_blocks_per_group, 1807 diff, (rfs->itable_buf + 1808 (fs->inode_blocks_per_group - diff) * 1809 fs->blocksize)); 1810 if (retval) 1811 goto errout; 1812 } 1813 1814 for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; 1815 j < fs->inode_blocks_per_group ; j++, blk++) 1816 ext2fs_block_alloc_stats2(fs, blk, -1); 1817 1818 ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk); 1819 ext2fs_group_desc_csum_set(rfs->old_fs, i); 1820 ext2fs_mark_super_dirty(rfs->old_fs); 1821 ext2fs_flush(rfs->old_fs); 1822 1823 if (rfs->progress) { 1824 retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 1825 ++moved, to_move); 1826 if (retval) 1827 goto errout; 1828 } 1829 } 1830 mark_table_blocks(fs, fs->block_map); 1831 ext2fs_flush(fs); 1832#ifdef RESIZE2FS_DEBUG 1833 if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1834 printf("Inode table move finished.\n"); 1835#endif 1836 return 0; 1837 1838errout: 1839 return retval; 1840} 1841 1842/* 1843 * Fix the resize inode 1844 */ 1845static errcode_t fix_resize_inode(ext2_filsys fs) 1846{ 1847 struct ext2_inode inode; 1848 errcode_t retval; 1849 char *block_buf = NULL; 1850 1851 if (!(fs->super->s_feature_compat & 1852 EXT2_FEATURE_COMPAT_RESIZE_INODE)) 1853 return 0; 1854 1855 retval = ext2fs_get_mem(fs->blocksize, &block_buf); 1856 if (retval) goto errout; 1857 1858 retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); 1859 if (retval) goto errout; 1860 1861 ext2fs_iblk_set(fs, &inode, 1); 1862 1863 retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); 1864 if (retval) goto errout; 1865 1866 if (!inode.i_block[EXT2_DIND_BLOCK]) { 1867 /* 1868 * Avoid zeroing out block #0; that's rude. This 1869 * should never happen anyway since the filesystem 1870 * should be fsck'ed and we assume it is consistent. 1871 */ 1872 fprintf(stderr, "%s", 1873 _("Should never happen: resize inode corrupt!\n")); 1874 exit(1); 1875 } 1876 1877 memset(block_buf, 0, fs->blocksize); 1878 1879 retval = io_channel_write_blk64(fs->io, inode.i_block[EXT2_DIND_BLOCK], 1880 1, block_buf); 1881 if (retval) goto errout; 1882 1883 retval = ext2fs_create_resize_inode(fs); 1884 if (retval) 1885 goto errout; 1886 1887errout: 1888 if (block_buf) 1889 ext2fs_free_mem(&block_buf); 1890 return retval; 1891} 1892 1893/* 1894 * Finally, recalculate the summary information 1895 */ 1896static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) 1897{ 1898 blk64_t blk; 1899 ext2_ino_t ino; 1900 unsigned int group = 0; 1901 unsigned int count = 0; 1902 blk64_t total_blocks_free = 0; 1903 int total_inodes_free = 0; 1904 int group_free = 0; 1905 int uninit = 0; 1906 blk64_t super_blk, old_desc_blk, new_desc_blk; 1907 int old_desc_blocks; 1908 1909 /* 1910 * First calculate the block statistics 1911 */ 1912 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); 1913 ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk, 1914 &new_desc_blk, 0); 1915 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 1916 old_desc_blocks = fs->super->s_first_meta_bg; 1917 else 1918 old_desc_blocks = fs->desc_blocks + 1919 fs->super->s_reserved_gdt_blocks; 1920 for (blk = B2C(fs->super->s_first_data_block); 1921 blk < ext2fs_blocks_count(fs->super); 1922 blk += EXT2FS_CLUSTER_RATIO(fs)) { 1923 if ((uninit && 1924 !(EQ_CLSTR(blk, super_blk) || 1925 ((old_desc_blk && old_desc_blocks && 1926 GE_CLSTR(blk, old_desc_blk) && 1927 LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) || 1928 ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) || 1929 EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) || 1930 EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) || 1931 ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) && 1932 LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group) 1933 + fs->inode_blocks_per_group))))) || 1934 (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) { 1935 group_free++; 1936 total_blocks_free++; 1937 } 1938 count++; 1939 if ((count == fs->super->s_clusters_per_group) || 1940 EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) { 1941 ext2fs_bg_free_blocks_count_set(fs, group, group_free); 1942 ext2fs_group_desc_csum_set(fs, group); 1943 group++; 1944 if (group >= fs->group_desc_count) 1945 break; 1946 count = 0; 1947 group_free = 0; 1948 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); 1949 ext2fs_super_and_bgd_loc2(fs, group, &super_blk, 1950 &old_desc_blk, 1951 &new_desc_blk, 0); 1952 if (fs->super->s_feature_incompat & 1953 EXT2_FEATURE_INCOMPAT_META_BG) 1954 old_desc_blocks = fs->super->s_first_meta_bg; 1955 else 1956 old_desc_blocks = fs->desc_blocks + 1957 fs->super->s_reserved_gdt_blocks; 1958 } 1959 } 1960 total_blocks_free = C2B(total_blocks_free); 1961 ext2fs_free_blocks_count_set(fs->super, total_blocks_free); 1962 1963 /* 1964 * Next, calculate the inode statistics 1965 */ 1966 group_free = 0; 1967 count = 0; 1968 group = 0; 1969 1970 /* Protect loop from wrap-around if s_inodes_count maxed */ 1971 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT); 1972 for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) { 1973 if (uninit || 1974 !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) { 1975 group_free++; 1976 total_inodes_free++; 1977 } 1978 count++; 1979 if ((count == fs->super->s_inodes_per_group) || 1980 (ino == fs->super->s_inodes_count)) { 1981 ext2fs_bg_free_inodes_count_set(fs, group, group_free); 1982 ext2fs_group_desc_csum_set(fs, group); 1983 group++; 1984 if (group >= fs->group_desc_count) 1985 break; 1986 count = 0; 1987 group_free = 0; 1988 uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT); 1989 } 1990 } 1991 fs->super->s_free_inodes_count = total_inodes_free; 1992 ext2fs_mark_super_dirty(fs); 1993 return 0; 1994} 1995 1996/* 1997 * Journal may have been relocated; update the backup journal blocks 1998 * in the superblock. 1999 */ 2000static errcode_t fix_sb_journal_backup(ext2_filsys fs) 2001{ 2002 errcode_t retval; 2003 struct ext2_inode inode; 2004 2005 if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 2006 return 0; 2007 2008 /* External journal? Nothing to do. */ 2009 if (fs->super->s_journal_dev && !fs->super->s_journal_inum) 2010 return 0; 2011 2012 retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode); 2013 if (retval) 2014 return retval; 2015 memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); 2016 fs->super->s_jnl_blocks[15] = inode.i_size_high; 2017 fs->super->s_jnl_blocks[16] = inode.i_size; 2018 fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; 2019 ext2fs_mark_super_dirty(fs); 2020 return 0; 2021} 2022 2023static int calc_group_overhead(ext2_filsys fs, blk64_t grp, 2024 int old_desc_blocks) 2025{ 2026 blk64_t super_blk, old_desc_blk, new_desc_blk; 2027 int overhead; 2028 2029 /* inode table blocks plus allocation bitmaps */ 2030 overhead = fs->inode_blocks_per_group + 2; 2031 2032 ext2fs_super_and_bgd_loc2(fs, grp, &super_blk, 2033 &old_desc_blk, &new_desc_blk, 0); 2034 if ((grp == 0) || super_blk) 2035 overhead++; 2036 if (old_desc_blk) 2037 overhead += old_desc_blocks; 2038 else if (new_desc_blk) 2039 overhead++; 2040 return overhead; 2041} 2042 2043 2044/* 2045 * calcluate the minimum number of blocks the given fs can be resized to 2046 */ 2047blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags) 2048{ 2049 ext2_ino_t inode_count; 2050 dgrp_t groups; 2051 blk64_t blks_needed, data_blocks; 2052 blk64_t grp, data_needed, last_start; 2053 blk64_t overhead = 0; 2054 int old_desc_blocks; 2055 int extra_groups = 0; 2056 int flexbg_size = 1 << fs->super->s_log_groups_per_flex; 2057 2058 /* 2059 * first figure out how many group descriptors we need to 2060 * handle the number of inodes we have 2061 */ 2062 inode_count = fs->super->s_inodes_count - 2063 fs->super->s_free_inodes_count; 2064 blks_needed = ext2fs_div_ceil(inode_count, 2065 fs->super->s_inodes_per_group) * 2066 EXT2_BLOCKS_PER_GROUP(fs->super); 2067 groups = ext2fs_div64_ceil(blks_needed, 2068 EXT2_BLOCKS_PER_GROUP(fs->super)); 2069#ifdef RESIZE2FS_DEBUG 2070 if (flags & RESIZE_DEBUG_MIN_CALC) 2071 printf("fs has %d inodes, %d groups required.\n", 2072 inode_count, groups); 2073#endif 2074 2075 /* 2076 * number of old-style block group descriptor blocks 2077 */ 2078 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 2079 old_desc_blocks = fs->super->s_first_meta_bg; 2080 else 2081 old_desc_blocks = fs->desc_blocks + 2082 fs->super->s_reserved_gdt_blocks; 2083 2084 /* calculate how many blocks are needed for data */ 2085 data_needed = ext2fs_blocks_count(fs->super) - 2086 ext2fs_free_blocks_count(fs->super); 2087 2088 for (grp = 0; grp < fs->group_desc_count; grp++) 2089 data_needed -= calc_group_overhead(fs, grp, old_desc_blocks); 2090#ifdef RESIZE2FS_DEBUG 2091 if (flags & RESIZE_DEBUG_MIN_CALC) 2092 printf("fs requires %llu data blocks.\n", data_needed); 2093#endif 2094 2095 /* 2096 * For ext4 we need to allow for up to a flex_bg worth of 2097 * inode tables of slack space so the resize operation can be 2098 * guaranteed to finish. 2099 */ 2100 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 2101 extra_groups = flexbg_size - (groups & (flexbg_size - 1)); 2102 data_needed += fs->inode_blocks_per_group * extra_groups; 2103 extra_groups = groups % flexbg_size; 2104 } 2105 2106 /* 2107 * figure out how many data blocks we have given the number of groups 2108 * we need for our inodes 2109 */ 2110 data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super); 2111 last_start = 0; 2112 for (grp = 0; grp < groups; grp++) { 2113 overhead = calc_group_overhead(fs, grp, old_desc_blocks); 2114 2115 /* 2116 * we want to keep track of how much data we can store in 2117 * the groups leading up to the last group so we can determine 2118 * how big the last group needs to be 2119 */ 2120 if (grp != (groups - 1)) 2121 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - 2122 overhead; 2123 2124 data_blocks -= overhead; 2125 } 2126#ifdef RESIZE2FS_DEBUG 2127 if (flags & RESIZE_DEBUG_MIN_CALC) 2128 printf("With %d group(s), we have %llu blocks available.\n", 2129 groups, data_blocks); 2130#endif 2131 2132 /* 2133 * if we need more group descriptors in order to accomodate our data 2134 * then we need to add them here 2135 */ 2136 while (data_needed > data_blocks) { 2137 blk64_t remainder = data_needed - data_blocks; 2138 dgrp_t extra_grps; 2139 2140 /* figure out how many more groups we need for the data */ 2141 extra_grps = ext2fs_div64_ceil(remainder, 2142 EXT2_BLOCKS_PER_GROUP(fs->super)); 2143 2144 data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super); 2145 2146 /* ok we have to account for the last group */ 2147 overhead = calc_group_overhead(fs, groups-1, old_desc_blocks); 2148 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead; 2149 2150 for (grp = groups; grp < groups+extra_grps; grp++) { 2151 overhead = calc_group_overhead(fs, grp, 2152 old_desc_blocks); 2153 2154 /* 2155 * again, we need to see how much data we cram into 2156 * all of the groups leading up to the last group 2157 */ 2158 if (grp != (groups + extra_grps - 1)) 2159 last_start += EXT2_BLOCKS_PER_GROUP(fs->super) 2160 - overhead; 2161 2162 data_blocks -= overhead; 2163 } 2164 2165 groups += extra_grps; 2166 extra_groups += extra_grps; 2167 if (fs->super->s_feature_incompat 2168 & EXT4_FEATURE_INCOMPAT_FLEX_BG 2169 && extra_groups > flexbg_size) { 2170 /* 2171 * For ext4 we need to allow for up to a flex_bg worth 2172 * of inode tables of slack space so the resize 2173 * operation can be guaranteed to finish. 2174 */ 2175 extra_groups = flexbg_size - 2176 (groups & (flexbg_size - 1)); 2177 data_needed += (fs->inode_blocks_per_group * 2178 extra_groups); 2179 extra_groups = groups % flexbg_size; 2180 } 2181#ifdef RESIZE2FS_DEBUG 2182 if (flags & RESIZE_DEBUG_MIN_CALC) 2183 printf("Added %d extra group(s), " 2184 "data_needed %llu, data_blocks %llu, " 2185 "last_start %llu\n", 2186 extra_grps, data_needed, data_blocks, 2187 last_start); 2188#endif 2189 } 2190 2191 /* now for the fun voodoo */ 2192 overhead = calc_group_overhead(fs, groups-1, old_desc_blocks); 2193#ifdef RESIZE2FS_DEBUG 2194 if (flags & RESIZE_DEBUG_MIN_CALC) 2195 printf("Last group's overhead is %llu\n", overhead); 2196#endif 2197 2198 /* 2199 * if this is the case then the last group is going to have data in it 2200 * so we need to adjust the size of the last group accordingly 2201 */ 2202 if (last_start < data_needed) { 2203 blk64_t remainder = data_needed - last_start; 2204 2205#ifdef RESIZE2FS_DEBUG 2206 if (flags & RESIZE_DEBUG_MIN_CALC) 2207 printf("Need %llu data blocks in last group\n", 2208 remainder); 2209#endif 2210 /* 2211 * 50 is a magic number that mkfs/resize uses to see if its 2212 * even worth making/resizing the fs. basically you need to 2213 * have at least 50 blocks in addition to the blocks needed 2214 * for the metadata in the last group 2215 */ 2216 if (remainder > 50) 2217 overhead += remainder; 2218 else 2219 overhead += 50; 2220 } else 2221 overhead += 50; 2222 2223 overhead += fs->super->s_first_data_block; 2224#ifdef RESIZE2FS_DEBUG 2225 if (flags & RESIZE_DEBUG_MIN_CALC) 2226 printf("Final size of last group is %lld\n", overhead); 2227#endif 2228 2229 /* 2230 * since our last group doesn't have to be BLOCKS_PER_GROUP large, we 2231 * only do groups-1, and then add the number of blocks needed to 2232 * handle the group descriptor metadata+data that we need 2233 */ 2234 blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super); 2235 blks_needed += overhead; 2236 2237 /* 2238 * Make sure blks_needed covers the end of the inode table in 2239 * the last block group. 2240 */ 2241 overhead = ext2fs_inode_table_loc(fs, groups-1) + 2242 fs->inode_blocks_per_group; 2243 if (blks_needed < overhead) 2244 blks_needed = overhead; 2245 2246#ifdef RESIZE2FS_DEBUG 2247 if (flags & RESIZE_DEBUG_MIN_CALC) 2248 printf("Estimated blocks needed: %llu\n", blks_needed); 2249#endif 2250 2251 /* 2252 * If at this point we've already added up more "needed" than 2253 * the current size, just return current size as minimum. 2254 */ 2255 if (blks_needed >= ext2fs_blocks_count(fs->super)) 2256 return ext2fs_blocks_count(fs->super); 2257 /* 2258 * We need to reserve a few extra blocks if extents are 2259 * enabled, in case we need to grow the extent tree. The more 2260 * we shrink the file system, the more space we need. 2261 */ 2262 if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { 2263 blk64_t safe_margin = (ext2fs_blocks_count(fs->super) - 2264 blks_needed)/500; 2265#ifdef RESIZE2FS_DEBUG 2266 if (flags & RESIZE_DEBUG_MIN_CALC) 2267 printf("Extents safety margin: %llu\n", safe_margin); 2268#endif 2269 blks_needed += safe_margin; 2270 } 2271 2272 return blks_needed; 2273} 2274