2 * e2fsck.c - a consistency checker for the new extended file system.
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Public
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
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 :-).
43 #include <sys/ioctl.h>
46 #include "et/com_err.h"
47 #include "uuid/uuid.h"
50 #include "../version.h"
52 extern int isatty(int);
54 const char * program_name
= "e2fsck";
55 const char * device_name
= NULL
;
56 const char * filesystem_name
= NULL
;
58 /* Command line options */
61 int tflag
= 0; /* Do timing */
62 int cflag
= 0; /* check disk */
66 int normalize_swapfs
= 0;
67 int inode_buffer_blocks
= 0;
75 int invalid_bitmaps
= 0;
76 static int show_version_only
= 0;
78 static int replace_bad_blocks
= 0;
79 static char *bad_blocks_file
= 0;
81 static int possible_block_sizes
[] = { 1024, 2048, 4096, 8192, 0};
83 struct resource_track global_rtrack
;
85 static int root_filesystem
= 0;
86 static int read_only_root
= 0;
88 int *invalid_inode_bitmap
;
89 int *invalid_block_bitmap
;
90 int *invalid_inode_table
;
91 int restart_e2fsck
= 0;
93 static void usage(NOARGS
)
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
);
102 static void show_stats(ext2_filsys fs
)
104 int inodes
, inodes_used
, blocks
, blocks_used
;
106 int num_files
, num_links
;
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
);
119 frag_percent
= (10000 * fs_fragmented
) / inodes_used
;
120 frag_percent
= (frag_percent
+ 5) / 10;
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
);
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"
143 "%8d character device file%s\n"
144 "%8d block device file%s\n"
147 "%8d symbolic link%s (%d fast symbolic link%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" : "");
165 static void check_mount(NOARGS
)
168 int mount_flags
, cont
, fd
;
170 retval
= ext2fs_check_if_mounted(filesystem_name
, &mount_flags
);
172 com_err("ext2fs_check_if_mount", retval
,
173 "while determining whether %s is mounted.",
177 if (!(mount_flags
& EXT2_MF_MOUNTED
))
180 #if (defined(__linux__) && defined(HAVE_MNTENT_H))
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
186 fd
= open(MOUNTED
, O_RDWR
);
195 printf("Warning! %s is mounted.\n", device_name
);
199 printf("%s is mounted.\n\n", device_name
);
200 printf("\a\a\a\aWARNING!!! Running e2fsck on a mounted filesystem "
201 "may cause\nSEVERE filesystem damage.\a\a\a\n\n");
202 if (isatty (0) && isatty (1))
203 cont
= ask_yn("Do you really want to continue", -1);
207 printf ("check aborted.\n");
213 static void sync_disks(NOARGS
)
221 static blk_t
get_backup_sb(ext2_filsys fs
)
223 if (!fs
|| !fs
->super
)
225 return fs
->super
->s_blocks_per_group
+ 1;
231 static const char *corrupt_msg
=
232 "\nThe superblock could not be read or does not describe a correct ext2\n"
233 "filesystem. If the device is valid and it really contains an ext2\n"
234 "filesystem (and not swap or ufs or something else), then the superblock\n"
235 "is corrupt, and you might try running e2fsck with an alternate superblock:\n"
236 " e2fsck -b %d <device>\n\n";
238 static void check_super_value(ext2_filsys fs
, const char *descr
,
239 unsigned long value
, int flags
,
240 unsigned long min
, unsigned long max
)
242 if (((flags
& MIN_CHECK
) && (value
< min
)) ||
243 ((flags
& MAX_CHECK
) && (value
> max
))) {
244 printf("Corruption found in superblock. (%s = %lu).\n",
246 printf(corrupt_msg
, get_backup_sb(fs
));
251 static void relocate_hint(ext2_filsys fs
)
253 static hint_issued
= 0;
256 * Only issue the hint once, and only if we're using the
257 * primary superblocks.
259 if (hint_issued
|| superblock
)
262 printf("Note: if there is several inode or block bitmap blocks\n"
263 "which require relocation, or one part of the inode table\n"
264 "which must be moved, you may wish to try running e2fsck\n"
265 "with the '-b %d' option first. The problem may lie only\n"
266 "with the primary block group descriptor, and the backup\n"
267 "block group descriptor may be OK.\n\n", get_backup_sb(fs
));
272 static void check_super_block(ext2_filsys fs
)
274 blk_t first_block
, last_block
;
275 struct ext2fs_sb
*s
= (struct ext2fs_sb
*) fs
->super
;
276 blk_t blocks_per_group
= fs
->super
->s_blocks_per_group
;
280 struct problem_context pctx
;
282 clear_problem_context(&pctx
);
285 * Verify the super block constants...
287 check_super_value(fs
, "inodes_count", s
->s_inodes_count
,
289 check_super_value(fs
, "blocks_count", s
->s_blocks_count
,
291 check_super_value(fs
, "first_data_block", s
->s_first_data_block
,
292 MAX_CHECK
, 0, s
->s_blocks_count
);
293 check_super_value(fs
, "log_frag_size", s
->s_log_frag_size
,
295 check_super_value(fs
, "log_block_size", s
->s_log_block_size
,
296 MIN_CHECK
| MAX_CHECK
, s
->s_log_frag_size
,
298 check_super_value(fs
, "frags_per_group", s
->s_frags_per_group
,
299 MIN_CHECK
| MAX_CHECK
, 1, 8 * EXT2_BLOCK_SIZE(s
));
300 check_super_value(fs
, "blocks_per_group", s
->s_blocks_per_group
,
301 MIN_CHECK
| MAX_CHECK
, 1, 8 * EXT2_BLOCK_SIZE(s
));
302 check_super_value(fs
, "inodes_per_group", s
->s_inodes_per_group
,
304 check_super_value(fs
, "r_blocks_count", s
->s_r_blocks_count
,
305 MAX_CHECK
, 0, s
->s_blocks_count
);
307 retval
= ext2fs_get_device_size(filesystem_name
, EXT2_BLOCK_SIZE(s
),
310 com_err("ext2fs_get_device_size", retval
,
311 "while trying to check physical size of filesystem");
314 if (should_be
< s
->s_blocks_count
) {
315 printf("The filesystem size (according to the superblock) is %d blocks\n", s
->s_blocks_count
);
316 printf("The physical size of the device is %d blocks\n",
318 printf("Either the superblock or the partition table is likely to be corrupt!\n");
324 if (s
->s_log_block_size
!= s
->s_log_frag_size
) {
325 printf("Superblock block_size = %d, fragsize = %d.\n",
326 EXT2_BLOCK_SIZE(s
), EXT2_FRAG_SIZE(s
));
327 printf("This version of e2fsck does not support fragment "
329 "from the block size.\n");
333 should_be
= s
->s_frags_per_group
/
334 (s
->s_log_block_size
- s
->s_log_frag_size
+ 1);
335 if (s
->s_blocks_per_group
!= should_be
) {
336 printf("Superblock blocks_per_group = %u, should "
337 "have been %u\n", s
->s_blocks_per_group
,
339 printf(corrupt_msg
, get_backup_sb(fs
));
343 should_be
= (s
->s_log_block_size
== 0) ? 1 : 0;
344 if (s
->s_first_data_block
!= should_be
) {
345 printf("Superblock first_data_block = %u, should "
346 "have been %u\n", s
->s_first_data_block
,
348 printf(corrupt_msg
, get_backup_sb(fs
));
353 * Verify the group descriptors....
355 first_block
= fs
->super
->s_first_data_block
;
356 last_block
= first_block
+ blocks_per_group
;
358 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
361 if (i
== fs
->group_desc_count
- 1)
362 last_block
= fs
->super
->s_blocks_count
;
363 if ((fs
->group_desc
[i
].bg_block_bitmap
< first_block
) ||
364 (fs
->group_desc
[i
].bg_block_bitmap
>= last_block
)) {
366 pctx
.blk
= fs
->group_desc
[i
].bg_block_bitmap
;
367 if (fix_problem(fs
, PR_0_BB_NOT_GROUP
, &pctx
)) {
368 fs
->group_desc
[i
].bg_block_bitmap
= 0;
369 invalid_block_bitmap
[i
]++;
373 if ((fs
->group_desc
[i
].bg_inode_bitmap
< first_block
) ||
374 (fs
->group_desc
[i
].bg_inode_bitmap
>= last_block
)) {
376 pctx
.blk
= fs
->group_desc
[i
].bg_inode_bitmap
;
377 if (fix_problem(fs
, PR_0_IB_NOT_GROUP
, &pctx
)) {
378 fs
->group_desc
[i
].bg_inode_bitmap
= 0;
379 invalid_inode_bitmap
[i
]++;
383 if ((fs
->group_desc
[i
].bg_inode_table
< first_block
) ||
384 ((fs
->group_desc
[i
].bg_inode_table
+
385 fs
->inode_blocks_per_group
- 1) >= last_block
)) {
387 pctx
.blk
= fs
->group_desc
[i
].bg_inode_table
;
388 if (fix_problem(fs
, PR_0_ITABLE_NOT_GROUP
, &pctx
)) {
389 fs
->group_desc
[i
].bg_inode_table
= 0;
390 invalid_inode_table
[i
]++;
394 first_block
+= fs
->super
->s_blocks_per_group
;
395 last_block
+= fs
->super
->s_blocks_per_group
;
398 * If we have invalid bitmaps, set the error state of the
401 if (invalid_bitmaps
&& rwflag
) {
402 fs
->super
->s_state
&= ~EXT2_VALID_FS
;
403 ext2fs_mark_super_dirty(fs
);
407 * If the UUID field isn't assigned, assign it.
409 if (rwflag
&& uuid_is_null(s
->s_uuid
)) {
411 printf("%s: Adding UUID to filesystem.\n",
414 printf("Filesystem did not have a UUID; "
415 "generating one.\n\n");
416 uuid_generate(s
->s_uuid
);
417 ext2fs_mark_super_dirty(fs
);
423 * This routine checks to see if a filesystem can be skipped; if so,
424 * it will exit with E2FSCK_OK. Under some conditions it will print a
425 * message explaining why a check is being forced.
427 static void check_if_skip(ext2_filsys fs
)
429 const char *reason
= NULL
;
431 if (force
|| bad_blocks_file
|| cflag
|| swapfs
)
434 if (fs
->super
->s_state
& EXT2_ERROR_FS
)
435 reason
= "contains a file system with errors";
436 else if (fs
->super
->s_mnt_count
>=
437 (unsigned) fs
->super
->s_max_mnt_count
)
438 reason
= "has reached maximal mount count";
439 else if (fs
->super
->s_checkinterval
&&
440 time(0) >= (fs
->super
->s_lastcheck
+
441 fs
->super
->s_checkinterval
))
442 reason
= "has gone too long without being checked";
443 else if ((fs
->super
->s_state
& EXT2_VALID_FS
) == 0)
444 reason
= "was not cleanly unmounted";
446 printf("%s %s, check forced.\n", device_name
, reason
);
449 printf("%s: clean, %d/%d files, %d/%d blocks\n", device_name
,
450 fs
->super
->s_inodes_count
- fs
->super
->s_free_inodes_count
,
451 fs
->super
->s_inodes_count
,
452 fs
->super
->s_blocks_count
- fs
->super
->s_free_blocks_count
,
453 fs
->super
->s_blocks_count
);
458 #define PATH_SET "PATH=/sbin"
460 static void PRS(int argc
, char *argv
[])
465 extern void *mallwatch
;
467 char *oldpath
= getenv("PATH");
469 /* Update our PATH to include /sbin */
473 newpath
= malloc(sizeof (PATH_SET
) + 1 + strlen (oldpath
));
475 fatal_error("Couldn't malloc() newpath");
476 strcpy (newpath
, PATH_SET
);
477 strcat (newpath
, ":");
478 strcat (newpath
, oldpath
);
483 setbuf(stdout
, NULL
);
484 setbuf(stderr
, NULL
);
485 initialize_ext2_error_table();
488 program_name
= *argv
;
489 while ((c
= getopt (argc
, argv
, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF
)
511 /* What we do by default, anyway! */
514 use_superblock
= atoi(optarg
);
517 blocksize
= atoi(optarg
);
520 inode_buffer_blocks
= atoi(optarg
);
523 process_inode_size
= atoi(optarg
);
526 replace_bad_blocks
++;
528 bad_blocks_file
= malloc(strlen(optarg
)+1);
529 if (!bad_blocks_file
)
530 fatal_error("Couldn't malloc bad_blocks_file");
531 strcpy(bad_blocks_file
, optarg
);
543 fatal_error ("-F not supported");
550 show_version_only
= 1;
554 mallwatch
= (void *) strtol(optarg
, NULL
, 0);
558 device_name
= optarg
;
561 normalize_swapfs
= 1;
568 if (show_version_only
)
570 if (optind
!= argc
- 1)
572 if (nflag
&& !bad_blocks_file
&& !cflag
&& !swapfs
)
574 filesystem_name
= argv
[optind
];
575 if (device_name
== 0)
576 device_name
= filesystem_name
;
579 int fd
= open(filesystem_name
, O_RDONLY
, 0);
582 com_err("open", errno
, "while opening %s for flushing",
586 if (ioctl(fd
, BLKFLSBUF
, 0) < 0) {
587 com_err("BLKFLSBUF", errno
, "while trying to flush %s",
593 fatal_error ("BLKFLSBUF not supported");
594 #endif /* BLKFLSBUF */
597 if (cflag
|| bad_blocks_file
) {
598 fprintf(stderr
, "Incompatible options not "
599 "allowed when byte-swapping.\n");
605 static const char *my_ver_string
= E2FSPROGS_VERSION
;
606 static const char *my_ver_date
= E2FSPROGS_DATE
;
608 int main (int argc
, char *argv
[])
610 errcode_t retval
= 0;
611 int exit_value
= FSCK_OK
;
616 const char *lib_ver_date
;
625 my_ver
= ext2fs_parse_version_string(my_ver_string
);
626 lib_ver
= ext2fs_get_library_version(0, &lib_ver_date
);
627 if (my_ver
> lib_ver
) {
628 fprintf( stderr
, "Error: ext2fs library version "
633 init_resource_track(&global_rtrack
);
637 if (!preen
|| show_version_only
)
638 fprintf (stderr
, "e2fsck %s, %s for EXT2 FS %s, %s\n",
639 my_ver_string
, my_ver_date
, EXT2FS_VERSION
,
642 if (show_version_only
) {
643 fprintf(stderr
, "\tUsing %s, %s\n",
644 error_message(EXT2_ET_BASE
), lib_ver_date
);
650 if (!preen
&& !nflag
&& !yflag
) {
651 if (!isatty (0) || !isatty (1))
652 die ("need terminal for interactive repairs");
654 superblock
= use_superblock
;
657 io_ptr
= unix_io_manager
;
659 io_ptr
= test_io_manager
;
660 test_io_backing_manager
= unix_io_manager
;
663 if (superblock
&& blocksize
) {
664 retval
= ext2fs_open(filesystem_name
,
665 rwflag
? EXT2_FLAG_RW
: 0,
666 superblock
, blocksize
, io_ptr
, &fs
);
667 } else if (superblock
) {
668 for (i
=0; possible_block_sizes
[i
]; i
++) {
669 retval
= ext2fs_open(filesystem_name
,
670 rwflag
? EXT2_FLAG_RW
: 0,
672 possible_block_sizes
[i
],
678 retval
= ext2fs_open(filesystem_name
,
679 rwflag
? EXT2_FLAG_RW
: 0,
681 if (!superblock
&& !preen
&&
682 ((retval
== EXT2_ET_BAD_MAGIC
) ||
683 ((retval
== 0) && ext2fs_check_desc(fs
)))) {
684 if (!fs
|| (fs
->group_desc_count
> 1)) {
685 printf("%s trying backup blocks...\n",
686 retval
? "Couldn't find ext2 superblock," :
687 "Group descriptors look bad...");
688 superblock
= get_backup_sb(fs
);
695 com_err(program_name
, retval
, "while trying to open %s",
697 if (retval
== EXT2_ET_REV_TOO_HIGH
)
698 printf ("Get a newer version of e2fsck!\n");
699 else if (retval
== EXT2_ET_SHORT_READ
)
700 printf ("Could this be a zero-length partition?\n");
701 else if ((retval
== EPERM
) || (retval
== EACCES
))
702 printf("You must have %s access to the "
703 "filesystem or be root\n",
704 rwflag
? "r/w" : "r/o");
705 else if (retval
== ENXIO
)
706 printf("Possibly non-existent or swap device?\n");
708 printf(corrupt_msg
, get_backup_sb(fs
));
711 #ifdef EXT2_CURRENT_REV
712 if (fs
->super
->s_rev_level
> E2FSCK_CURRENT_REV
) {
713 com_err(program_name
, EXT2_ET_REV_TOO_HIGH
,
714 "while trying to open %s",
720 * Check for compatibility with the feature sets. We need to
721 * be more stringent than ext2fs_open().
723 s
= (struct ext2fs_sb
*) fs
->super
;
724 if ((s
->s_feature_compat
& ~EXT2_LIB_FEATURE_COMPAT_SUPP
) ||
725 (s
->s_feature_incompat
& ~EXT2_LIB_FEATURE_INCOMPAT_SUPP
)) {
726 com_err(program_name
, EXT2_ET_UNSUPP_FEATURE
,
727 "(%s)", filesystem_name
);
729 printf ("Get a newer version of e2fsck!\n");
732 if (s
->s_feature_ro_compat
& ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP
) {
733 com_err(program_name
, EXT2_ET_RO_UNSUPP_FEATURE
,
734 "(%s)", filesystem_name
);
739 * If the user specified a specific superblock, presumably the
740 * master superblock has been trashed. So we mark the
741 * superblock as dirty, so it can be written out.
743 if (superblock
&& rwflag
)
744 ext2fs_mark_super_dirty(fs
);
747 * Don't overwrite the backup superblock and block
748 * descriptors, until we're sure the filesystem is OK....
750 fs
->flags
|= EXT2_FLAG_MASTER_SB_ONLY
;
752 ehandler_init(fs
->io
);
754 invalid_inode_bitmap
= allocate_memory(sizeof(int) *
755 fs
->group_desc_count
,
756 "invalid_inode_bitmap");
757 invalid_block_bitmap
= allocate_memory(sizeof(int) *
758 fs
->group_desc_count
,
759 "invalid_block_bitmap");
760 invalid_inode_table
= allocate_memory(sizeof(int) *
761 fs
->group_desc_count
,
762 "invalid_inode_table");
764 check_super_block(fs
);
767 read_bad_blocks_file(fs
, bad_blocks_file
, replace_bad_blocks
);
771 if (normalize_swapfs
) {
772 if ((fs
->flags
& EXT2_FLAG_SWAP_BYTES
) ==
773 ext2fs_native_flag()) {
774 fprintf(stderr
, "%s: Filesystem byte order "
775 "already normalized.\n", device_name
);
783 * Mark the system as valid, 'til proven otherwise
785 ext2fs_mark_valid(fs
);
787 retval
= ext2fs_read_bb_inode(fs
, &fs
->badblocks
);
789 com_err(program_name
, retval
,
790 "while reading bad blocks inode");
792 printf("This doesn't bode well, but we'll try to go on...\n");
796 free(invalid_inode_bitmap
);
797 free(invalid_block_bitmap
);
798 free(invalid_inode_table
);
799 if (restart_e2fsck
) {
801 printf("Restarting e2fsck from the beginning...\n");
803 superblock
= use_superblock
;
812 mtrace_print("Cleanup");
814 if (ext2fs_test_changed(fs
)) {
815 exit_value
= FSCK_NONDESTRUCT
;
817 printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
819 if (root_filesystem
&& !read_only_root
) {
820 printf("%s: ***** REBOOT LINUX *****\n", device_name
);
821 exit_value
= FSCK_REBOOT
;
824 if (ext2fs_test_valid(fs
))
825 fs
->flags
&= ~EXT2_FLAG_MASTER_SB_ONLY
;
827 exit_value
= FSCK_UNCORRECTED
;
829 if (ext2fs_test_valid(fs
)) {
830 if (!(fs
->super
->s_state
& EXT2_VALID_FS
))
831 exit_value
= FSCK_NONDESTRUCT
;
832 fs
->super
->s_state
= EXT2_VALID_FS
;
834 fs
->super
->s_state
&= ~EXT2_VALID_FS
;
835 fs
->super
->s_mnt_count
= 0;
836 fs
->super
->s_lastcheck
= time(NULL
);
837 ext2fs_mark_super_dirty(fs
);
846 print_resource_track(&global_rtrack
);