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