e2fsck.c revision 21c84b71e205b5ab13f14343da5645dcc985856d
1/* 2 * e2fsck.c - a consistency checker for the new extended file system. 3 * 4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12/* Usage: e2fsck [-dfpnsvy] device 13 * -d -- debugging this program 14 * -f -- check the fs even if it is marked valid 15 * -p -- "preen" the filesystem 16 * -n -- open the filesystem r/o mode; never try to fix problems 17 * -v -- verbose (tells how many files) 18 * -y -- always answer yes to questions 19 * 20 * The device may be a block device or a image of one, but this isn't 21 * enforced (but it's not much fun on a character device :-). 22 */ 23 24#include <stdio.h> 25#ifdef HAVE_STDLIB_H 26#include <stdlib.h> 27#endif 28#include <string.h> 29#include <fcntl.h> 30#include <ctype.h> 31#include <termios.h> 32#include <time.h> 33#ifdef HAVE_GETOPT_H 34#include <getopt.h> 35#endif 36#include <unistd.h> 37#ifdef HAVE_ERRNO_H 38#include <errno.h> 39#endif 40#ifdef HAVE_MNTENT_H 41#include <mntent.h> 42#endif 43#include <sys/ioctl.h> 44#include <malloc.h> 45 46#include "et/com_err.h" 47#include "uuid/uuid.h" 48#include "e2fsck.h" 49#include "problem.h" 50#include "../version.h" 51 52extern int isatty(int); 53 54const char * program_name = "e2fsck"; 55const char * device_name = NULL; 56const char * filesystem_name = NULL; 57 58/* Command line options */ 59int nflag = 0; 60int yflag = 0; 61int tflag = 0; /* Do timing */ 62int cflag = 0; /* check disk */ 63int preen = 0; 64int rwflag = 1; 65int swapfs = 0; 66int normalize_swapfs = 0; 67int inode_buffer_blocks = 0; 68blk_t use_superblock; 69blk_t superblock; 70int blocksize = 0; 71int verbose = 0; 72int list = 0; 73int debug = 0; 74int force = 0; 75int invalid_bitmaps = 0; 76static int show_version_only = 0; 77 78static int replace_bad_blocks = 0; 79static char *bad_blocks_file = 0; 80 81static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0}; 82 83struct resource_track global_rtrack; 84 85static int root_filesystem = 0; 86static int read_only_root = 0; 87 88int *invalid_inode_bitmap; 89int *invalid_block_bitmap; 90int *invalid_inode_table; 91int restart_e2fsck = 0; 92 93static void usage(NOARGS) 94{ 95 fprintf(stderr, 96 "Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n" 97 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n" 98 "\t\t[-l|-L bad_blocks_file] device\n", program_name); 99 exit(FSCK_USAGE); 100} 101 102static void show_stats(ext2_filsys fs) 103{ 104 int inodes, inodes_used, blocks, blocks_used; 105 int dir_links; 106 int num_files, num_links; 107 int frag_percent; 108 109 dir_links = 2 * fs_directory_count - 1; 110 num_files = fs_total_count - dir_links; 111 num_links = fs_links_count - dir_links; 112 inodes = fs->super->s_inodes_count; 113 inodes_used = (fs->super->s_inodes_count - 114 fs->super->s_free_inodes_count); 115 blocks = fs->super->s_blocks_count; 116 blocks_used = (fs->super->s_blocks_count - 117 fs->super->s_free_blocks_count); 118 119 frag_percent = (10000 * fs_fragmented) / inodes_used; 120 frag_percent = (frag_percent + 5) / 10; 121 122 if (!verbose) { 123 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n", 124 device_name, inodes_used, inodes, 125 frag_percent / 10, frag_percent % 10, 126 blocks_used, blocks); 127 return; 128 } 129 printf ("\n%8d inode%s used (%d%%)\n", inodes_used, 130 (inodes_used != 1) ? "s" : "", 131 100 * inodes_used / inodes); 132 printf ("%8d non-contiguous inodes (%0d.%d%%)\n", 133 fs_fragmented, frag_percent / 10, frag_percent % 10); 134 printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n", 135 fs_ind_count, fs_dind_count, fs_tind_count); 136 printf ("%8d block%s used (%d%%)\n" 137 "%8d bad block%s\n", blocks_used, 138 (blocks_used != 1) ? "s" : "", 139 100 * blocks_used / blocks, fs_badblocks_count, 140 fs_badblocks_count != 1 ? "s" : ""); 141 printf ("\n%8d regular file%s\n" 142 "%8d director%s\n" 143 "%8d character device file%s\n" 144 "%8d block device file%s\n" 145 "%8d fifo%s\n" 146 "%8d link%s\n" 147 "%8d symbolic link%s (%d fast symbolic link%s)\n" 148 "%8d socket%s\n" 149 "--------\n" 150 "%8d file%s\n", 151 fs_regular_count, (fs_regular_count != 1) ? "s" : "", 152 fs_directory_count, (fs_directory_count != 1) ? "ies" : "y", 153 fs_chardev_count, (fs_chardev_count != 1) ? "s" : "", 154 fs_blockdev_count, (fs_blockdev_count != 1) ? "s" : "", 155 fs_fifo_count, (fs_fifo_count != 1) ? "s" : "", 156 fs_links_count - dir_links, 157 ((fs_links_count - dir_links) != 1) ? "s" : "", 158 fs_symlinks_count, (fs_symlinks_count != 1) ? "s" : "", 159 fs_fast_symlinks_count, (fs_fast_symlinks_count != 1) ? "s" : "", 160 fs_sockets_count, (fs_sockets_count != 1) ? "s" : "", 161 fs_total_count - dir_links, 162 ((fs_total_count - dir_links) != 1) ? "s" : ""); 163} 164 165static void check_mount(NOARGS) 166{ 167 errcode_t retval; 168 int mount_flags, cont, fd; 169 170 retval = ext2fs_check_if_mounted(filesystem_name, &mount_flags); 171 if (retval) { 172 com_err("ext2fs_check_if_mount", retval, 173 "while determining whether %s is mounted.", 174 filesystem_name); 175 return; 176 } 177 if (!(mount_flags & EXT2_MF_MOUNTED)) 178 return; 179 180#if (defined(__linux__) && defined(HAVE_MNTENT_H)) 181 /* 182 * If the root is mounted read-only, then /etc/mtab is 183 * probably not correct; so we won't issue a warning based on 184 * it. 185 */ 186 fd = open(MOUNTED, O_RDWR); 187 if (fd < 0) { 188 if (errno == EROFS) 189 return; 190 } else 191 close(fd); 192#endif 193 194 if (!rwflag) { 195 printf("Warning! %s is mounted.\n", device_name); 196 return; 197 } 198 199 printf ("%s is mounted. ", device_name); 200 if (isatty (0) && isatty (1)) 201 cont = ask_yn("Do you really want to continue", -1); 202 else 203 cont = 0; 204 if (!cont) { 205 printf ("check aborted.\n"); 206 exit (0); 207 } 208 return; 209} 210 211static void sync_disks(NOARGS) 212{ 213 sync(); 214 sync(); 215 sleep(1); 216 sync(); 217} 218 219#define MIN_CHECK 1 220#define MAX_CHECK 2 221 222static const char *corrupt_msg = 223"\nThe superblock could not be read or does not describe a correct ext2\n" 224"filesystem. If the device is valid and it really contains an ext2\n" 225"filesystem (and not swap or ufs or something else), then the superblock\n" 226"is corrupt, and you might try running e2fsck with an alternate superblock:\n" 227" e2fsck -b 8193 <device>\n\n"; 228 229static void check_super_value(const char *descr, unsigned long value, 230 int flags, unsigned long min, unsigned long max) 231{ 232 if (((flags & MIN_CHECK) && (value < min)) || 233 ((flags & MAX_CHECK) && (value > max))) { 234 printf("Corruption found in superblock. (%s = %lu).\n", 235 descr, value); 236 printf(corrupt_msg); 237 fatal_error(0); 238 } 239} 240 241static void relocate_hint(void) 242{ 243 static hint_issued = 0; 244 245 /* 246 * Only issue the hint once, and only if we're using the 247 * primary superblocks. 248 */ 249 if (hint_issued || superblock) 250 return; 251 252 printf("Note: if there is several inode or block bitmap blocks\n" 253 "which require relocation, or one part of the inode table\n" 254 "which must be moved, you may wish to try running e2fsck\n" 255 "the '-b 8193' option first. The problem may lie only with\n" 256 "the primary block group descriptor, and the backup block\n" 257 "group descriptor may be OK.\n\n"); 258 hint_issued = 1; 259} 260 261 262static void check_super_block(ext2_filsys fs) 263{ 264 blk_t first_block, last_block; 265 struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super; 266 blk_t blocks_per_group = fs->super->s_blocks_per_group; 267 int i; 268 blk_t should_be; 269 errcode_t retval; 270 struct problem_context pctx; 271 272 clear_problem_context(&pctx); 273 274 /* 275 * Verify the super block constants... 276 */ 277 check_super_value("inodes_count", s->s_inodes_count, 278 MIN_CHECK, 1, 0); 279 check_super_value("blocks_count", s->s_blocks_count, 280 MIN_CHECK, 1, 0); 281 check_super_value("first_data_block", s->s_first_data_block, 282 MAX_CHECK, 0, s->s_blocks_count); 283 check_super_value("log_frag_size", s->s_log_frag_size, 284 MAX_CHECK, 0, 2); 285 check_super_value("log_block_size", s->s_log_block_size, 286 MIN_CHECK | MAX_CHECK, s->s_log_frag_size, 287 2); 288 check_super_value("frags_per_group", s->s_frags_per_group, 289 MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s)); 290 check_super_value("blocks_per_group", s->s_blocks_per_group, 291 MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s)); 292 check_super_value("inodes_per_group", s->s_inodes_per_group, 293 MIN_CHECK, 1, 0); 294 check_super_value("r_blocks_count", s->s_r_blocks_count, 295 MAX_CHECK, 0, s->s_blocks_count); 296 297 retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s), 298 &should_be); 299 if (retval) { 300 com_err("ext2fs_get_device_size", retval, 301 "while trying to check physical size of filesystem"); 302 fatal_error(0); 303 } 304 if (should_be < s->s_blocks_count) { 305 printf("The filesystem size (according to the superblock) is %d blocks\n", s->s_blocks_count); 306 printf("The physical size of the device is %d blocks\n", 307 should_be); 308 printf("Either the superblock or the partition table is likely to be corrupt!\n"); 309 preenhalt(fs); 310 if (ask("Abort", 1)) 311 fatal_error(0); 312 } 313 314 if (s->s_log_block_size != s->s_log_frag_size) { 315 printf("Superblock block_size = %d, fragsize = %d.\n", 316 EXT2_BLOCK_SIZE(s), EXT2_FRAG_SIZE(s)); 317 printf("This version of e2fsck does not support fragment " 318 "sizes different\n" 319 "from the block size.\n"); 320 fatal_error(0); 321 } 322 323 should_be = s->s_frags_per_group / 324 (s->s_log_block_size - s->s_log_frag_size + 1); 325 if (s->s_blocks_per_group != should_be) { 326 printf("Superblock blocks_per_group = %u, should " 327 "have been %u\n", s->s_blocks_per_group, 328 should_be); 329 printf(corrupt_msg); 330 fatal_error(0); 331 } 332 333 should_be = (s->s_log_block_size == 0) ? 1 : 0; 334 if (s->s_first_data_block != should_be) { 335 printf("Superblock first_data_block = %u, should " 336 "have been %u\n", s->s_first_data_block, 337 should_be); 338 printf(corrupt_msg); 339 fatal_error(0); 340 } 341 342 /* 343 * Verify the group descriptors.... 344 */ 345 first_block = fs->super->s_first_data_block; 346 last_block = first_block + blocks_per_group; 347 348 for (i = 0; i < fs->group_desc_count; i++) { 349 pctx.group = i; 350 351 if (i == fs->group_desc_count - 1) 352 last_block = fs->super->s_blocks_count; 353 if ((fs->group_desc[i].bg_block_bitmap < first_block) || 354 (fs->group_desc[i].bg_block_bitmap >= last_block)) { 355 relocate_hint(); 356 pctx.blk = fs->group_desc[i].bg_block_bitmap; 357 if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) { 358 fs->group_desc[i].bg_block_bitmap = 0; 359 invalid_block_bitmap[i]++; 360 invalid_bitmaps++; 361 } 362 } 363 if ((fs->group_desc[i].bg_inode_bitmap < first_block) || 364 (fs->group_desc[i].bg_inode_bitmap >= last_block)) { 365 relocate_hint(); 366 pctx.blk = fs->group_desc[i].bg_inode_bitmap; 367 if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) { 368 fs->group_desc[i].bg_inode_bitmap = 0; 369 invalid_inode_bitmap[i]++; 370 invalid_bitmaps++; 371 } 372 } 373 if ((fs->group_desc[i].bg_inode_table < first_block) || 374 ((fs->group_desc[i].bg_inode_table + 375 fs->inode_blocks_per_group - 1) >= last_block)) { 376 relocate_hint(); 377 pctx.blk = fs->group_desc[i].bg_inode_table; 378 if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) { 379 fs->group_desc[i].bg_inode_table = 0; 380 invalid_inode_table[i]++; 381 invalid_bitmaps++; 382 } 383 } 384 first_block += fs->super->s_blocks_per_group; 385 last_block += fs->super->s_blocks_per_group; 386 } 387 /* 388 * If we have invalid bitmaps, set the error state of the 389 * filesystem. 390 */ 391 if (invalid_bitmaps && rwflag) { 392 fs->super->s_state &= ~EXT2_VALID_FS; 393 ext2fs_mark_super_dirty(fs); 394 } 395 396 /* 397 * If the UUID field isn't assigned, assign it. 398 */ 399 if (rwflag && uuid_is_null(s->s_uuid)) { 400 if (preen) 401 printf("%s: Adding UUID to filesystem.\n", 402 device_name); 403 else 404 printf("Filesystem did not have a UUID; " 405 "generating one.\n\n"); 406 uuid_generate(s->s_uuid); 407 ext2fs_mark_super_dirty(fs); 408 } 409 return; 410} 411 412/* 413 * This routine checks to see if a filesystem can be skipped; if so, 414 * it will exit with E2FSCK_OK. Under some conditions it will print a 415 * message explaining why a check is being forced. 416 */ 417static void check_if_skip(ext2_filsys fs) 418{ 419 const char *reason = NULL; 420 421 if (force || bad_blocks_file || cflag || swapfs) 422 return; 423 424 if (fs->super->s_state & EXT2_ERROR_FS) 425 reason = "contains a file system with errors"; 426 else if (fs->super->s_mnt_count >= 427 (unsigned) fs->super->s_max_mnt_count) 428 reason = "has reached maximal mount count"; 429 else if (fs->super->s_checkinterval && 430 time(0) >= (fs->super->s_lastcheck + 431 fs->super->s_checkinterval)) 432 reason = "has gone too long without being checked"; 433 else if ((fs->super->s_state & EXT2_VALID_FS) == 0) 434 reason = "was not cleanly unmounted"; 435 if (reason) { 436 printf("%s %s, check forced.\n", device_name, reason); 437 return; 438 } 439 printf("%s: clean, %d/%d files, %d/%d blocks\n", device_name, 440 fs->super->s_inodes_count - fs->super->s_free_inodes_count, 441 fs->super->s_inodes_count, 442 fs->super->s_blocks_count - fs->super->s_free_blocks_count, 443 fs->super->s_blocks_count); 444 ext2fs_close(fs); 445 exit(FSCK_OK); 446} 447 448#define PATH_SET "PATH=/sbin" 449 450static void PRS(int argc, char *argv[]) 451{ 452 int flush = 0; 453 char c; 454#ifdef MTRACE 455 extern void *mallwatch; 456#endif 457 char *oldpath = getenv("PATH"); 458 459 /* Update our PATH to include /sbin */ 460 if (oldpath) { 461 char *newpath; 462 463 newpath = malloc(sizeof (PATH_SET) + 1 + strlen (oldpath)); 464 if (!newpath) 465 fatal_error("Couldn't malloc() newpath"); 466 strcpy (newpath, PATH_SET); 467 strcat (newpath, ":"); 468 strcat (newpath, oldpath); 469 putenv (newpath); 470 } else 471 putenv (PATH_SET); 472 473 setbuf(stdout, NULL); 474 setbuf(stderr, NULL); 475 initialize_ext2_error_table(); 476 477 if (argc && *argv) 478 program_name = *argv; 479 while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF) 480 switch (c) { 481 case 'p': 482 case 'a': 483 preen = 1; 484 yflag = nflag = 0; 485 break; 486 case 'n': 487 nflag = 1; 488 preen = yflag = 0; 489 break; 490 case 'y': 491 yflag = 1; 492 preen = nflag = 0; 493 break; 494 case 't': 495 tflag++; 496 break; 497 case 'c': 498 cflag++; 499 break; 500 case 'r': 501 /* What we do by default, anyway! */ 502 break; 503 case 'b': 504 use_superblock = atoi(optarg); 505 break; 506 case 'B': 507 blocksize = atoi(optarg); 508 break; 509 case 'I': 510 inode_buffer_blocks = atoi(optarg); 511 break; 512 case 'P': 513 process_inode_size = atoi(optarg); 514 break; 515 case 'L': 516 replace_bad_blocks++; 517 case 'l': 518 bad_blocks_file = malloc(strlen(optarg)+1); 519 if (!bad_blocks_file) 520 fatal_error("Couldn't malloc bad_blocks_file"); 521 strcpy(bad_blocks_file, optarg); 522 break; 523 case 'd': 524 debug = 1; 525 break; 526 case 'f': 527 force = 1; 528 break; 529 case 'F': 530#ifdef BLKFLSBUF 531 flush = 1; 532#else 533 fatal_error ("-F not supported"); 534#endif 535 break; 536 case 'v': 537 verbose = 1; 538 break; 539 case 'V': 540 show_version_only = 1; 541 break; 542#ifdef MTRACE 543 case 'M': 544 mallwatch = (void *) strtol(optarg, NULL, 0); 545 break; 546#endif 547 case 'N': 548 device_name = optarg; 549 break; 550 case 's': 551 normalize_swapfs = 1; 552 case 'S': 553 swapfs = 1; 554 break; 555 default: 556 usage (); 557 } 558 if (show_version_only) 559 return; 560 if (optind != argc - 1) 561 usage (); 562 if (nflag && !bad_blocks_file && !cflag && !swapfs) 563 rwflag = 0; 564 filesystem_name = argv[optind]; 565 if (device_name == 0) 566 device_name = filesystem_name; 567 if (flush) { 568#ifdef BLKFLSBUF 569 int fd = open(filesystem_name, O_RDONLY, 0); 570 571 if (fd < 0) { 572 com_err("open", errno, "while opening %s for flushing", 573 filesystem_name); 574 exit(FSCK_ERROR); 575 } 576 if (ioctl(fd, BLKFLSBUF, 0) < 0) { 577 com_err("BLKFLSBUF", errno, "while trying to flush %s", 578 filesystem_name); 579 exit(FSCK_ERROR); 580 } 581 close(fd); 582#else 583 fatal_error ("BLKFLSBUF not supported"); 584#endif /* BLKFLSBUF */ 585 } 586 if (swapfs) { 587 if (cflag || bad_blocks_file) { 588 fprintf(stderr, "Incompatible options not " 589 "allowed when byte-swapping.\n"); 590 fatal_error(0); 591 } 592 } 593} 594 595int main (int argc, char *argv[]) 596{ 597 errcode_t retval = 0; 598 int exit_value = FSCK_OK; 599 int i; 600 ext2_filsys fs = 0; 601 io_manager io_ptr; 602 struct ext2fs_sb *s; 603 604#ifdef MTRACE 605 mtrace(); 606#endif 607#ifdef MCHECK 608 mcheck(0); 609#endif 610 611 init_resource_track(&global_rtrack); 612 613 PRS(argc, argv); 614 615 if (!preen || show_version_only) 616 fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n", 617 E2FSPROGS_VERSION, E2FSPROGS_DATE, 618 EXT2FS_VERSION, EXT2FS_DATE); 619 620 if (show_version_only) { 621 fprintf(stderr, "\tUsing %s\n", 622 error_message(EXT2_ET_BASE)); 623 exit(0); 624 } 625 626 check_mount(); 627 628 if (!preen && !nflag && !yflag) { 629 if (!isatty (0) || !isatty (1)) 630 die ("need terminal for interactive repairs"); 631 } 632 superblock = use_superblock; 633restart: 634#if 1 635 io_ptr = unix_io_manager; 636#else 637 io_ptr = test_io_manager; 638 test_io_backing_manager = unix_io_manager; 639#endif 640 sync_disks(); 641 if (superblock && blocksize) { 642 retval = ext2fs_open(filesystem_name, 643 rwflag ? EXT2_FLAG_RW : 0, 644 superblock, blocksize, io_ptr, &fs); 645 } else if (superblock) { 646 for (i=0; possible_block_sizes[i]; i++) { 647 retval = ext2fs_open(filesystem_name, 648 rwflag ? EXT2_FLAG_RW : 0, 649 superblock, 650 possible_block_sizes[i], 651 io_ptr, &fs); 652 if (!retval) 653 break; 654 } 655 } else 656 retval = ext2fs_open(filesystem_name, 657 rwflag ? EXT2_FLAG_RW : 0, 658 0, 0, io_ptr, &fs); 659 if (!superblock && !preen && 660 ((retval == EXT2_ET_BAD_MAGIC) || 661 ((retval == 0) && ext2fs_check_desc(fs)))) { 662 if (!fs || (fs->group_desc_count > 1)) { 663 printf("%s trying backup blocks...\n", 664 retval ? "Couldn't find ext2 superblock," : 665 "Group descriptors look bad..."); 666 superblock = 8193; 667 if (fs) 668 ext2fs_close(fs); 669 goto restart; 670 } 671 } 672 if (retval) { 673 com_err(program_name, retval, "while trying to open %s", 674 filesystem_name); 675 if (retval == EXT2_ET_REV_TOO_HIGH) 676 printf ("Get a newer version of e2fsck!\n"); 677 else if (retval == EXT2_ET_SHORT_READ) 678 printf ("Could this be a zero-length partition?\n"); 679 else if ((retval == EPERM) || (retval == EACCES)) 680 printf("You must have %s access to the " 681 "filesystem or be root\n", 682 rwflag ? "r/w" : "r/o"); 683 else if (retval == ENXIO) 684 printf("Possibly non-existent or swap device?\n"); 685 else 686 printf(corrupt_msg); 687 fatal_error(0); 688 } 689#ifdef EXT2_CURRENT_REV 690 if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) { 691 com_err(program_name, EXT2_ET_REV_TOO_HIGH, 692 "while trying to open %s", 693 filesystem_name); 694 goto get_newer; 695 } 696#endif 697 /* 698 * Check for compatibility with the feature sets. We have to 699 * check because we need to be more stringent than ext2fs_open 700 */ 701 s = (struct ext2fs_sb *) fs->super; 702 if (s->s_feature_compat || s->s_feature_incompat || 703 s->s_feature_ro_compat) { 704 com_err(program_name, EXT2_ET_UNSUPP_FEATURE, 705 " (%s)", filesystem_name); 706 get_newer: 707 printf ("Get a newer version of e2fsck!\n"); 708 fatal_error(0); 709 } 710 711 /* 712 * If the user specified a specific superblock, presumably the 713 * master superblock has been trashed. So we mark the 714 * superblock as dirty, so it can be written out. 715 */ 716 if (superblock && rwflag) 717 ext2fs_mark_super_dirty(fs); 718 719 /* 720 * Don't overwrite the backup superblock and block 721 * descriptors, until we're sure the filesystem is OK.... 722 */ 723 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 724 725 ehandler_init(fs->io); 726 727 invalid_inode_bitmap = allocate_memory(sizeof(int) * 728 fs->group_desc_count, 729 "invalid_inode_bitmap"); 730 invalid_block_bitmap = allocate_memory(sizeof(int) * 731 fs->group_desc_count, 732 "invalid_block_bitmap"); 733 invalid_inode_table = allocate_memory(sizeof(int) * 734 fs->group_desc_count, 735 "invalid_inode_table"); 736 737 check_super_block(fs); 738 check_if_skip(fs); 739 if (bad_blocks_file) 740 read_bad_blocks_file(fs, bad_blocks_file, replace_bad_blocks); 741 else if (cflag) 742 test_disk(fs); 743 744 if (normalize_swapfs) { 745 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == 746 ext2fs_native_flag()) { 747 fprintf(stderr, "%s: Filesystem byte order " 748 "already normalized.\n", device_name); 749 fatal_error(0); 750 } 751 } 752 if (swapfs) 753 swap_filesys(fs); 754 755 /* 756 * Mark the system as valid, 'til proven otherwise 757 */ 758 ext2fs_mark_valid(fs); 759 760 retval = ext2fs_read_bb_inode(fs, &fs->badblocks); 761 if (retval) { 762 com_err(program_name, retval, 763 "while reading bad blocks inode"); 764 preenhalt(fs); 765 printf("This doesn't bode well, but we'll try to go on...\n"); 766 } 767 768 pass1(fs); 769 free(invalid_inode_bitmap); 770 free(invalid_block_bitmap); 771 free(invalid_inode_table); 772 if (restart_e2fsck) { 773 ext2fs_close(fs); 774 printf("Restarting e2fsck from the beginning...\n"); 775 restart_e2fsck = 0; 776 superblock = use_superblock; 777 goto restart; 778 } 779 pass2(fs); 780 pass3(fs); 781 pass4(fs); 782 pass5(fs); 783 784#ifdef MTRACE 785 mtrace_print("Cleanup"); 786#endif 787 if (ext2fs_test_changed(fs)) { 788 exit_value = FSCK_NONDESTRUCT; 789 if (!preen) 790 printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n", 791 device_name); 792 if (root_filesystem && !read_only_root) { 793 printf("%s: ***** REBOOT LINUX *****\n", device_name); 794 exit_value = FSCK_REBOOT; 795 } 796 } 797 if (ext2fs_test_valid(fs)) 798 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 799 else 800 exit_value = FSCK_UNCORRECTED; 801 if (rwflag) { 802 if (ext2fs_test_valid(fs)) { 803 if (!(fs->super->s_state & EXT2_VALID_FS)) 804 exit_value = FSCK_NONDESTRUCT; 805 fs->super->s_state = EXT2_VALID_FS; 806 } else 807 fs->super->s_state &= ~EXT2_VALID_FS; 808 fs->super->s_mnt_count = 0; 809 fs->super->s_lastcheck = time(NULL); 810 ext2fs_mark_super_dirty(fs); 811 } 812 show_stats(fs); 813 814 write_bitmaps(fs); 815 ext2fs_close(fs); 816 sync_disks(); 817 818 if (tflag) 819 print_resource_track(&global_rtrack); 820 821 return exit_value; 822} 823