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