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