1 /* 2 ext2_resize.c -- ext2 resizer 3 Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <config.h> 20 21 #ifndef DISCOVER_ONLY 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include "ext2.h" 26 27 static int ext2_add_group(struct ext2_fs *fs, blk_t groupsize) 28 { 29 blk_t admin; 30 int group; 31 blk_t groupstart; 32 blk_t newgdblocks; 33 int sparse; 34 35 if (fs->opt_verbose) 36 fputs ("ext2_add_group\n", stderr); 37 38 if (!ped_realloc ((void*) &fs->gd, 39 (fs->numgroups+1) * sizeof(struct ext2_group_desc) 40 + fs->blocksize)) 41 return 0; 42 43 if (fs->opt_debug) 44 { 45 if (EXT2_SUPER_BLOCKS_COUNT(fs->sb) != 46 EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) 47 + fs->numgroups * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) 48 { 49 fputs ("ext2_add_group: last (existing) group " 50 "isn't complete!\n", stderr); 51 52 return 0; 53 } 54 } 55 56 group = fs->numgroups; 57 sparse = ext2_is_group_sparse(fs, group); 58 groupstart = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) 59 + group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 60 61 admin = fs->adminblocks; 62 if (!sparse) 63 admin -= fs->gdblocks + 1; 64 65 if (fs->opt_debug) 66 { 67 if (groupsize < fs->adminblocks || 68 groupsize > EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) 69 { 70 fprintf(stderr, 71 "ext2_add_group: groups of %i blocks are " 72 "impossible!\n", groupsize); 73 74 return 0; 75 } 76 } 77 78 newgdblocks = ped_div_round_up((fs->numgroups + 1) 79 * sizeof(struct ext2_group_desc), 80 fs->blocksize); 81 if (newgdblocks != fs->gdblocks) 82 { 83 int i; 84 85 for (i=0;i<fs->numgroups;i++) 86 if (ext2_is_group_sparse(fs, i)) 87 { 88 blk_t start; 89 90 start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) 91 + i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 92 ext2_set_block_state(fs, 93 start + fs->gdblocks + 1, 1, 1); 94 } 95 96 fs->gdblocks++; 97 fs->adminblocks++; 98 if (sparse) 99 admin++; 100 } 101 102 fs->numgroups++; 103 104 fs->sb.s_inodes_count = PED_CPU_TO_LE32( 105 EXT2_SUPER_INODES_COUNT(fs->sb) 106 + EXT2_SUPER_INODES_PER_GROUP(fs->sb)); 107 fs->sb.s_blocks_count = PED_CPU_TO_LE32( 108 EXT2_SUPER_BLOCKS_COUNT(fs->sb) + groupsize); 109 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32( 110 EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + groupsize - admin); 111 fs->sb.s_free_inodes_count = PED_CPU_TO_LE32( 112 EXT2_SUPER_FREE_INODES_COUNT(fs->sb) 113 + EXT2_SUPER_INODES_PER_GROUP(fs->sb)); 114 fs->metadirty |= EXT2_META_SB; 115 116 { 117 blk_t off; 118 blk_t sparseoff; 119 120 off = groupstart; 121 sparseoff = off + fs->itoffset - 2; 122 123 if (sparse) 124 { 125 fs->gd[group].bg_block_bitmap 126 = PED_CPU_TO_LE32(sparseoff); 127 fs->gd[group].bg_inode_bitmap 128 = PED_CPU_TO_LE32(sparseoff + 1); 129 } 130 else 131 { 132 fs->gd[group].bg_block_bitmap 133 = PED_CPU_TO_LE32(off); 134 fs->gd[group].bg_inode_bitmap 135 = PED_CPU_TO_LE32(off + 1); 136 } 137 138 /* Hey, I don't know _why_ either */ 139 fs->gd[group].bg_inode_table = PED_CPU_TO_LE32(sparseoff + 2); 140 } 141 142 fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16(groupsize - admin); 143 fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16( 144 EXT2_SUPER_INODES_PER_GROUP(fs->sb)); 145 fs->gd[group].bg_used_dirs_count = 0; 146 fs->metadirty |= EXT2_META_SB | EXT2_META_GD; 147 148 { 149 struct ext2_buffer_head *bh; 150 blk_t i; 151 152 bh = ext2_bcreate(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group])); 153 if (!bh) 154 return 0; 155 156 if (sparse) 157 { 158 bh->data[0] |= _bitmap[0]; 159 for (i=1;i<=fs->gdblocks;i++) 160 bh->data[i>>3] |= _bitmap[i&7]; 161 } 162 163 i = EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]) - groupstart; 164 bh->data[i>>3] |= _bitmap[i&7]; 165 166 i = EXT2_GROUP_INODE_BITMAP(fs->gd[group]) - groupstart; 167 bh->data[i>>3] |= _bitmap[i&7]; 168 169 for (i=0;i<fs->inodeblocks;i++) 170 { 171 blk_t j; 172 173 j = EXT2_GROUP_INODE_TABLE(fs->gd[group]) 174 - groupstart + i; 175 bh->data[j>>3] |= _bitmap[j&7]; 176 } 177 178 for (i=groupsize;i<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);i++) 179 bh->data[i>>3] |= _bitmap[i&7]; 180 181 ext2_brelse(bh, 0); /* this is a block bitmap */ 182 } 183 184 if (!ext2_zero_blocks(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]), 1)) 185 return 0; 186 if (!ext2_zero_blocks(fs, EXT2_GROUP_INODE_TABLE(fs->gd[group]), 187 fs->inodeblocks)) 188 return 0; 189 190 if (fs->opt_safe) 191 if (!ext2_sync(fs)) 192 return 0; 193 194 return 1; 195 } 196 197 static int ext2_del_group(struct ext2_fs *fs) 198 { 199 blk_t admin; 200 int group; 201 blk_t groupsize; 202 blk_t newgdblocks; 203 int sparse; 204 205 if (fs->opt_verbose) 206 fputs ("ext2_del_group\n", stderr); 207 208 group = fs->numgroups - 1; 209 sparse = ext2_is_group_sparse(fs, group); 210 211 admin = fs->adminblocks; 212 if (!sparse) 213 admin -= fs->gdblocks + 1; 214 215 groupsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb) 216 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) 217 - group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 218 219 if (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) < groupsize - admin) 220 { 221 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 222 _("File system is too full to remove a group!")); 223 224 return 0; 225 } 226 227 if (EXT2_SUPER_FREE_INODES_COUNT(fs->sb) 228 < EXT2_SUPER_INODES_PER_GROUP(fs->sb)) 229 { 230 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 231 _("File system has too many allocated inodes to " 232 "remove a group!")); 233 return 0; 234 } 235 236 if (fs->opt_debug) 237 { 238 if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) != 239 EXT2_SUPER_INODES_PER_GROUP(fs->sb)) 240 { 241 fputs ("ext2_del_group: this should not " 242 "happen anymore!\n", stderr); 243 244 return 0; 245 } 246 } 247 248 newgdblocks = ped_div_round_up((fs->numgroups - 1) * 249 sizeof(struct ext2_group_desc), fs->blocksize); 250 251 if (newgdblocks != fs->gdblocks) 252 { 253 int i; 254 255 for (i=0;i<fs->numgroups;i++) 256 if (ext2_is_group_sparse(fs, i)) 257 { 258 blk_t start; 259 260 start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 261 i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 262 ext2_set_block_state(fs, 263 start + fs->gdblocks, 264 0, 1); 265 } 266 267 fs->gdblocks--; 268 fs->adminblocks--; 269 if (sparse) 270 admin--; 271 } 272 273 if (fs->opt_debug) 274 { 275 if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) 276 != groupsize - admin) 277 { 278 blk_t i; 279 blk_t num; 280 blk_t offset; 281 282 offset = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 283 group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 284 num = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 285 286 for (i=0;i<num;i++) 287 if (ext2_is_data_block(fs, offset+i) && 288 ext2_get_block_state(fs, offset+i)) 289 { 290 fprintf(stderr, 291 "error: block relocator " 292 "should have relocated " 293 "%i\n", 294 offset+i); 295 296 return 0; 297 } 298 } 299 } 300 301 fs->numgroups--; 302 303 fs->sb.s_inodes_count = PED_CPU_TO_LE32( 304 EXT2_SUPER_INODES_COUNT(fs->sb) 305 - EXT2_SUPER_INODES_PER_GROUP(fs->sb)); 306 fs->sb.s_blocks_count = PED_CPU_TO_LE32( 307 EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupsize); 308 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32( 309 EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - (groupsize - admin)); 310 fs->sb.s_free_inodes_count = PED_CPU_TO_LE32( 311 EXT2_SUPER_FREE_INODES_COUNT(fs->sb) 312 - EXT2_SUPER_INODES_PER_GROUP(fs->sb)); 313 fs->metadirty |= EXT2_META_SB; 314 315 if (fs->opt_safe) 316 ext2_sync(fs); 317 318 ped_realloc ((void*) &fs->gd, 319 fs->numgroups * sizeof(struct ext2_group_desc) 320 + fs->blocksize); 321 322 return 1; 323 } 324 325 static int ext2_grow_group(struct ext2_fs *fs, blk_t newsize) 326 { 327 int group; 328 blk_t groupoff; 329 blk_t gblocks; 330 blk_t i; 331 332 if (fs->opt_verbose) 333 fputs ("ext2_grow_group\n", stderr); 334 335 group = fs->numgroups - 1; 336 groupoff = group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) 337 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 338 gblocks = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupoff; 339 340 if (fs->opt_debug) 341 { 342 if (newsize < gblocks) 343 { 344 fputs ("ext2_grow_group: called to shrink group!\n", 345 stderr); 346 347 return 0; 348 } 349 350 if (gblocks == newsize) 351 { 352 fputs ("ext2_grow_group: nothing to do!\n", stderr); 353 return 0; 354 } 355 } 356 357 for (i=gblocks;i<newsize;i++) 358 ext2_set_block_state(fs, groupoff + i, 0, 1); 359 360 fs->sb.s_blocks_count = PED_CPU_TO_LE32( 361 EXT2_SUPER_BLOCKS_COUNT(fs->sb) + newsize - gblocks); 362 fs->metadirty |= EXT2_META_SB; 363 364 if (fs->opt_safe) 365 ext2_sync(fs); 366 367 return 1; 368 } 369 370 static int ext2_shrink_group(struct ext2_fs *fs, blk_t newsize) 371 { 372 blk_t admin; 373 int group; 374 blk_t groupoff; 375 blk_t gblocks; 376 blk_t i; 377 378 if (fs->opt_verbose) 379 fputs ("ext2_shrink_group\n", stderr); 380 381 group = fs->numgroups - 1; 382 383 admin = fs->adminblocks; 384 if (!ext2_is_group_sparse(fs, group)) 385 admin -= fs->gdblocks + 1; 386 387 groupoff = group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) 388 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 389 gblocks = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupoff; 390 391 if (fs->opt_debug) 392 { 393 if (newsize < admin) 394 { 395 fprintf(stderr, 396 "ext2_shrink_group: cant shrink a group " 397 "to %i blocks\n", newsize); 398 399 return 0; 400 } 401 402 if (newsize > gblocks) 403 { 404 fputs ("ext2_shrink_group: called to grow group!\n", 405 stderr); 406 407 return 0; 408 } 409 410 if (gblocks == newsize) 411 { 412 fputs ("ext2_shrink_group: nothing to do!\n", 413 stderr); 414 415 return 0; 416 } 417 } 418 419 for (i=newsize;i<gblocks;i++) 420 { 421 if (fs->opt_debug && ext2_get_block_state(fs, groupoff + i)) 422 { 423 fprintf(stderr, 424 "error: block relocator should have relocated " 425 "%i\n", 426 groupoff + i); 427 428 return 0; 429 } 430 431 ext2_set_block_state(fs, groupoff + i, 1, 0); 432 } 433 434 i = gblocks - newsize; 435 fs->sb.s_blocks_count = PED_CPU_TO_LE32( 436 EXT2_SUPER_BLOCKS_COUNT(fs->sb) - i); 437 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32( 438 EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - i); 439 fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16( 440 EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) - i); 441 442 fs->metadirty |= EXT2_META_SB | EXT2_META_GD; 443 444 if (fs->opt_safe) 445 ext2_sync(fs); 446 447 return 1; 448 } 449 450 451 452 453 454 455 static int ext2_grow_fs(struct ext2_fs *fs, blk_t newsize, PedTimer* timer) 456 { 457 blk_t diff; 458 blk_t sizelast; 459 blk_t origsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb); 460 461 if (fs->opt_verbose) 462 fputs ("ext2_grow_fs\n", stderr); 463 464 if (!ext2_block_relocate(fs, newsize)) 465 return 0; 466 467 if (!ext2_metadata_push(fs, newsize)) 468 return 0; 469 470 diff = newsize - EXT2_SUPER_BLOCKS_COUNT(fs->sb); 471 sizelast = EXT2_SUPER_BLOCKS_COUNT(fs->sb) 472 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) 473 - (fs->numgroups-1) * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 474 475 if (sizelast != EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) 476 { 477 blk_t growto; 478 479 growto = sizelast + diff; 480 if (growto > EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) 481 growto = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 482 483 if (!ext2_grow_group(fs, growto)) 484 return 0; 485 486 diff -= growto - sizelast; 487 } 488 489 ped_timer_reset (timer); 490 ped_timer_set_state_name (timer, _("adding groups")); 491 492 while (diff) 493 { 494 ped_timer_update (timer, 495 1.0 - 1.0 * diff / (newsize - origsize)); 496 497 sizelast = PED_MIN(diff, EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); 498 if (!ext2_add_group(fs, sizelast)) 499 return 0; 500 501 diff -= sizelast; 502 } 503 504 ped_timer_update (timer, 1.0); 505 506 return 1; 507 } 508 509 static int ext2_shrink_fs(struct ext2_fs *fs, blk_t newsize, 510 PedTimer* timer) 511 { 512 blk_t origsize = EXT2_SUPER_BLOCKS_COUNT (fs->sb); 513 blk_t diff; 514 int newgroups; 515 blk_t sizelast; 516 517 if (fs->opt_verbose) 518 fputs ("ext2_shrink_fs\n", stderr); 519 520 newgroups = ped_div_round_up (newsize 521 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), 522 EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); 523 if (EXT2_SUPER_BLOCKS_COUNT(fs->sb) 524 - EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) > newsize) 525 { 526 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 527 _("Your file system is too full to resize it to %i " 528 "blocks. Sorry."), newsize); 529 return 0; 530 } 531 532 if (EXT2_SUPER_INODES_COUNT(fs->sb) 533 - EXT2_SUPER_FREE_INODES_COUNT(fs->sb) 534 > newgroups * EXT2_SUPER_INODES_PER_GROUP(fs->sb)) 535 { 536 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 537 _("Your file system has too many occupied inodes to " 538 "resize it to %i blocks. Sorry."), newsize); 539 return 0; 540 } 541 542 if (!ext2_inode_relocate(fs, newgroups)) 543 return 0; 544 545 if (!ext2_block_relocate(fs, newsize)) 546 return 0; 547 548 diff = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - newsize; 549 550 ped_timer_reset (timer); 551 ped_timer_set_state_name (timer, _("shrinking")); 552 553 while (diff > 0) 554 { 555 ped_timer_update (timer, 556 1.0 - 1.0 * diff / (origsize - newsize)); 557 558 sizelast = EXT2_SUPER_BLOCKS_COUNT(fs->sb) 559 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - 560 (fs->numgroups - 1) 561 * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 562 563 if (diff < sizelast) 564 { 565 if (!ext2_shrink_group(fs, sizelast - diff)) 566 return 0; 567 568 diff = 0; 569 } 570 else 571 { 572 if (!ext2_del_group(fs)) 573 return 0; 574 575 diff -= sizelast; 576 } 577 } 578 579 ped_timer_update (timer, 1.0); 580 581 return 1; 582 } 583 584 int ext2_determine_itoffset(struct ext2_fs *fs) 585 { 586 int i; 587 588 fs->itoffset = EXT2_GROUP_INODE_TABLE(fs->gd[0]) 589 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 590 591 /*PED_DEBUG (0x20, "itoffset is %d", fs->itoffset); 592 593 PED_DEBUG (0x20, "walking %d groups", fs->numgroups);*/ 594 595 for (i=0;i<fs->numgroups;i++) 596 { 597 blk_t start; 598 blk_t bb; 599 blk_t ib; 600 blk_t it; 601 602 start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) 603 + (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); 604 it = start + fs->itoffset; 605 606 /*PED_DEBUG (0x21, "start = %d, it = %d", start, it);*/ 607 608 if (ext2_is_group_sparse(fs, i)) 609 { 610 /*PED_DEBUG (0x21, "%d has a superblock copy", i);*/ 611 bb = it - 2; 612 ib = it - 1; 613 } 614 else 615 { 616 /*PED_DEBUG (0x21, "%d doesn't have a superblock copy", 617 i);*/ 618 bb = start; 619 ib = start + 1; 620 } 621 622 if (EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) != bb || 623 EXT2_GROUP_INODE_BITMAP(fs->gd[i]) != ib || 624 EXT2_GROUP_INODE_TABLE(fs->gd[i]) != it) 625 { 626 /* ped_exception_throw (PED_EXCEPTION_NO_FEATURE, 627 PED_EXCEPTION_CANCEL, 628 _("This ext2 file system has a rather strange layout! " 629 "Parted can't resize this (yet)."));*/ 630 631 /* PED_DEBUG (0x21, "calculated block bitmap to be %d, " 632 "but fs says %d.", bb, 633 EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])); 634 PED_DEBUG (0x21, "calculated inode bitmap to be %d, " 635 "but fs says %d.", ib, 636 EXT2_GROUP_INODE_BITMAP(fs->gd[i])); 637 PED_DEBUG (0x21, "calculated inode table to be %d, " 638 "but fs says %d.", it, 639 EXT2_GROUP_INODE_TABLE(fs->gd[i]));*/ 640 641 return 0; 642 } 643 } 644 645 return 1; 646 } 647 648 int ext2_resize_fs(struct ext2_fs *fs, blk_t newsize, PedTimer* timer) 649 { 650 blk_t residue; 651 int status; 652 653 if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS) 654 { 655 ped_exception_throw ( 656 PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL, 657 _("File system has errors! You should run e2fsck.")); 658 return 0; 659 } 660 661 if (!(EXT2_SUPER_STATE(fs->sb) & EXT2_VALID_FS)) 662 { 663 ped_exception_throw ( 664 PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 665 _("File system was not cleanly unmounted! " 666 "You should run e2fsck.")); 667 return 0; 668 } 669 670 if (EXT2_SUPER_FEATURE_COMPAT(fs->sb) 671 & EXT2_FEATURE_COMPAT_HAS_DIR_INDEX) { 672 if (ped_exception_throw ( 673 PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL, 674 _("The file system has the 'dir_index' feature " 675 "enabled. Parted can only resize the file system " 676 "if it disables this feature. You can enable it " 677 "later by running 'tune2fs -O dir_index DEVICE' " 678 "and then 'e2fsck -fD DEVICE'.")) 679 != PED_EXCEPTION_IGNORE) 680 return 0; 681 fs->sb.s_feature_compat 682 = PED_CPU_TO_LE32(EXT2_SUPER_FEATURE_COMPAT(fs->sb) 683 & ~EXT2_FEATURE_COMPAT_HAS_DIR_INDEX); 684 fs->metadirty |= EXT2_META_SB; 685 } 686 687 if (!ext2_determine_itoffset(fs) && ped_exception_throw ( 688 PED_EXCEPTION_WARNING, 689 PED_EXCEPTION_OK_CANCEL, 690 _("A resize operation on this file system will " 691 "use EXPERIMENTAL code\n" 692 "that MAY CORRUPT it (although no one has " 693 "reported any such damage yet).\n" 694 "You should at least backup your data first, " 695 "and run 'e2fsck -f' afterwards.")) 696 == PED_EXCEPTION_CANCEL) 697 { 698 return 0; 699 } 700 701 if (fs->opt_verbose) 702 fputs ("ext2_resize_fs\n", stderr); 703 704 residue = (newsize - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) 705 % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 706 if (residue && residue <= fs->adminblocks) 707 newsize -= residue; 708 709 if (newsize == EXT2_SUPER_BLOCKS_COUNT(fs->sb)) 710 return 1; 711 712 fs->relocator_pool 713 = (unsigned char *)ped_malloc(ext2_relocator_pool_size << 10); 714 if (!fs->relocator_pool) 715 return 0; 716 fs->relocator_pool_end 717 = fs->relocator_pool + (ext2_relocator_pool_size << 10); 718 719 if (newsize < EXT2_SUPER_BLOCKS_COUNT(fs->sb)) 720 status = ext2_shrink_fs(fs, newsize, timer); 721 else 722 status = ext2_grow_fs(fs, newsize, timer); 723 724 ped_free(fs->relocator_pool); 725 fs->relocator_pool = NULL; 726 fs->relocator_pool_end = NULL; 727 728 return status; 729 } 730 #endif /* !DISCOVER_ONLY */