Many files:

pass*.c, super.c: Massive changes to avoid using printf and com_err
  	routines.  All diagnostic messages are now routed through the
  	fix_problem interface.
  pass2.c (check_dir_block): Check for duplicate '.' and '..' entries.
  problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
  	PR_2_DUP_DOT_DOT.
  problem.c: Added new problem codes for some of the superblock
  	corruption checks, and for the pass header messages.  ("Pass
  	1: xxxxx")
  util.c (print_resource_track): Now takes a description argument.
  super.c, unix.c, e2fsck.c: New files to separate out the
  	operating-specific operations out from e2fsck.c.  e2fsck.c now
  	contains the global e2fsck context management routines, and
  	super.c contains the "pass 0" initial validation of the
  	superblock and global block group descriptors.
  pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
  	(nearly) all global variables and moved them to the e2fsck
  	context structure.
  problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
  	PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS, PR_0_BLOCKS_PER_GROUP,
  	PR_0_FIRST_DATA_BLOCK
expect.1, expect.2:
  Updated tests to align with e2fsck problem.c changes.
bitmap-optimize
Theodore Ts'o 1997-10-03 17:48:10 +00:00
parent d163b09487
commit 1b6bf1759a
49 changed files with 3518 additions and 2220 deletions

View File

@ -1,3 +1,43 @@
Fri Oct 3 13:40:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass*.c, super.c: Massive changes to avoid using printf and
com_err routines. All diagnostic messages are now routed
through the fix_problem interface.
Sat Sep 6 17:13:28 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass2.c (check_dir_block): Check for duplicate '.' and '..'
entries.
* problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
PR_2_DUP_DOT_DOT.
Tue Sep 2 09:04:51 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* problem.c: Added new problem codes for some of the
superblock corruption checks, and for the pass header
messages. ("Pass 1: xxxxx")
* util.c (print_resource_track): Now takes a description
argument.
Mon Aug 25 10:23:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* super.c, unix.c, e2fsck.c: New files to separate out the
operating-specific operations out from e2fsck.c.
e2fsck.c now contains the global e2fsck context management
routines, and super.c contains the "pass 0" initial
validation of the superblock and global block group
descriptors.
* pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
(nearly) all global variables and moved them to the e2fsck
context structure.
* problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS,
PR_0_BLOCKS_PER_GROUP, PR_0_FIRST_DATA_BLOCK
Thu Aug 14 10:55:21 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* message.c: Add compression for the word "Illegal"

View File

@ -52,17 +52,19 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUI
#
#MCHECK= -DMCHECK
OBJS= e2fsck.o pass1.o pass1b.o pass2.o pass3.o pass4.o pass5.o \
swapfs.o badblocks.o util.o dirinfo.o ehandler.o problem.o message.o \
$(MTRACE_OBJ)
OBJS= unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o pass3.o pass4.o \
pass5.o swapfs.o badblocks.o util.o dirinfo.o ehandler.o \
problem.o message.o $(MTRACE_OBJ)
PROFILED_OBJS= profiled/e2fsck.o profiled/pass1.o profiled/pass1b.o \
PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o profiled/super.o \
profiled/pass1.o profiled/pass1b.o \
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
profiled/badblocks.o profiled/util.o profiled/dirinfo.o \
profiled/ehandler.o profiled/message.o profiled/problem.o \
profiled/swapfs.o
SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/super.c \
$(srcdir)/pass1.c \
$(srcdir)/pass1b.c \
$(srcdir)/pass2.c \
@ -71,6 +73,7 @@ SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/pass5.c \
$(srcdir)/badblocks.c \
$(srcdir)/util.c \
$(srcdir)/unix.c \
$(srcdir)/dirinfo.c \
$(srcdir)/ehandler.c \
$(srcdir)/problem.c \

View File

@ -23,15 +23,16 @@ static void invalid_block(ext2_filsys fs, blk_t blk)
return;
}
void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
int replace_bad_blocks)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
badblocks_list bb_list = 0;
FILE *f;
char buf[1024];
read_bitmaps(fs);
read_bitmaps(ctx);
/*
* Make sure the bad block inode is sane. If there are any
@ -72,8 +73,8 @@ void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
}
} else {
sprintf(buf, "badblocks -b %d %s%s %d", fs->blocksize,
preen ? "" : "-s ", fs->device_name,
fs->super->s_blocks_count);
(ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
fs->device_name, fs->super->s_blocks_count);
f = popen(buf, "r");
if (!f) {
com_err("read_bad_blocks_file", errno,
@ -106,9 +107,9 @@ void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
return;
}
void test_disk(ext2_filsys fs)
void test_disk(e2fsck_t ctx)
{
read_bad_blocks_file(fs, 0, 1);
read_bad_blocks_file(ctx, 0, 1);
}
static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,

View File

@ -9,841 +9,117 @@
* %End-Header%
*/
/* Usage: e2fsck [-dfpnsvy] device
* -d -- debugging this program
* -f -- check the fs even if it is marked valid
* -p -- "preen" the filesystem
* -n -- open the filesystem r/o mode; never try to fix problems
* -v -- verbose (tells how many files)
* -y -- always answer yes to questions
*
* The device may be a block device or a image of one, but this isn't
* enforced (but it's not much fun on a character device :-).
*/
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <time.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <unistd.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <sys/ioctl.h>
#include <malloc.h>
#include "et/com_err.h"
#include "uuid/uuid.h"
#include "e2fsck.h"
#include "problem.h"
#include "../version.h"
extern int isatty(int);
const char * program_name = "e2fsck";
const char * device_name = NULL;
const char * filesystem_name = NULL;
/* Command line options */
int nflag = 0;
int yflag = 0;
int tflag = 0; /* Do timing */
int cflag = 0; /* check disk */
int preen = 0;
int rwflag = 1;
int swapfs = 0;
int normalize_swapfs = 0;
int inode_buffer_blocks = 0;
blk_t use_superblock;
blk_t superblock;
int blocksize = 0;
int verbose = 0;
int list = 0;
int debug = 0;
int force = 0;
int invalid_bitmaps = 0;
static int show_version_only = 0;
static int replace_bad_blocks = 0;
static char *bad_blocks_file = 0;
static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0};
struct resource_track global_rtrack;
static int root_filesystem = 0;
static int read_only_root = 0;
int *invalid_inode_bitmap;
int *invalid_block_bitmap;
int *invalid_inode_table;
int restart_e2fsck = 0;
static void usage(NOARGS)
/*
* This function allocates an e2fsck context
*/
errcode_t e2fsck_allocate_context(e2fsck_t *ret)
{
fprintf(stderr,
"Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n"
"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
"\t\t[-l|-L bad_blocks_file] device\n", program_name);
exit(FSCK_USAGE);
}
e2fsck_t context;
static void show_stats(ext2_filsys fs)
{
int inodes, inodes_used, blocks, blocks_used;
int dir_links;
int num_files, num_links;
int frag_percent;
context = malloc(sizeof(struct e2fsck_struct));
if (!context)
return ENOMEM;
dir_links = 2 * fs_directory_count - 1;
num_files = fs_total_count - dir_links;
num_links = fs_links_count - dir_links;
inodes = fs->super->s_inodes_count;
inodes_used = (fs->super->s_inodes_count -
fs->super->s_free_inodes_count);
blocks = fs->super->s_blocks_count;
blocks_used = (fs->super->s_blocks_count -
fs->super->s_free_blocks_count);
memset(context, 0, sizeof(struct e2fsck_struct));
frag_percent = (10000 * fs_fragmented) / inodes_used;
frag_percent = (frag_percent + 5) / 10;
if (!verbose) {
printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
device_name, inodes_used, inodes,
frag_percent / 10, frag_percent % 10,
blocks_used, blocks);
return;
}
printf ("\n%8d inode%s used (%d%%)\n", inodes_used,
(inodes_used != 1) ? "s" : "",
100 * inodes_used / inodes);
printf ("%8d non-contiguous inodes (%0d.%d%%)\n",
fs_fragmented, frag_percent / 10, frag_percent % 10);
printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n",
fs_ind_count, fs_dind_count, fs_tind_count);
printf ("%8d block%s used (%d%%)\n"
"%8d bad block%s\n", blocks_used,
(blocks_used != 1) ? "s" : "",
100 * blocks_used / blocks, fs_badblocks_count,
fs_badblocks_count != 1 ? "s" : "");
printf ("\n%8d regular file%s\n"
"%8d director%s\n"
"%8d character device file%s\n"
"%8d block device file%s\n"
"%8d fifo%s\n"
"%8d link%s\n"
"%8d symbolic link%s (%d fast symbolic link%s)\n"
"%8d socket%s\n"
"--------\n"
"%8d file%s\n",
fs_regular_count, (fs_regular_count != 1) ? "s" : "",
fs_directory_count, (fs_directory_count != 1) ? "ies" : "y",
fs_chardev_count, (fs_chardev_count != 1) ? "s" : "",
fs_blockdev_count, (fs_blockdev_count != 1) ? "s" : "",
fs_fifo_count, (fs_fifo_count != 1) ? "s" : "",
fs_links_count - dir_links,
((fs_links_count - dir_links) != 1) ? "s" : "",
fs_symlinks_count, (fs_symlinks_count != 1) ? "s" : "",
fs_fast_symlinks_count, (fs_fast_symlinks_count != 1) ? "s" : "",
fs_sockets_count, (fs_sockets_count != 1) ? "s" : "",
fs_total_count - dir_links,
((fs_total_count - dir_links) != 1) ? "s" : "");
}
context->process_inode_size = 256;
static void check_mount(NOARGS)
{
errcode_t retval;
int mount_flags, cont, fd;
retval = ext2fs_check_if_mounted(filesystem_name, &mount_flags);
if (retval) {
com_err("ext2fs_check_if_mount", retval,
"while determining whether %s is mounted.",
filesystem_name);
return;
}
if (!(mount_flags & EXT2_MF_MOUNTED))
return;
#if (defined(__linux__) && defined(HAVE_MNTENT_H))
/*
* If the root is mounted read-only, then /etc/mtab is
* probably not correct; so we won't issue a warning based on
* it.
*/
fd = open(MOUNTED, O_RDWR);
if (fd < 0) {
if (errno == EROFS)
return;
} else
close(fd);
#endif
if (!rwflag) {
printf("Warning! %s is mounted.\n", device_name);
return;
}
printf("%s is mounted.\n\n", device_name);
printf("\a\a\a\aWARNING!!! Running e2fsck on a mounted filesystem "
"may cause\nSEVERE filesystem damage.\a\a\a\n\n");
if (isatty (0) && isatty (1))
cont = ask_yn("Do you really want to continue", -1);
else
cont = 0;
if (!cont) {
printf ("check aborted.\n");
exit (0);
}
return;
}
static void sync_disks(NOARGS)
{
sync();
sync();
sleep(1);
sync();
}
static blk_t get_backup_sb(ext2_filsys fs)
{
if (!fs || !fs->super)
return 8193;
return fs->super->s_blocks_per_group + 1;
}
#define MIN_CHECK 1
#define MAX_CHECK 2
static const char *corrupt_msg =
"\nThe superblock could not be read or does not describe a correct ext2\n"
"filesystem. If the device is valid and it really contains an ext2\n"
"filesystem (and not swap or ufs or something else), then the superblock\n"
"is corrupt, and you might try running e2fsck with an alternate superblock:\n"
" e2fsck -b %d <device>\n\n";
static void check_super_value(ext2_filsys fs, const char *descr,
unsigned long value, int flags,
unsigned long min, unsigned long max)
{
if (((flags & MIN_CHECK) && (value < min)) ||
((flags & MAX_CHECK) && (value > max))) {
printf("Corruption found in superblock. (%s = %lu).\n",
descr, value);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
}
static void relocate_hint(ext2_filsys fs)
{
static hint_issued = 0;
/*
* Only issue the hint once, and only if we're using the
* primary superblocks.
*/
if (hint_issued || superblock)
return;
printf("Note: if there is several inode or block bitmap blocks\n"
"which require relocation, or one part of the inode table\n"
"which must be moved, you may wish to try running e2fsck\n"
"with the '-b %d' option first. The problem may lie only\n"
"with the primary block group descriptor, and the backup\n"
"block group descriptor may be OK.\n\n", get_backup_sb(fs));
hint_issued = 1;
}
static void check_super_block(ext2_filsys fs)
{
blk_t first_block, last_block;
struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super;
blk_t blocks_per_group = fs->super->s_blocks_per_group;
int i;
blk_t should_be;
errcode_t retval;
struct problem_context pctx;
clear_problem_context(&pctx);
/*
* Verify the super block constants...
*/
check_super_value(fs, "inodes_count", s->s_inodes_count,
MIN_CHECK, 1, 0);
check_super_value(fs, "blocks_count", s->s_blocks_count,
MIN_CHECK, 1, 0);
check_super_value(fs, "first_data_block", s->s_first_data_block,
MAX_CHECK, 0, s->s_blocks_count);
check_super_value(fs, "log_frag_size", s->s_log_frag_size,
MAX_CHECK, 0, 2);
check_super_value(fs, "log_block_size", s->s_log_block_size,
MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
2);
check_super_value(fs, "frags_per_group", s->s_frags_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value(fs, "blocks_per_group", s->s_blocks_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value(fs, "inodes_per_group", s->s_inodes_per_group,
MIN_CHECK, 1, 0);
check_super_value(fs, "r_blocks_count", s->s_r_blocks_count,
MAX_CHECK, 0, s->s_blocks_count);
retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s),
&should_be);
if (retval) {
com_err("ext2fs_get_device_size", retval,
"while trying to check physical size of filesystem");
fatal_error(0);
}
if (should_be < s->s_blocks_count) {
printf("The filesystem size (according to the superblock) is %d blocks\n", s->s_blocks_count);
printf("The physical size of the device is %d blocks\n",
should_be);
printf("Either the superblock or the partition table is likely to be corrupt!\n");
preenhalt(fs);
if (ask("Abort", 1))
fatal_error(0);
}
if (s->s_log_block_size != s->s_log_frag_size) {
printf("Superblock block_size = %d, fragsize = %d.\n",
EXT2_BLOCK_SIZE(s), EXT2_FRAG_SIZE(s));
printf("This version of e2fsck does not support fragment "
"sizes different\n"
"from the block size.\n");
fatal_error(0);
}
should_be = s->s_frags_per_group /
(s->s_log_block_size - s->s_log_frag_size + 1);
if (s->s_blocks_per_group != should_be) {
printf("Superblock blocks_per_group = %u, should "
"have been %u\n", s->s_blocks_per_group,
should_be);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
should_be = (s->s_log_block_size == 0) ? 1 : 0;
if (s->s_first_data_block != should_be) {
printf("Superblock first_data_block = %u, should "
"have been %u\n", s->s_first_data_block,
should_be);
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
/*
* Verify the group descriptors....
*/
first_block = fs->super->s_first_data_block;
last_block = first_block + blocks_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
pctx.group = i;
if (i == fs->group_desc_count - 1)
last_block = fs->super->s_blocks_count;
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
relocate_hint(fs);
pctx.blk = fs->group_desc[i].bg_block_bitmap;
if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_block_bitmap = 0;
invalid_block_bitmap[i]++;
invalid_bitmaps++;
}
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
relocate_hint(fs);
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_bitmap = 0;
invalid_inode_bitmap[i]++;
invalid_bitmaps++;
}
}
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
relocate_hint(fs);
pctx.blk = fs->group_desc[i].bg_inode_table;
if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_table = 0;
invalid_inode_table[i]++;
invalid_bitmaps++;
}
}
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
}
/*
* If we have invalid bitmaps, set the error state of the
* filesystem.
*/
if (invalid_bitmaps && rwflag) {
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
}
/*
* If the UUID field isn't assigned, assign it.
*/
if (rwflag && uuid_is_null(s->s_uuid)) {
if (preen)
printf("%s: Adding UUID to filesystem.\n",
device_name);
else
printf("Filesystem did not have a UUID; "
"generating one.\n\n");
uuid_generate(s->s_uuid);
ext2fs_mark_super_dirty(fs);
}
return;
*ret = context;
return 0;
}
/*
* This routine checks to see if a filesystem can be skipped; if so,
* it will exit with E2FSCK_OK. Under some conditions it will print a
* message explaining why a check is being forced.
* This function resets an e2fsck context; it is called when e2fsck
* needs to be restarted.
*/
static void check_if_skip(ext2_filsys fs)
errcode_t e2fsck_reset_context(e2fsck_t ctx)
{
const char *reason = NULL;
if (force || bad_blocks_file || cflag || swapfs)
return;
if (fs->super->s_state & EXT2_ERROR_FS)
reason = "contains a file system with errors";
else if (fs->super->s_mnt_count >=
(unsigned) fs->super->s_max_mnt_count)
reason = "has reached maximal mount count";
else if (fs->super->s_checkinterval &&
time(0) >= (fs->super->s_lastcheck +
fs->super->s_checkinterval))
reason = "has gone too long without being checked";
else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
reason = "was not cleanly unmounted";
if (reason) {
printf("%s %s, check forced.\n", device_name, reason);
return;
if (ctx->inode_used_map) {
ext2fs_free_inode_bitmap(ctx->inode_used_map);
ctx->inode_used_map = 0;
}
if (ctx->inode_dir_map) {
ext2fs_free_inode_bitmap(ctx->inode_dir_map);
ctx->inode_dir_map = 0;
}
if (ctx->block_found_map) {
ext2fs_free_block_bitmap(ctx->block_found_map);
ctx->block_found_map = 0;
}
if (ctx->inode_link_info) {
ext2fs_free_icount(ctx->inode_link_info);
ctx->inode_link_info = 0;
}
if (ctx->fs->dblist) {
ext2fs_free_dblist(ctx->fs->dblist);
ctx->fs->dblist = 0;
}
free_dir_info(ctx->fs);
if (ctx->block_dup_map) {
ext2fs_free_block_bitmap(ctx->block_dup_map);
ctx->block_dup_map = 0;
}
if (ctx->inode_bb_map) {
ext2fs_free_inode_bitmap(ctx->inode_bb_map);
ctx->inode_bb_map = 0;
}
if (ctx->inode_bad_map) {
ext2fs_free_inode_bitmap(ctx->inode_bad_map);
ctx->inode_bad_map = 0;
}
printf("%s: clean, %d/%d files, %d/%d blocks\n", device_name,
fs->super->s_inodes_count - fs->super->s_free_inodes_count,
fs->super->s_inodes_count,
fs->super->s_blocks_count - fs->super->s_free_blocks_count,
fs->super->s_blocks_count);
ext2fs_close(fs);
exit(FSCK_OK);
}
#define PATH_SET "PATH=/sbin"
/*
* Clear the array of invalid meta-data flags
*/
if (ctx->invalid_inode_bitmap_flag) {
free(ctx->invalid_inode_bitmap_flag);
ctx->invalid_inode_bitmap_flag = 0;
}
if (ctx->invalid_block_bitmap_flag) {
free(ctx->invalid_block_bitmap_flag);
ctx->invalid_block_bitmap_flag = 0;
}
if (ctx->invalid_inode_table_flag) {
free(ctx->invalid_inode_table_flag);
ctx->invalid_inode_table_flag = 0;
}
static void PRS(int argc, char *argv[])
{
int flush = 0;
char c;
#ifdef MTRACE
extern void *mallwatch;
#endif
char *oldpath = getenv("PATH");
/* Clear statistic counters */
ctx->fs_directory_count = 0;
ctx->fs_regular_count = 0;
ctx->fs_blockdev_count = 0;
ctx->fs_chardev_count = 0;
ctx->fs_links_count = 0;
ctx->fs_symlinks_count = 0;
ctx->fs_fast_symlinks_count = 0;
ctx->fs_fifo_count = 0;
ctx->fs_total_count = 0;
ctx->fs_badblocks_count = 0;
ctx->fs_sockets_count = 0;
ctx->fs_ind_count = 0;
ctx->fs_dind_count = 0;
ctx->fs_tind_count = 0;
ctx->fs_fragmented = 0;
/* Update our PATH to include /sbin */
if (oldpath) {
char *newpath;
newpath = malloc(sizeof (PATH_SET) + 1 + strlen (oldpath));
if (!newpath)
fatal_error("Couldn't malloc() newpath");
strcpy (newpath, PATH_SET);
strcat (newpath, ":");
strcat (newpath, oldpath);
putenv (newpath);
} else
putenv (PATH_SET);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
initialize_ext2_error_table();
/* Reset the superblock to the user's requested value */
ctx->superblock = ctx->use_superblock;
if (argc && *argv)
program_name = *argv;
while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF)
switch (c) {
case 'p':
case 'a':
preen = 1;
yflag = nflag = 0;
break;
case 'n':
nflag = 1;
preen = yflag = 0;
break;
case 'y':
yflag = 1;
preen = nflag = 0;
break;
case 't':
tflag++;
break;
case 'c':
cflag++;
break;
case 'r':
/* What we do by default, anyway! */
break;
case 'b':
use_superblock = atoi(optarg);
break;
case 'B':
blocksize = atoi(optarg);
break;
case 'I':
inode_buffer_blocks = atoi(optarg);
break;
case 'P':
process_inode_size = atoi(optarg);
break;
case 'L':
replace_bad_blocks++;
case 'l':
bad_blocks_file = malloc(strlen(optarg)+1);
if (!bad_blocks_file)
fatal_error("Couldn't malloc bad_blocks_file");
strcpy(bad_blocks_file, optarg);
break;
case 'd':
debug = 1;
break;
case 'f':
force = 1;
break;
case 'F':
#ifdef BLKFLSBUF
flush = 1;
#else
fatal_error ("-F not supported");
#endif
break;
case 'v':
verbose = 1;
break;
case 'V':
show_version_only = 1;
break;
#ifdef MTRACE
case 'M':
mallwatch = (void *) strtol(optarg, NULL, 0);
break;
#endif
case 'N':
device_name = optarg;
break;
case 's':
normalize_swapfs = 1;
case 'S':
swapfs = 1;
break;
default:
usage ();
}
if (show_version_only)
return;
if (optind != argc - 1)
usage ();
if (nflag && !bad_blocks_file && !cflag && !swapfs)
rwflag = 0;
filesystem_name = argv[optind];
if (device_name == 0)
device_name = filesystem_name;
if (flush) {
#ifdef BLKFLSBUF
int fd = open(filesystem_name, O_RDONLY, 0);
if (fd < 0) {
com_err("open", errno, "while opening %s for flushing",
filesystem_name);
exit(FSCK_ERROR);
}
if (ioctl(fd, BLKFLSBUF, 0) < 0) {
com_err("BLKFLSBUF", errno, "while trying to flush %s",
filesystem_name);
exit(FSCK_ERROR);
}
close(fd);
#else
fatal_error ("BLKFLSBUF not supported");
#endif /* BLKFLSBUF */
}
if (swapfs) {
if (cflag || bad_blocks_file) {
fprintf(stderr, "Incompatible options not "
"allowed when byte-swapping.\n");
fatal_error(0);
}
}
return 0;
}
static const char *my_ver_string = E2FSPROGS_VERSION;
static const char *my_ver_date = E2FSPROGS_DATE;
int main (int argc, char *argv[])
void e2fsck_free_context(e2fsck_t ctx)
{
errcode_t retval = 0;
int exit_value = FSCK_OK;
int i;
ext2_filsys fs = 0;
io_manager io_ptr;
struct ext2fs_sb *s;
const char *lib_ver_date;
int my_ver, lib_ver;
if (!ctx)
return;
#ifdef MTRACE
mtrace();
#endif
#ifdef MCHECK
mcheck(0);
#endif
my_ver = ext2fs_parse_version_string(my_ver_string);
lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
if (my_ver > lib_ver) {
fprintf( stderr, "Error: ext2fs library version "
"out of date!\n");
show_version_only++;
}
e2fsck_reset_context(ctx);
init_resource_track(&global_rtrack);
PRS(argc, argv);
if (!preen || show_version_only)
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
my_ver_string, my_ver_date, EXT2FS_VERSION,
EXT2FS_DATE);
if (show_version_only) {
fprintf(stderr, "\tUsing %s, %s\n",
error_message(EXT2_ET_BASE), lib_ver_date);
exit(0);
}
check_mount();
if (!preen && !nflag && !yflag) {
if (!isatty (0) || !isatty (1))
die ("need terminal for interactive repairs");
}
superblock = use_superblock;
restart:
#if 1
io_ptr = unix_io_manager;
#else
io_ptr = test_io_manager;
test_io_backing_manager = unix_io_manager;
#endif
sync_disks();
if (superblock && blocksize) {
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
superblock, blocksize, io_ptr, &fs);
} else if (superblock) {
for (i=0; possible_block_sizes[i]; i++) {
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
superblock,
possible_block_sizes[i],
io_ptr, &fs);
if (!retval)
break;
}
} else
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
0, 0, io_ptr, &fs);
if (!superblock && !preen &&
((retval == EXT2_ET_BAD_MAGIC) ||
((retval == 0) && ext2fs_check_desc(fs)))) {
if (!fs || (fs->group_desc_count > 1)) {
printf("%s trying backup blocks...\n",
retval ? "Couldn't find ext2 superblock," :
"Group descriptors look bad...");
superblock = get_backup_sb(fs);
if (fs)
ext2fs_close(fs);
goto restart;
}
}
if (retval) {
com_err(program_name, retval, "while trying to open %s",
filesystem_name);
if (retval == EXT2_ET_REV_TOO_HIGH)
printf ("Get a newer version of e2fsck!\n");
else if (retval == EXT2_ET_SHORT_READ)
printf ("Could this be a zero-length partition?\n");
else if ((retval == EPERM) || (retval == EACCES))
printf("You must have %s access to the "
"filesystem or be root\n",
rwflag ? "r/w" : "r/o");
else if (retval == ENXIO)
printf("Possibly non-existent or swap device?\n");
else
printf(corrupt_msg, get_backup_sb(fs));
fatal_error(0);
}
#ifdef EXT2_CURRENT_REV
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
com_err(program_name, EXT2_ET_REV_TOO_HIGH,
"while trying to open %s",
filesystem_name);
goto get_newer;
}
#endif
/*
* Check for compatibility with the feature sets. We need to
* be more stringent than ext2fs_open().
*/
s = (struct ext2fs_sb *) fs->super;
if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
(s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
"(%s)", filesystem_name);
get_newer:
printf ("Get a newer version of e2fsck!\n");
fatal_error(0);
}
if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
com_err(program_name, EXT2_ET_RO_UNSUPP_FEATURE,
"(%s)", filesystem_name);
goto get_newer;
}
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
* superblock as dirty, so it can be written out.
*/
if (superblock && rwflag)
ext2fs_mark_super_dirty(fs);
/*
* Don't overwrite the backup superblock and block
* descriptors, until we're sure the filesystem is OK....
*/
fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
ehandler_init(fs->io);
invalid_inode_bitmap = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_inode_bitmap");
invalid_block_bitmap = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_block_bitmap");
invalid_inode_table = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_inode_table");
check_super_block(fs);
check_if_skip(fs);
if (bad_blocks_file)
read_bad_blocks_file(fs, bad_blocks_file, replace_bad_blocks);
else if (cflag)
test_disk(fs);
if (normalize_swapfs) {
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
ext2fs_native_flag()) {
fprintf(stderr, "%s: Filesystem byte order "
"already normalized.\n", device_name);
fatal_error(0);
}
}
if (swapfs)
swap_filesys(fs);
/*
* Mark the system as valid, 'til proven otherwise
*/
ext2fs_mark_valid(fs);
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
if (retval) {
com_err(program_name, retval,
"while reading bad blocks inode");
preenhalt(fs);
printf("This doesn't bode well, but we'll try to go on...\n");
}
pass1(fs);
free(invalid_inode_bitmap);
free(invalid_block_bitmap);
free(invalid_inode_table);
if (restart_e2fsck) {
ext2fs_close(fs);
printf("Restarting e2fsck from the beginning...\n");
restart_e2fsck = 0;
superblock = use_superblock;
goto restart;
}
pass2(fs);
pass3(fs);
pass4(fs);
pass5(fs);
#ifdef MTRACE
mtrace_print("Cleanup");
#endif
if (ext2fs_test_changed(fs)) {
exit_value = FSCK_NONDESTRUCT;
if (!preen)
printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
device_name);
if (root_filesystem && !read_only_root) {
printf("%s: ***** REBOOT LINUX *****\n", device_name);
exit_value = FSCK_REBOOT;
}
}
if (ext2fs_test_valid(fs))
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
else
exit_value = FSCK_UNCORRECTED;
if (rwflag) {
if (ext2fs_test_valid(fs)) {
if (!(fs->super->s_state & EXT2_VALID_FS))
exit_value = FSCK_NONDESTRUCT;
fs->super->s_state = EXT2_VALID_FS;
} else
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_mnt_count = 0;
fs->super->s_lastcheck = time(NULL);
ext2fs_mark_super_dirty(fs);
}
show_stats(fs);
write_bitmaps(fs);
ext2fs_close(fs);
sync_disks();
if (tflag)
print_resource_track(&global_rtrack);
return exit_value;
free(ctx);
}

View File

@ -44,12 +44,6 @@
*/
#define E2FSCK_CURRENT_REV 1
/*
* Inode count arrays
*/
extern ext2_icount_t inode_count;
extern ext2_icount_t inode_link_info;
/*
* The directory information structure; stores directory information
* collected in earlier passes, to avoid disk i/o in fetching the
@ -73,85 +67,110 @@ struct resource_track {
};
/*
* Variables
* E2fsck options
*/
extern const char * program_name;
extern const char * device_name;
extern ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
extern ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
extern ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
extern ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
extern ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */
extern ext2fs_block_bitmap block_illegal_map; /* Meta-data blocks */
extern const char *fix_msg[2]; /* Fixed or ignored! */
extern const char *clear_msg[2]; /* Cleared or ignored! */
extern int *invalid_inode_bitmap;
extern int *invalid_block_bitmap;
extern int *invalid_inode_table;
extern int restart_e2fsck;
/* Command line options */
extern int nflag;
extern int yflag;
extern int tflag;
extern int preen;
extern int verbose;
extern int list;
extern int debug;
extern int force;
extern int rwflag;
extern int inode_buffer_blocks;
extern int process_inode_size;
extern int directory_blocks;
extern int no_bad_inode;
extern int no_lpf;
extern int lpf_corrupted;
/* Files counts */
extern int fs_directory_count;
extern int fs_regular_count;
extern int fs_blockdev_count;
extern int fs_chardev_count;
extern int fs_links_count;
extern int fs_symlinks_count;
extern int fs_fast_symlinks_count;
extern int fs_fifo_count;
extern int fs_total_count;
extern int fs_badblocks_count;
extern int fs_sockets_count;
extern int fs_ind_count;
extern int fs_dind_count;
extern int fs_tind_count;
extern int fs_fragmented;
extern struct resource_track global_rtrack;
extern int invalid_bitmaps;
#define E2F_OPT_READONLY 0x0001
#define E2F_OPT_PREEN 0x0002
#define E2F_OPT_YES 0x0004
#define E2F_OPT_NO 0x0008
#define E2F_OPT_TIME 0x0010
#define E2F_OPT_TIME2 0x0020
#define E2F_OPT_CHECKBLOCKS 0x0040
#define E2F_OPT_DEBUG 0x0080
/*
* For pass1_check_directory and pass1_get_blocks
* This is the global e2fsck structure.
*/
extern ino_t stashed_ino;
extern struct ext2_inode *stashed_inode;
struct e2fsck_struct {
ext2_filsys fs;
const char *program_name;
const char *filesystem_name;
const char *device_name;
int options;
blk_t use_superblock; /* sb requested by user */
blk_t superblock; /* sb used to open fs */
ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
ext2fs_block_bitmap block_illegal_map; /* Meta-data blocks */
/*
* Inode count arrays
*/
ext2_icount_t inode_count;
ext2_icount_t inode_link_info;
/*
* Array of flags indicating whether an inode bitmap, block
* bitmap, or inode table is invalid
*/
int *invalid_inode_bitmap_flag;
int *invalid_block_bitmap_flag;
int *invalid_inode_table_flag;
int invalid_bitmaps; /* There are invalid bitmaps/itable */
/*
* For pass1_check_directory and pass1_get_blocks
*/
ino_t stashed_ino;
struct ext2_inode *stashed_inode;
/*
* Tuning parameters
*/
int process_inode_size;
int inode_buffer_blocks;
/*
* For timing purposes
*/
struct resource_track global_rtrack;
/* File counts */
int fs_directory_count;
int fs_regular_count;
int fs_blockdev_count;
int fs_chardev_count;
int fs_links_count;
int fs_symlinks_count;
int fs_fast_symlinks_count;
int fs_fifo_count;
int fs_total_count;
int fs_badblocks_count;
int fs_sockets_count;
int fs_ind_count;
int fs_dind_count;
int fs_tind_count;
int fs_fragmented;
};
typedef struct e2fsck_struct *e2fsck_t;
/*
* Variables
*/
extern int restart_e2fsck;
/*
* Procedure declarations
*/
extern void pass1(ext2_filsys fs);
extern void pass1_dupblocks(ext2_filsys fs, char *block_buf);
extern void pass2(ext2_filsys fs);
extern void pass3(ext2_filsys fs);
extern void pass4(ext2_filsys fs);
extern void pass5(ext2_filsys fs);
extern void pass1(e2fsck_t ctx);
extern void pass1_dupblocks(e2fsck_t ctx, char *block_buf);
extern void pass2(e2fsck_t ctx);
extern void pass3(e2fsck_t ctx);
extern void pass4(e2fsck_t ctx);
extern void pass5(e2fsck_t ctx);
/* e2fsck.c */
errcode_t e2fsck_allocate_context(e2fsck_t *ret);
errcode_t e2fsck_reset_context(e2fsck_t ctx);
void e2fsck_free_context(e2fsck_t ctx);
/* pass1.c */
extern errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
@ -163,9 +182,9 @@ extern errcode_t pass1_write_inode(ext2_filsys fs, ino_t ino,
extern int e2fsck_pass1_check_device_inode(struct ext2_inode *inode);
/* badblock.c */
extern void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
extern void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
int replace_bad_blocks);
extern void test_disk(ext2_filsys fs);
extern void test_disk(e2fsck_t ctx);
/* dirinfo.c */
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent);
@ -178,18 +197,22 @@ extern struct dir_info *dir_info_iter(int *control);
extern const char *ehandler_operation(const char *op);
extern void ehandler_init(io_channel channel);
/* super.c */
void check_super_block(e2fsck_t ctx);
/* swapfs.c */
void swap_filesys(ext2_filsys fs);
void swap_filesys(e2fsck_t ctx);
/* util.c */
extern void *allocate_memory(int size, const char *description);
extern int ask(const char * string, int def);
extern int ask(e2fsck_t ctx, const char * string, int def);
extern int ask_yn(const char * string, int def);
extern void fatal_error (const char * fmt_string);
extern void read_bitmaps(ext2_filsys fs);
extern void write_bitmaps(ext2_filsys fs);
extern void preenhalt(ext2_filsys fs);
extern void print_resource_track(struct resource_track *track);
extern void read_bitmaps(e2fsck_t ctx);
extern void write_bitmaps(e2fsck_t ctx);
extern void preenhalt(e2fsck_t ctx);
extern void print_resource_track(const char *desc,
struct resource_track *track);
extern void init_resource_track(struct resource_track *track);
extern int inode_has_valid_blocks(struct ext2_inode *inode);
extern void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
@ -199,10 +222,11 @@ extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
#ifdef MTRACE
extern void mtrace_print(char *mesg);
#endif
extern blk_t get_backup_sb(ext2_filsys fs);
#define die(str) fatal_error(str)
/*
* pass3.c
*/
extern int reconnect_file(ext2_filsys fs, ino_t inode);
extern int reconnect_file(e2fsck_t ctx, ino_t inode);

View File

@ -29,6 +29,10 @@ static errcode_t e2fsck_handle_read_error(io_channel channel,
{
int i;
char *p;
ext2_filsys fs = channel->app_data;
e2fsck_t ctx;
ctx = fs->private;
/*
* If more than one block was read, try reading each block
@ -51,8 +55,8 @@ static errcode_t e2fsck_handle_read_error(io_channel channel,
else
printf("Error reading block %lu (%s). ", block,
error_message(error));
preenhalt(NULL);
if (ask("Ignore error", 1))
preenhalt(ctx);
if (ask(ctx, "Ignore error", 1))
return 0;
return error;
@ -68,7 +72,11 @@ static errcode_t e2fsck_handle_write_error(io_channel channel,
{
int i;
const char *p;
ext2_filsys fs = channel->app_data;
e2fsck_t ctx;
ctx = fs->private;
/*
* If more than one block was written, try writing each block
* separately. We could use the actual bytes read to figure
@ -91,8 +99,8 @@ static errcode_t e2fsck_handle_write_error(io_channel channel,
else
printf("Error writing block %lu (%s). ", block,
error_message(error));
preenhalt(NULL);
if (ask("Ignore error", 1))
preenhalt(ctx);
if (ask(ctx, "Ignore error", 1))
return 0;
return error;

View File

@ -139,7 +139,7 @@ int main (int argc, char *argv[])
num_inodes++;
}
print_resource_track(&global_rtrack);
print_resource_track(NULL, &global_rtrack);
printf("%d inodes scanned.\n", num_inodes);
exit(0);

View File

@ -15,8 +15,11 @@
*
* %b <blk> block number
* %B <blkcount> integer
* %c <blk2> block number
* %di <dirent>->ino inode number
* %dn <dirent>->name string
* %dr <dirent>->rec_len
* %dl <dirent>->name_len
* %D <dir> inode number
* %g <group> integer
* %i <ino> inode number
@ -29,6 +32,7 @@
* %If <inode> -> i_file_acl
* %Id <inode> -> i_dir_acl
* %j <ino2> inode number
* %m <com_err error message>
* %N <num>
* %p ext2fs_get_pathname of directory <ino>
* %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
@ -37,6 +41,8 @@
* %q ext2fs_get_pathname of directory <dir>
* %Q ext2fs_get_pathname of directory <ino> with <dir> as
* the containing directory.
* %s <str> miscellaneous string
* %S backup superblock
*
* The following '@' expansions are supported:
*
@ -49,12 +55,15 @@
* @d directory
* @e entry
* @E Entry '%Dn' in %p (%i)
* @f filesystem
* @F for @i %i (%Q) is
* @g group
* @l lost+found
* @L is a link
* @u unattached
* @r root inode
* @s should be
* @S superblock
* @z zero-length
*/
@ -90,6 +99,7 @@ static const char *abbrevs[] = {
"ddirectory",
"eentry",
"E@e '%Dn' in %p (%i)",
"ffilesystem",
"Ffor @i %i (%Q) is",
"ggroup",
"llost+found",
@ -97,6 +107,7 @@ static const char *abbrevs[] = {
"uunattached",
"rroot @i",
"sshould be",
"Ssuper@b",
"zzero-length",
"@@",
0
@ -145,8 +156,8 @@ static void print_pathname(ext2_filsys fs, ino_t dir, ino_t ino)
* expansion; an @ expression can contain further '@' and '%'
* expressions.
*/
static _INLINE_ void expand_at_expression(ext2_filsys fs, char ch,
struct problem_context *ctx,
static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
struct problem_context *pctx,
int *first)
{
const char **cpp, *str;
@ -162,7 +173,7 @@ static _INLINE_ void expand_at_expression(ext2_filsys fs, char ch,
*first = 0;
fputc(toupper(*str++), stdout);
}
print_e2fsck_message(fs, str, ctx, *first);
print_e2fsck_message(ctx, str, pctx, *first);
} else
printf("@%c", ch);
}
@ -242,6 +253,12 @@ static _INLINE_ void expand_dirent_expression(char ch,
len = dirent->rec_len;
printf("%.*s", dirent->name_len, dirent->name);
break;
case 'r':
printf("%u", dirent->rec_len);
break;
case 'l':
printf("%u", dirent->name_len);
break;
default:
no_dirent:
printf("%%D%c", ch);
@ -265,6 +282,9 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
case 'B':
printf("%d", ctx->blkcount);
break;
case 'c':
printf("%u", ctx->blk2);
break;
case 'd':
printf("%lu", ctx->dir);
break;
@ -277,6 +297,9 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
case 'j':
printf("%lu", ctx->ino2);
break;
case 'm':
printf("%s", error_message(ctx->errcode));
break;
case 'N':
printf("%u", ctx->num);
break;
@ -293,6 +316,12 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
case 'Q':
print_pathname(fs, ctx->dir, ctx->ino);
break;
case 'S':
printf("%d", get_backup_sb(fs));
break;
case 's':
printf("%s", ctx->str);
break;
default:
no_context:
printf("%%%c", ch);
@ -300,25 +329,26 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
}
}
void print_e2fsck_message(ext2_filsys fs, const char *msg,
struct problem_context *ctx, int first)
void print_e2fsck_message(e2fsck_t ctx, const char *msg,
struct problem_context *pctx, int first)
{
ext2_filsys fs = ctx->fs;
const char * cp;
int i;
for (cp = msg; *cp; cp++) {
if (cp[0] == '@') {
cp++;
expand_at_expression(fs, *cp, ctx, &first);
expand_at_expression(ctx, *cp, pctx, &first);
} else if (cp[0] == '%' && cp[1] == 'I') {
cp += 2;
expand_inode_expression(*cp, ctx);
expand_inode_expression(*cp, pctx);
} else if (cp[0] == '%' && cp[1] == 'D') {
cp += 2;
expand_dirent_expression(*cp, ctx);
expand_dirent_expression(*cp, pctx);
} else if ((cp[0] == '%')) {
cp++;
expand_percent_expression(fs, *cp, ctx);
expand_percent_expression(fs, *cp, pctx);
} else {
for (i=0; cp[i]; i++)
if ((cp[i] == '@') || cp[i] == '%')

File diff suppressed because it is too large Load Diff

View File

@ -89,12 +89,12 @@ struct dup_inode {
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, void *private);
static void delete_file(ext2_filsys fs, struct dup_inode *dp,
static void delete_file(e2fsck_t ctx, struct dup_inode *dp,
char *block_buf);
static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf);
static void pass1b(ext2_filsys fs, char *block_buf);
static void pass1c(ext2_filsys fs, char *block_buf);
static void pass1d(ext2_filsys fs, char *block_buf);
static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf);
static void pass1b(e2fsck_t ctx, char *block_buf);
static void pass1c(e2fsck_t ctx, char *block_buf);
static void pass1d(e2fsck_t ctx, char *block_buf);
static struct dup_block *dup_blk = 0;
static struct dup_inode *dup_ino = 0;
@ -105,30 +105,32 @@ static ext2fs_inode_bitmap inode_dup_map;
/*
* Main procedure for handling duplicate blocks
*/
void pass1_dupblocks(ext2_filsys fs, char *block_buf)
void pass1_dupblocks(e2fsck_t ctx, char *block_buf)
{
errcode_t retval;
ext2_filsys fs = ctx->fs;
struct dup_block *p, *q, *next_p, *next_q;
struct dup_inode *r, *next_r;
struct problem_context pctx;
clear_problem_context(&pctx);
retval = ext2fs_allocate_inode_bitmap(fs,
pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
"multiply claimed inode map", &inode_dup_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_dup_map");
if (pctx.errcode) {
fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
pass1b(fs, block_buf);
pass1c(fs, block_buf);
pass1d(fs, block_buf);
pass1b(ctx, block_buf);
pass1c(ctx, block_buf);
pass1d(ctx, block_buf);
/*
* Time to free all of the accumulated data structures that we
* don't need anymore.
*/
ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
ext2fs_free_block_bitmap(ctx->block_dup_map); ctx->block_dup_map = 0;
for (p = dup_blk; p; p = next_p) {
next_p = p->next_block;
for (q = p; q; q = next_q) {
@ -148,34 +150,42 @@ void pass1_dupblocks(ext2_filsys fs, char *block_buf)
struct process_block_struct {
ino_t ino;
int dup_blocks;
e2fsck_t ctx;
struct problem_context *pctx;
};
void pass1b(ext2_filsys fs, char *block_buf)
void pass1b(e2fsck_t ctx, char *block_buf)
{
ext2_filsys fs = ctx->fs;
ino_t ino;
struct ext2_inode inode;
ext2_inode_scan scan;
errcode_t retval;
struct process_block_struct pb;
struct dup_inode *dp;
struct problem_context pctx;
clear_problem_context(&pctx);
printf("Duplicate blocks found... invoking duplicate block passes.\n");
printf("Pass 1B: Rescan for duplicate/bad blocks\n");
retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
if (retval) {
com_err(program_name, retval, "while opening inode scan");
fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
&scan);
if (pctx.errcode) {
fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
fatal_error(0);
}
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err(program_name, retval, "while starting inode scan");
pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
if (pctx.errcode) {
fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
fatal_error(0);
}
stashed_inode = &inode;
ctx->stashed_inode = &inode;
pb.ctx = ctx;
pb.pctx = &pctx;
while (ino) {
stashed_ino = ino;
pctx.ino = ctx->stashed_ino = ino;
if ((ino != EXT2_BAD_INO) &&
(!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
(!ext2fs_test_inode_bitmap(ctx->inode_used_map, ino) ||
!ext2fs_inode_has_valid_blocks(&inode)))
goto next;
@ -184,8 +194,7 @@ void pass1b(ext2_filsys fs, char *block_buf)
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
process_pass1b_block, &pb);
if (pb.dup_blocks) {
if (ino != EXT2_BAD_INO)
printf("\n");
end_problem_latch(ctx, PR_LATCH_DBLOCK);
dp = allocate_memory(sizeof(struct dup_inode),
"duplicate inode record");
dp->ino = ino;
@ -198,16 +207,15 @@ void pass1b(ext2_filsys fs, char *block_buf)
dup_inode_count++;
}
if (retval)
com_err(program_name, retval,
com_err(ctx->program_name, retval,
"while calling ext2fs_block_iterate in pass1b");
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
goto next;
if (retval) {
com_err(program_name, retval,
"while doing inode scan");
if (pctx.errcode) {
fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
fatal_error(0);
}
}
@ -224,21 +232,21 @@ int process_pass1b_block(ext2_filsys fs,
struct process_block_struct *p;
struct dup_block *dp, *q, *r;
int i;
e2fsck_t ctx;
if (!*block_nr)
return 0;
p = (struct process_block_struct *) private;
ctx = p->ctx;
if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
/* OK, this is a duplicate block */
if (p->ino != EXT2_BAD_INO) {
if (!p->dup_blocks)
printf("Duplicate/bad block(s) in inode %lu:",
p->ino);
printf(" %u", *block_nr);
p->pctx->blk = *block_nr;
fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
}
p->dup_blocks++;
ext2fs_mark_block_bitmap(block_dup_map, *block_nr);
ext2fs_mark_block_bitmap(ctx->block_dup_map, *block_nr);
ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
dp = allocate_memory(sizeof(struct dup_block),
"duplicate block record");
@ -314,13 +322,17 @@ static int search_dirent_proc(ino_t dir, int entry,
}
void pass1c(ext2_filsys fs, char *block_buf)
void pass1c(e2fsck_t ctx, char *block_buf)
{
ext2_filsys fs = ctx->fs;
struct dup_inode *p;
int inodes_left = dup_inode_count;
struct search_dir_struct sd;
struct problem_context pctx;
printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
clear_problem_context(&pctx);
fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
/*
* First check to see if any of the inodes with dup blocks is
@ -344,23 +356,25 @@ void pass1c(ext2_filsys fs, char *block_buf)
search_dirent_proc, &sd);
}
static void pass1d(ext2_filsys fs, char *block_buf)
static void pass1d(e2fsck_t ctx, char *block_buf)
{
ext2_filsys fs = ctx->fs;
struct dup_inode *p, *s;
struct dup_block *q, *r;
ino_t *shared;
int shared_len;
int i;
errcode_t retval;
int file_ok;
int meta_data = 0;
struct problem_context pctx;
printf("Pass 1D: Reconciling duplicate blocks\n");
read_bitmaps(fs);
printf("(There are %d inodes containing duplicate/bad blocks.)\n\n",
dup_inode_count);
clear_problem_context(&pctx);
fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
read_bitmaps(ctx);
pctx.num = dup_inode_count;
fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
shared = allocate_memory(sizeof(ino_t) * dup_inode_count,
"Shared inode list");
for (p = dup_ino; p; p = p->next) {
@ -385,7 +399,7 @@ static void pass1d(ext2_filsys fs, char *block_buf)
continue;
if (q->num_bad > 1)
file_ok = 0;
if (ext2fs_test_block_bitmap(block_illegal_map,
if (ext2fs_test_block_bitmap(ctx->block_illegal_map,
q->block)) {
file_ok = 0;
meta_data = 1;
@ -412,18 +426,17 @@ static void pass1d(ext2_filsys fs, char *block_buf)
/*
* Report the inode that we are working on
*/
clear_problem_context(&pctx);
pctx.inode = &p->inode;
pctx.ino = p->ino;
pctx.dir = p->dir;
pctx.blkcount = p->num_dupblocks;
pctx.num = meta_data ? shared_len+1 : shared_len;
fix_problem(fs, PR_1B_DUP_FILE, &pctx);
fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
pctx.blkcount = 0;
pctx.num = 0;
if (meta_data)
fix_problem(fs, PR_1B_SHARE_METADATA, &pctx);
fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
for (i = 0; i < shared_len; i++) {
for (s = dup_ino; s; s = s->next)
@ -437,28 +450,23 @@ static void pass1d(ext2_filsys fs, char *block_buf)
pctx.inode = &s->inode;
pctx.ino = s->ino;
pctx.dir = s->dir;
fix_problem(fs, PR_1B_DUP_FILE_LIST, &pctx);
fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
}
if (file_ok) {
printf("Duplicated blocks already reassigned or cloned.\n\n");
fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
continue;
}
if (ask("Clone duplicate/bad blocks", 1)) {
retval = clone_file(fs, p, block_buf);
if (retval)
printf("Couldn't clone file: %s\n",
error_message(retval));
else {
printf("\n");
if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
pctx.errcode = clone_file(ctx, p, block_buf);
if (pctx.errcode)
fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
else
continue;
}
}
if (ask("Delete file", 1))
delete_file(fs, p, block_buf);
if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
delete_file(ctx, p, block_buf);
else
ext2fs_unmark_valid(fs);
printf("\n");
}
free(shared);
}
@ -468,40 +476,46 @@ static int delete_file_block(ext2_filsys fs,
int blockcnt,
void *private)
{
struct process_block_struct *pb = private;
struct dup_block *p;
e2fsck_t ctx;
ctx = pb->ctx;
if (!*block_nr)
return 0;
if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
for (p = dup_blk; p; p = p->next_block)
if (p->block == *block_nr)
break;
if (p) {
p->num_bad--;
if (p->num_bad == 1)
ext2fs_unmark_block_bitmap(block_dup_map,
ext2fs_unmark_block_bitmap(ctx->block_dup_map,
*block_nr);
} else
com_err("delete_file_block", 0,
"internal error; can't find dup_blk for %d\n",
*block_nr);
} else {
ext2fs_unmark_block_bitmap(block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
}
return 0;
}
static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
static void delete_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
struct process_block_struct pb;
struct ext2_inode inode;
pb.ino = dp->ino;
pb.dup_blocks = dp->num_dupblocks;
pb.ctx = ctx;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
delete_file_block, &pb);
@ -509,10 +523,10 @@ static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
com_err("delete_file", retval,
"while calling ext2fs_block_iterate for inode %d",
dp->ino);
ext2fs_unmark_inode_bitmap(inode_used_map, dp->ino);
ext2fs_unmark_inode_bitmap(inode_dir_map, dp->ino);
if (inode_bad_map)
ext2fs_unmark_inode_bitmap(inode_bad_map, dp->ino);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, dp->ino);
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, dp->ino);
if (ctx->inode_bad_map)
ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, dp->ino);
ext2fs_unmark_inode_bitmap(fs->inode_map, dp->ino);
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_bb_dirty(fs);
@ -526,6 +540,7 @@ struct clone_struct {
errcode_t errcode;
ino_t dir;
char *buf;
e2fsck_t ctx;
};
static int clone_file_block(ext2_filsys fs,
@ -537,16 +552,19 @@ static int clone_file_block(ext2_filsys fs,
blk_t new_block;
errcode_t retval;
struct clone_struct *cs = (struct clone_struct *) private;
e2fsck_t ctx;
ctx = cs->ctx;
if (!*block_nr)
return 0;
if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
for (p = dup_blk; p; p = p->next_block)
if (p->block == *block_nr)
break;
if (p) {
retval = ext2fs_new_block(fs, 0, block_found_map,
retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
&new_block);
if (retval) {
cs->errcode = retval;
@ -574,10 +592,10 @@ static int clone_file_block(ext2_filsys fs,
}
p->num_bad--;
if (p->num_bad == 1)
ext2fs_unmark_block_bitmap(block_dup_map,
ext2fs_unmark_block_bitmap(ctx->block_dup_map,
*block_nr);
*block_nr = new_block;
ext2fs_mark_block_bitmap(block_found_map,
ext2fs_mark_block_bitmap(ctx->block_found_map,
new_block);
ext2fs_mark_block_bitmap(fs->block_map, new_block);
return BLOCK_CHANGED;
@ -589,18 +607,20 @@ static int clone_file_block(ext2_filsys fs,
return 0;
}
static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
struct clone_struct cs;
cs.errcode = 0;
cs.buf = malloc(fs->blocksize);
cs.dir = 0;
cs.ctx = ctx;
cs.buf = malloc(fs->blocksize);
if (!cs.buf)
return ENOMEM;
if (ext2fs_test_inode_bitmap(inode_dir_map, dp->ino))
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dp->ino))
cs.dir = dp->ino;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
@ -620,8 +640,3 @@ static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
}
return 0;
}

View File

@ -40,23 +40,19 @@
* - The inode_bad_map bitmap
*/
#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
/*
* Keeps track of how many times an inode is referenced.
*/
ext2_icount_t inode_count = 0;
static void deallocate_inode(ext2_filsys fs, ino_t ino,
static void deallocate_inode(e2fsck_t ctx, ino_t ino,
char* block_buf);
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino);
static int process_bad_inode(e2fsck_t ctx, ino_t dir, ino_t ino);
static int check_dir_block(ext2_filsys fs,
struct ext2_db_entry *dir_blocks_info,
void *private);
static int allocate_dir_block(ext2_filsys fs,
static int allocate_dir_block(e2fsck_t ctx,
struct ext2_db_entry *dir_blocks_info,
char *buf, struct problem_context *pctx);
static int update_dir_block(ext2_filsys fs,
@ -67,30 +63,33 @@ static int update_dir_block(ext2_filsys fs,
struct check_dir_struct {
char *buf;
struct problem_context pctx;
e2fsck_t ctx;
};
void pass2(ext2_filsys fs)
void pass2(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
char *buf;
struct resource_track rtrack;
struct dir_info *dir;
errcode_t retval;
ino_t size;
struct check_dir_struct cd;
init_resource_track(&rtrack);
clear_problem_context(&cd.pctx);
#ifdef MTRACE
mtrace_print("Pass 2");
#endif
if (!preen)
printf("Pass 2: Checking directory structure\n");
retval = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
0, inode_link_info, &inode_count);
if (retval) {
com_err("ext2fs_create_icount", retval,
"while creating inode_count");
if (!(ctx->options & E2F_OPT_PREEN))
fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
0, ctx->inode_link_info,
&ctx->inode_count);
if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
fatal_error(0);
}
buf = allocate_memory(fs->blocksize, "directory scan buffer");
@ -105,33 +104,31 @@ void pass2(ext2_filsys fs)
dir->parent = EXT2_ROOT_INO;
cd.buf = buf;
clear_problem_context(&cd.pctx);
cd.ctx = ctx;
retval = ext2fs_dblist_iterate(fs->dblist, check_dir_block, &cd);
if (retval) {
com_err("ext2fs_dblist_iterate", retval,
"while iterating through dblist");
cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
&cd);
if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
fatal_error(0);
}
free(buf);
ext2fs_free_dblist(fs->dblist);
if (inode_bad_map) {
ext2fs_free_inode_bitmap(inode_bad_map);
inode_bad_map = 0;
}
if (tflag > 1) {
printf("Pass 2: ");
print_resource_track(&rtrack);
if (ctx->inode_bad_map) {
ext2fs_free_inode_bitmap(ctx->inode_bad_map);
ctx->inode_bad_map = 0;
}
if (ctx->options & E2F_OPT_TIME2)
print_resource_track("Pass 2", &rtrack);
}
/*
* Make sure the first entry in the directory is '.', and that the
* directory entry is sane.
*/
static int check_dot(ext2_filsys fs,
static int check_dot(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
ino_t ino, struct problem_context *pctx)
{
@ -150,7 +147,7 @@ static int check_dot(ext2_filsys fs,
problem = PR_2_DOT_NULL_TERM;
if (problem) {
if (fix_problem(fs, problem, pctx)) {
if (fix_problem(ctx, problem, pctx)) {
if (dirent->rec_len < 12)
dirent->rec_len = 12;
dirent->inode = ino;
@ -162,7 +159,7 @@ static int check_dot(ext2_filsys fs,
}
}
if (dirent->inode != ino) {
if (fix_problem(fs, PR_2_BAD_INODE_DOT, pctx)) {
if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
dirent->inode = ino;
status = 1;
}
@ -170,9 +167,9 @@ static int check_dot(ext2_filsys fs,
if (dirent->rec_len > 12) {
new_len = dirent->rec_len - 12;
if (new_len > 12) {
preenhalt(fs);
preenhalt(ctx);
if (created ||
ask("Directory entry for '.' is big. Split", 1)) {
ask(ctx, "Directory entry for '.' is big. Split", 1)) {
nextdir = (struct ext2_dir_entry *)
((char *) dirent + 12);
dirent->rec_len = 12;
@ -191,7 +188,7 @@ static int check_dot(ext2_filsys fs,
* directory entry is sane. We do not check the inode number of '..'
* here; this gets done in pass 3.
*/
static int check_dotdot(ext2_filsys fs,
static int check_dotdot(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
struct dir_info *dir, struct problem_context *pctx)
{
@ -207,7 +204,7 @@ static int check_dotdot(ext2_filsys fs,
problem = PR_2_DOT_DOT_NULL_TERM;
if (problem) {
if (fix_problem(fs, problem, pctx)) {
if (fix_problem(ctx, problem, pctx)) {
if (dirent->rec_len < 12)
dirent->rec_len = 12;
/*
@ -232,7 +229,7 @@ static int check_dotdot(ext2_filsys fs,
* Check to make sure a directory entry doesn't contain any illegal
* characters.
*/
static int check_name(ext2_filsys fs,
static int check_name(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
ino_t dir_ino, struct problem_context *pctx)
{
@ -243,7 +240,7 @@ static int check_name(ext2_filsys fs,
for ( i = 0; i < dirent->name_len; i++) {
if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
if (fixup < 0) {
fixup = fix_problem(fs, PR_2_BAD_NAME, pctx);
fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
}
if (fixup) {
dirent->name[i] = '.';
@ -262,19 +259,23 @@ static int check_dir_block(ext2_filsys fs,
struct ext2_dir_entry *dirent;
int offset = 0;
int dir_modified = 0;
errcode_t retval;
int dot_state;
blk_t block_nr = db->blk;
ino_t ino = db->ino;
__u16 links;
struct check_dir_struct *cd = private;
char *buf = cd->buf;
char *buf;
e2fsck_t ctx;
int problem;
buf = cd->buf;
ctx = cd->ctx;
/*
* Make sure the inode is still in use (could have been
* deleted in the duplicate/bad blocks pass.
*/
if (!(ext2fs_test_inode_bitmap(inode_used_map, ino)))
if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
return 0;
cd->pctx.ino = ino;
@ -285,7 +286,7 @@ static int check_dir_block(ext2_filsys fs,
cd->pctx.num = 0;
if (db->blk == 0) {
if (allocate_dir_block(fs, db, buf, &cd->pctx))
if (allocate_dir_block(ctx, db, buf, &cd->pctx))
return 0;
block_nr = db->blk;
}
@ -300,14 +301,16 @@ static int check_dir_block(ext2_filsys fs,
db->blockcnt, ino);
#endif
retval = ext2fs_read_dir_block(fs, block_nr, buf);
if (retval) {
com_err(program_name, retval,
"while reading directory block %d", block_nr);
cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
if (cd->pctx.errcode) {
if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx))
fatal_error(0);
memset(buf, 0, fs->blocksize);
}
do {
dot_state++;
problem = 0;
dirent = (struct ext2_dir_entry *) (buf + offset);
cd->pctx.dirent = dirent;
cd->pctx.num = offset;
@ -315,7 +318,7 @@ static int check_dir_block(ext2_filsys fs,
(dirent->rec_len < 8) ||
((dirent->rec_len % 4) != 0) ||
((dirent->name_len+8) > dirent->rec_len)) {
if (fix_problem(fs, PR_2_DIR_CORRUPTED, &cd->pctx)) {
if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
dirent->rec_len = fs->blocksize - offset;
dirent->name_len = 0;
dirent->inode = 0;
@ -323,28 +326,27 @@ static int check_dir_block(ext2_filsys fs,
} else
return DIRENT_ABORT;
}
if (dirent->name_len > EXT2_NAME_LEN) {
if (fix_problem(fs, PR_2_FILENAME_LONG, &cd->pctx)) {
if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
dirent->name_len = EXT2_NAME_LEN;
dir_modified++;
}
}
if (dot_state == 1) {
if (check_dot(fs, dirent, ino, &cd->pctx))
if (check_dot(ctx, dirent, ino, &cd->pctx))
dir_modified++;
} else if (dot_state == 2) {
dir = get_dir_info(ino);
if (!dir) {
printf("Internal error: couldn't find dir_info for %lu\n",
ino);
fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
fatal_error(0);
}
if (check_dotdot(fs, dirent, dir, &cd->pctx))
if (check_dotdot(ctx, dirent, dir, &cd->pctx))
dir_modified++;
} else if (dirent->inode == ino) {
if (fix_problem(fs, PR_2_LINK_DOT, &cd->pctx)) {
problem = PR_2_LINK_DOT;
if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
@ -353,44 +355,66 @@ static int check_dir_block(ext2_filsys fs,
if (!dirent->inode)
goto next;
if (check_name(fs, dirent, ino, &cd->pctx))
dir_modified++;
/*
* Make sure the inode listed is a legal one.
*/
if (((dirent->inode != EXT2_ROOT_INO) &&
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) {
if (fix_problem(fs, PR_2_BAD_INO, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
/*
* If the inode is unused, offer to clear it.
*/
if (!(ext2fs_test_inode_bitmap(inode_used_map,
problem = PR_2_BAD_INO;
} else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
dirent->inode))) {
if (fix_problem(fs, PR_2_UNUSED_INODE, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
/*
* If the inode is unused, offer to clear it.
*/
problem = PR_2_UNUSED_INODE;
} else if (ctx->inode_bb_map &&
(ext2fs_test_inode_bitmap(ctx->inode_bb_map,
dirent->inode))) {
/*
* If the inode is in a bad block, offer to
* clear it.
*/
problem = PR_2_BB_INODE;
} else if ((dot_state > 2) &&
(dirent->name_len == 1) &&
(dirent->name[0] == '.')) {
/*
* If there's a '.' entry in anything other
* than the first directory entry, it's a
* duplicate entry that should be removed.
*/
problem = PR_2_DUP_DOT;
} else if ((dot_state > 2) &&
(dirent->name_len == 2) &&
(dirent->name[0] == '.') &&
(dirent->name[1] == '.')) {
/*
* If there's a '..' entry in anything other
* than the second directory entry, it's a
* duplicate entry that should be removed.
*/
problem = PR_2_DUP_DOT_DOT;
} else if ((dot_state > 2) &&
(dirent->inode == EXT2_ROOT_INO)) {
/*
* Don't allow links to the root directory.
* We check this specially to make sure we
* catch this error case even if the root
* directory hasn't been created yet.
*/
problem = PR_2_LINK_ROOT;
}
/*
* If the inode is in a bad block, offer to clear it.
*/
if (inode_bb_map &&
(ext2fs_test_inode_bitmap(inode_bb_map,
dirent->inode))) {
if (fix_problem(fs, PR_2_BB_INODE, &cd->pctx)) {
if (problem) {
if (fix_problem(ctx, problem, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else {
ext2fs_unmark_valid(fs);
if (problem == PR_2_BAD_INO)
goto next;
}
}
@ -400,30 +424,19 @@ static int check_dir_block(ext2_filsys fs,
* (We wait until now so that we can display the
* pathname to the user.)
*/
if (inode_bad_map &&
ext2fs_test_inode_bitmap(inode_bad_map,
if (ctx->inode_bad_map &&
ext2fs_test_inode_bitmap(ctx->inode_bad_map,
dirent->inode)) {
if (process_bad_inode(fs, ino, dirent->inode)) {
if (process_bad_inode(ctx, ino, dirent->inode)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
/*
* Don't allow links to the root directory. We check
* this specially to make sure we catch this error
* case even if the root directory hasn't been created
* yet.
*/
if ((dot_state > 2) && (dirent->inode == EXT2_ROOT_INO)) {
if (fix_problem(fs, PR_2_LINK_ROOT, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
if (check_name(ctx, dirent, ino, &cd->pctx))
dir_modified++;
/*
* If this is a directory, then mark its parent in its
* dir_info structure. If the parent field is already
@ -432,17 +445,17 @@ static int check_dir_block(ext2_filsys fs,
* and ask the user if he/she wants to clear this one.
*/
if ((dot_state > 2) &&
(ext2fs_test_inode_bitmap(inode_dir_map,
(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
dirent->inode))) {
subdir = get_dir_info(dirent->inode);
if (!subdir) {
printf("INTERNAL ERROR: missing dir %u\n",
dirent->inode);
cd->pctx.ino = dirent->inode;
fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
fatal_error(0);
}
if (subdir->parent) {
cd->pctx.ino2 = subdir->parent;
if (fix_problem(fs, PR_2_LINK_DIR,
if (fix_problem(ctx, PR_2_LINK_DIR,
&cd->pctx)) {
dirent->inode = 0;
dir_modified++;
@ -453,10 +466,11 @@ static int check_dir_block(ext2_filsys fs,
subdir->parent = ino;
}
ext2fs_icount_increment(inode_count, dirent->inode, &links);
ext2fs_icount_increment(ctx->inode_count, dirent->inode,
&links);
if (links > 1)
fs_links_count++;
fs_total_count++;
ctx->fs_links_count++;
ctx->fs_total_count++;
next:
offset += dirent->rec_len;
} while (offset < fs->blocksize);
@ -464,15 +478,17 @@ static int check_dir_block(ext2_filsys fs,
printf("\n");
#endif
if (offset != fs->blocksize) {
printf("Final rec_len is %d, should be %d\n",
dirent->rec_len,
dirent->rec_len - fs->blocksize + offset);
cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
dirent->rec_len = cd->pctx.num;
dir_modified++;
}
}
if (dir_modified) {
retval = ext2fs_write_dir_block(fs, block_nr, buf);
if (retval) {
com_err(program_name, retval,
"while writing directory block %d", block_nr);
cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
if (cd->pctx.errcode) {
if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, &cd->pctx))
fatal_error(0);
}
ext2fs_mark_changed(fs);
}
@ -488,9 +504,11 @@ static int deallocate_inode_block(ext2_filsys fs,
int blockcnt,
void *private)
{
e2fsck_t ctx = (e2fsck_t) private;
if (!*block_nr)
return 0;
ext2fs_unmark_block_bitmap(block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
return 0;
}
@ -498,26 +516,29 @@ static int deallocate_inode_block(ext2_filsys fs,
/*
* This fuction deallocates an inode
*/
static void deallocate_inode(ext2_filsys fs, ino_t ino,
static void deallocate_inode(e2fsck_t ctx, ino_t ino,
char* block_buf)
{
errcode_t retval;
ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
ext2fs_icount_store(inode_link_info, ino, 0);
struct problem_context pctx;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
e2fsck_read_inode(fs, ino, &inode, "deallocate_inode");
inode.i_links_count = 0;
inode.i_dtime = time(0);
e2fsck_write_inode(fs, ino, &inode, "deallocate_inode");
clear_problem_context(&pctx);
pctx.ino = ino;
/*
* Fix up the bitmaps...
*/
read_bitmaps(fs);
ext2fs_unmark_inode_bitmap(inode_used_map, ino);
ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
if (inode_bad_map)
ext2fs_unmark_inode_bitmap(inode_bad_map, ino);
read_bitmaps(ctx);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
if (ctx->inode_bad_map)
ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
@ -525,16 +546,17 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
return;
ext2fs_mark_bb_dirty(fs);
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
deallocate_inode_block, 0);
if (retval)
com_err("deallocate_inode", retval,
"while calling ext2fs_block_iterate for inode %d",
ino);
pctx.errcode = ext2fs_block_iterate(fs, ino, 0, block_buf,
deallocate_inode_block, ctx);
if (pctx.errcode) {
fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
fatal_error(0);
}
}
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
static int process_bad_inode(e2fsck_t ctx, ino_t dir, ino_t ino)
{
ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
int inode_modified = 0;
unsigned char *frag, *fsize;
@ -551,31 +573,31 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
!LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
!LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
!(LINUX_S_ISSOCK(inode.i_mode))) {
if (fix_problem(fs, PR_2_BAD_MODE, &pctx)) {
deallocate_inode(fs, ino, 0);
if (fix_problem(ctx, PR_2_BAD_MODE, &pctx)) {
deallocate_inode(ctx, ino, 0);
return 1;
}
}
if (LINUX_S_ISCHR(inode.i_mode)
&& !e2fsck_pass1_check_device_inode(&inode)) {
if (fix_problem(fs, PR_2_BAD_CHAR_DEV, &pctx)) {
deallocate_inode(fs, ino, 0);
if (fix_problem(ctx, PR_2_BAD_CHAR_DEV, &pctx)) {
deallocate_inode(ctx, ino, 0);
return 1;
}
}
if (LINUX_S_ISBLK(inode.i_mode)
&& !e2fsck_pass1_check_device_inode(&inode)) {
if (fix_problem(fs, PR_2_BAD_BLOCK_DEV, &pctx)) {
deallocate_inode(fs, ino, 0);
if (fix_problem(ctx, PR_2_BAD_BLOCK_DEV, &pctx)) {
deallocate_inode(ctx, ino, 0);
return 1;
}
}
if (inode.i_faddr &&
fix_problem(fs, PR_2_FADDR_ZERO, &pctx)) {
fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
inode.i_faddr = 0;
inode_modified++;
}
@ -598,7 +620,7 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
}
if (frag && *frag) {
pctx.num = *frag;
if (fix_problem(fs, PR_2_FRAG_ZERO, &pctx)) {
if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
*frag = 0;
inode_modified++;
}
@ -606,7 +628,7 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
}
if (fsize && *fsize) {
pctx.num = *fsize;
if (fix_problem(fs, PR_2_FSIZE_ZERO, &pctx)) {
if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
*fsize = 0;
inode_modified++;
}
@ -614,12 +636,12 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
}
if (inode.i_file_acl &&
fix_problem(fs, PR_2_FILE_ACL_ZERO, &pctx)) {
fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
inode.i_file_acl = 0;
inode_modified++;
}
if (inode.i_dir_acl &&
fix_problem(fs, PR_2_DIR_ACL_ZERO, &pctx)) {
fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
inode.i_dir_acl = 0;
inode_modified++;
}
@ -635,34 +657,34 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
* a "hole" in it, or if a directory has a illegal block number
* that was zeroed out and now needs to be replaced.
*/
static int allocate_dir_block(ext2_filsys fs,
static int allocate_dir_block(e2fsck_t ctx,
struct ext2_db_entry *db,
char *buf, struct problem_context *pctx)
{
ext2_filsys fs = ctx->fs;
blk_t blk;
char *block;
struct ext2_inode inode;
errcode_t retval;
if (fix_problem(fs, PR_2_DIRECTORY_HOLE, pctx) == 0)
if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
return 1;
/*
* Read the inode and block bitmaps in; we'll be messing with
* them.
*/
read_bitmaps(fs);
read_bitmaps(ctx);
/*
* First, find a free block
*/
retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
if (retval) {
com_err("allocate_dir_block", retval,
"while trying to fill a hole in a directory inode");
pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
if (pctx->errcode) {
pctx->str = "ext2fs_new_block";
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
ext2fs_mark_block_bitmap(block_found_map, blk);
ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
@ -670,22 +692,22 @@ static int allocate_dir_block(ext2_filsys fs,
* Now let's create the actual data block for the inode
*/
if (db->blockcnt)
retval = ext2fs_new_dir_block(fs, 0, 0, &block);
pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
else
retval = ext2fs_new_dir_block(fs, db->ino, EXT2_ROOT_INO,
&block);
pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
EXT2_ROOT_INO, &block);
if (retval) {
com_err("allocate_dir_block", retval,
"while creating new directory block");
if (pctx->errcode) {
pctx->str = "ext2fs_new_dir_block";
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
retval = ext2fs_write_dir_block(fs, blk, block);
pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
free(block);
if (retval) {
com_err("allocate_dir_block", retval,
"while writing an empty directory block");
if (pctx->errcode) {
pctx->str = "ext2fs_write_dir_block";
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
@ -702,11 +724,11 @@ static int allocate_dir_block(ext2_filsys fs,
* Finally, update the block pointers for the inode
*/
db->blk = blk;
retval = ext2fs_block_iterate(fs, db->ino, BLOCK_FLAG_HOLE,
pctx->errcode = ext2fs_block_iterate(fs, db->ino, BLOCK_FLAG_HOLE,
0, update_dir_block, db);
if (retval) {
com_err("allocate_dir_block", retval,
"while calling ext2fs_block_iterate");
if (pctx->errcode) {
pctx->str = "ext2fs_block_iterate";
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}

View File

@ -37,18 +37,17 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
static void check_root(ext2_filsys fs);
static void check_directory(ext2_filsys fs, struct dir_info *dir,
static void check_root(e2fsck_t ctx);
static void check_directory(e2fsck_t ctx, struct dir_info *dir,
struct problem_context *pctx);
static ino_t get_lost_and_found(ext2_filsys fs);
static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent);
static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj);
static errcode_t expand_directory(ext2_filsys fs, ino_t dir);
static ino_t get_lost_and_found(e2fsck_t ctx);
static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent);
static errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj);
static errcode_t expand_directory(e2fsck_t ctx, ino_t dir);
static ino_t lost_and_found = 0;
static int bad_lost_and_found = 0;
@ -56,120 +55,120 @@ static int bad_lost_and_found = 0;
static ext2fs_inode_bitmap inode_loop_detect;
static ext2fs_inode_bitmap inode_done_map;
void pass3(ext2_filsys fs)
void pass3(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
int i;
errcode_t retval;
struct resource_track rtrack;
struct problem_context pctx;
struct dir_info *dir;
init_resource_track(&rtrack);
clear_problem_context(&pctx);
#ifdef MTRACE
mtrace_print("Pass 3");
#endif
if (!preen)
printf("Pass 3: Checking directory connectivity\n");
if (!(ctx->options & E2F_OPT_PREEN))
fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
/*
* Allocate some bitmaps to do loop detection.
*/
retval = ext2fs_allocate_inode_bitmap(fs,
"inode loop detection bitmap",
&inode_loop_detect);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_loop_detect");
pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
"inode loop detection bitmap", &inode_loop_detect);
if (pctx.errcode) {
pctx.num = 1;
fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
retval = ext2fs_allocate_inode_bitmap(fs, "inode done bitmap",
&inode_done_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_done_map");
pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "inode done bitmap",
&inode_done_map);
if (pctx.errcode) {
pctx.num = 2;
fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
if (tflag) {
printf("Peak memory: ");
print_resource_track(&global_rtrack);
}
if (ctx->options & E2F_OPT_TIME)
print_resource_track("Peak memory", &ctx->global_rtrack);
check_root(fs);
check_root(ctx);
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
clear_problem_context(&pctx);
for (i=0; (dir = dir_info_iter(&i)) != 0;) {
if (ext2fs_test_inode_bitmap(inode_dir_map, dir->ino))
check_directory(fs, dir, &pctx);
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
check_directory(ctx, dir, &pctx);
}
free_dir_info(fs);
ext2fs_free_inode_bitmap(inode_loop_detect);
ext2fs_free_inode_bitmap(inode_done_map);
if (tflag > 1) {
printf("Pass 3: ");
print_resource_track(&rtrack);
}
if (ctx->options & E2F_OPT_TIME2)
print_resource_track("Pass 3", &rtrack);
}
/*
* This makes sure the root inode is present; if not, we ask if the
* user wants us to create it. Not creating it is a fatal error.
*/
static void check_root(ext2_filsys fs)
static void check_root(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
blk_t blk;
errcode_t retval;
struct ext2_inode inode;
char * block;
struct problem_context pctx;
if (ext2fs_test_inode_bitmap(inode_used_map, EXT2_ROOT_INO)) {
clear_problem_context(&pctx);
if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
/*
* If the root inode is a directory, die here. The
* user must have answered 'no' in pass1 when we
* offered to clear it.
*/
if (!(ext2fs_test_inode_bitmap(inode_dir_map, EXT2_ROOT_INO)))
if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
EXT2_ROOT_INO)))
fatal_error("Root inode not directory");
return;
}
if (!fix_problem(fs, PR_3_NO_ROOT_INODE, 0))
if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx))
fatal_error("Cannot proceed without a root inode.");
read_bitmaps(fs);
read_bitmaps(ctx);
/*
* First, find a free block
*/
retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
if (retval) {
com_err("ext2fs_new_block", retval,
"while trying to create root directory");
pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
if (pctx.errcode) {
pctx.str = "ext2fs_new_block";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
ext2fs_mark_block_bitmap(block_found_map, blk);
ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
/*
* Now let's create the actual data block for the inode
*/
retval = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
&block);
if (retval) {
com_err("ext2fs_new_dir_block", retval,
"while creating new root directory");
pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
&block);
if (pctx.errcode) {
pctx.str = "ext2fs_new_dir_block";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
retval = ext2fs_write_dir_block(fs, blk, block);
if (retval) {
com_err("ext2fs_write_dir_block", retval,
"while writing the root directory block");
pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
if (pctx.errcode) {
pctx.str = "ext2fs_write_dir_block";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
free(block);
@ -188,10 +187,10 @@ static void check_root(ext2_filsys fs)
/*
* Write out the inode.
*/
retval = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
if (retval) {
com_err("ext2fs_write_inode", retval,
"While trying to create /lost+found");
pctx.errcode = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
if (pctx.errcode) {
pctx.str = "ext2fs_write_inode";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
@ -199,11 +198,11 @@ static void check_root(ext2_filsys fs)
* Miscellaneous bookkeeping...
*/
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO);
ext2fs_icount_store(inode_count, EXT2_ROOT_INO, 2);
ext2fs_icount_store(inode_link_info, EXT2_ROOT_INO, 2);
ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
ext2fs_mark_inode_bitmap(inode_used_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(inode_dir_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
ext2fs_mark_ib_dirty(fs);
}
@ -216,9 +215,10 @@ static void check_root(ext2_filsys fs)
* a loop, we treat that as a disconnected directory and offer to
* reparent it to lost+found.
*/
static void check_directory(ext2_filsys fs, struct dir_info *dir,
static void check_directory(e2fsck_t ctx, struct dir_info *dir,
struct problem_context *pctx)
{
ext2_filsys fs = ctx->fs;
struct dir_info *p = dir;
ext2fs_clear_inode_bitmap(inode_loop_detect);
@ -258,12 +258,12 @@ static void check_directory(ext2_filsys fs, struct dir_info *dir,
* inode; offer to reconnect it to lost+found.
*/
pctx->ino = p->ino;
if (fix_problem(fs, PR_3_UNCONNECTED_DIR, pctx)) {
if (reconnect_file(fs, p->ino))
if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
if (reconnect_file(ctx, p->ino))
ext2fs_unmark_valid(fs);
else {
p->parent = lost_and_found;
fix_dotdot(fs, p, lost_and_found);
fix_dotdot(ctx, p, lost_and_found);
}
}
@ -276,8 +276,8 @@ check_dot_dot:
pctx->ino = dir->ino;
pctx->ino2 = dir->dotdot;
pctx->dir = dir->parent;
if (fix_problem(fs, PR_3_BAD_DOT_DOT, pctx))
fix_dotdot(fs, dir, dir->parent);
if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
fix_dotdot(ctx, dir, dir->parent);
}
}
@ -285,56 +285,61 @@ check_dot_dot:
* This routine gets the lost_and_found inode, making it a directory
* if necessary
*/
ino_t get_lost_and_found(ext2_filsys fs)
ino_t get_lost_and_found(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ino_t ino;
blk_t blk;
errcode_t retval;
struct ext2_inode inode;
char * block;
const char name[] = "lost+found";
struct problem_context pctx;
clear_problem_context(&pctx);
retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
sizeof(name)-1, 0, &ino);
if (!retval)
return ino;
if (retval != ENOENT)
printf("Error while trying to find /lost+found: %s",
error_message(retval));
if (!fix_problem(fs, PR_3_NO_LF_DIR, 0))
if (retval != ENOENT) {
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
}
if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
return 0;
/*
* Read the inode and block bitmaps in; we'll be messing with
* them.
*/
read_bitmaps(fs);
read_bitmaps(ctx);
/*
* First, find a free block
*/
retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
if (retval) {
com_err("ext2fs_new_block", retval,
"while trying to create /lost+found directory");
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
return 0;
}
ext2fs_mark_block_bitmap(block_found_map, blk);
ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
/*
* Next find a free inode.
*/
retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040755, inode_used_map,
&ino);
retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040755,
ctx->inode_used_map, &ino);
if (retval) {
com_err("ext2fs_new_inode", retval,
"while trying to create /lost+found directory");
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
return 0;
}
ext2fs_mark_inode_bitmap(inode_used_map, ino);
ext2fs_mark_inode_bitmap(inode_dir_map, ino);
ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_mark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
@ -343,16 +348,16 @@ ino_t get_lost_and_found(ext2_filsys fs)
*/
retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
if (retval) {
com_err("ext2fs_new_dir_block", retval,
"while creating new directory block");
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
return 0;
}
retval = ext2fs_write_dir_block(fs, blk, block);
free(block);
if (retval) {
com_err("ext2fs_write_dir_block", retval,
"while writing the directory block for /lost+found");
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
return 0;
}
@ -370,18 +375,19 @@ ino_t get_lost_and_found(ext2_filsys fs)
/*
* Next, write out the inode.
*/
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval) {
com_err("ext2fs_write_inode", retval,
"While trying to create /lost+found");
pctx.errcode = ext2fs_write_inode(fs, ino, &inode);
if (pctx.errcode) {
pctx.str = "ext2fs_write_inode";
fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
return 0;
}
/*
* Finally, create the directory link
*/
retval = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, 0);
if (retval) {
com_err("ext2fs_link", retval, "While creating /lost+found");
pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, 0);
if (pctx.errcode) {
pctx.str = "ext2fs_link";
fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
return 0;
}
@ -389,9 +395,9 @@ ino_t get_lost_and_found(ext2_filsys fs)
* Miscellaneous bookkeeping that needs to be kept straight.
*/
add_dir_info(fs, ino, EXT2_ROOT_INO);
adjust_inode_count(fs, EXT2_ROOT_INO, +1);
ext2fs_icount_store(inode_count, ino, 2);
ext2fs_icount_store(inode_link_info, ino, 2);
adjust_inode_count(ctx, EXT2_ROOT_INO, +1);
ext2fs_icount_store(ctx->inode_count, ino, 2);
ext2fs_icount_store(ctx->inode_link_info, ino, 2);
#if 0
printf("/lost+found created; inode #%lu\n", ino);
#endif
@ -401,44 +407,45 @@ ino_t get_lost_and_found(ext2_filsys fs)
/*
* This routine will connect a file to lost+found
*/
int reconnect_file(ext2_filsys fs, ino_t inode)
int reconnect_file(e2fsck_t ctx, ino_t inode)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
char name[80];
struct problem_context pctx;
clear_problem_context(&pctx);
pctx.ino = inode;
if (!bad_lost_and_found && !lost_and_found) {
lost_and_found = get_lost_and_found(ctx);
if (!lost_and_found)
bad_lost_and_found++;
}
if (bad_lost_and_found) {
printf("Bad or nonexistent /lost+found. Cannot reconnect.\n");
fix_problem(ctx, PR_3_NO_LPF, &pctx);
return 1;
}
if (!lost_and_found) {
lost_and_found = get_lost_and_found(fs);
if (!lost_and_found) {
printf("Bad or nonexistent /lost+found. Cannot reconnect.\n");
bad_lost_and_found++;
return 1;
}
}
sprintf(name, "#%lu", inode);
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
if (retval == EXT2_ET_DIR_NO_SPACE) {
if (!fix_problem(fs, PR_3_EXPAND_LF_DIR, 0))
if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
return 1;
retval = expand_directory(fs, lost_and_found);
retval = expand_directory(ctx, lost_and_found);
if (retval) {
printf("Could not expand /lost+found: %s\n",
error_message(retval));
pctx.errcode = retval;
fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
return 1;
}
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
}
if (retval) {
printf("Could not reconnect %lu: %s\n", inode,
error_message(retval));
pctx.errcode = retval;
fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
return 1;
}
adjust_inode_count(fs, inode, +1);
adjust_inode_count(ctx, inode, +1);
return 0;
}
@ -446,8 +453,9 @@ int reconnect_file(ext2_filsys fs, ino_t inode)
/*
* Utility routine to adjust the inode counts on an inode.
*/
static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
static errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
struct ext2_inode inode;
@ -465,11 +473,11 @@ static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
inode.i_links_count += adj;
if (adj == 1) {
ext2fs_icount_increment(inode_count, ino, 0);
ext2fs_icount_increment(inode_link_info, ino, 0);
ext2fs_icount_increment(ctx->inode_count, ino, 0);
ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
} else {
ext2fs_icount_decrement(inode_count, ino, 0);
ext2fs_icount_decrement(inode_link_info, ino, 0);
ext2fs_icount_decrement(ctx->inode_count, ino, 0);
ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
}
@ -487,6 +495,7 @@ struct fix_dotdot_struct {
ext2_filsys fs;
ino_t parent;
int done;
e2fsck_t ctx;
};
static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
@ -497,35 +506,42 @@ static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
{
struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) private;
errcode_t retval;
struct problem_context pctx;
if (dirent->name_len != 2)
return 0;
if (strncmp(dirent->name, "..", 2))
return 0;
retval = adjust_inode_count(fp->fs, dirent->inode, -1);
if (retval)
printf("Error while adjusting inode count on inode %u\n",
dirent->inode);
retval = adjust_inode_count(fp->fs, fp->parent, 1);
if (retval)
printf("Error while adjusting inode count on inode %lu\n",
fp->parent);
clear_problem_context(&pctx);
retval = adjust_inode_count(fp->ctx, dirent->inode, -1);
if (retval) {
pctx.errcode = retval;
fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
}
retval = adjust_inode_count(fp->ctx, fp->parent, 1);
if (retval) {
pctx.errcode = retval;
fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
}
dirent->inode = fp->parent;
fp->done++;
return DIRENT_ABORT | DIRENT_CHANGED;
}
static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent)
static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
struct fix_dotdot_struct fp;
struct problem_context pctx;
fp.fs = fs;
fp.parent = parent;
fp.done = 0;
fp.ctx = ctx;
#if 0
printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
@ -534,9 +550,11 @@ static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent)
retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
0, fix_dotdot_proc, &fp);
if (retval || !fp.done) {
printf("Couldn't fix parent of inode %lu: %s\n\n",
dir->ino, retval ? error_message(retval) :
"Couldn't find parent direntory entry");
clear_problem_context(&pctx);
pctx.ino = dir->ino;
pctx.errcode = retval;
fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
PR_3_FIX_PARENT_NOFIND, &pctx);
ext2fs_unmark_valid(fs);
}
dir->dotdot = parent;
@ -552,6 +570,7 @@ static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent)
struct expand_dir_struct {
int done;
errcode_t err;
e2fsck_t ctx;
};
static int expand_dir_proc(ext2_filsys fs,
@ -564,12 +583,16 @@ static int expand_dir_proc(ext2_filsys fs,
static blk_t last_blk = 0;
char *block;
errcode_t retval;
e2fsck_t ctx;
ctx = es->ctx;
if (*blocknr) {
last_blk = *blocknr;
return 0;
}
retval = ext2fs_new_block(fs, last_blk, block_found_map, &new_blk);
retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
&new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
@ -596,7 +619,7 @@ static int expand_dir_proc(ext2_filsys fs,
}
free(block);
*blocknr = new_blk;
ext2fs_mark_block_bitmap(block_found_map, new_blk);
ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
ext2fs_mark_bb_dirty(fs);
if (es->done)
@ -605,8 +628,9 @@ static int expand_dir_proc(ext2_filsys fs,
return BLOCK_CHANGED;
}
static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
static errcode_t expand_directory(e2fsck_t ctx, ino_t dir)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
struct expand_dir_struct es;
struct ext2_inode inode;
@ -620,6 +644,7 @@ static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
es.done = 0;
es.err = 0;
es.ctx = ctx;
retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND,
0, expand_dir_proc, &es);
@ -643,6 +668,3 @@ static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
return 0;
}

View File

@ -22,8 +22,9 @@
* This subroutine returns 1 then the caller shouldn't bother with the
* rest of the pass 4 tests.
*/
static int disconnect_inode(ext2_filsys fs, ino_t i)
static int disconnect_inode(e2fsck_t ctx, ino_t i)
{
ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
struct problem_context pctx;
@ -37,8 +38,8 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
/*
* This is a zero-length file; prompt to delete it...
*/
if (fix_problem(fs, PR_4_ZERO_LEN_INODE, &pctx)) {
ext2fs_icount_store(inode_link_info, i, 0);
if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
ext2fs_icount_store(ctx->inode_link_info, i, 0);
inode.i_links_count = 0;
inode.i_dtime = time(0);
e2fsck_write_inode(fs, i, &inode,
@ -46,9 +47,9 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
/*
* Fix up the bitmaps...
*/
read_bitmaps(fs);
ext2fs_unmark_inode_bitmap(inode_used_map, i);
ext2fs_unmark_inode_bitmap(inode_dir_map, i);
read_bitmaps(ctx);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
ext2fs_unmark_inode_bitmap(fs->inode_map, i);
ext2fs_mark_ib_dirty(fs);
return 0;
@ -58,8 +59,8 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
/*
* Prompt to reconnect.
*/
if (fix_problem(fs, PR_4_UNATTACHED_INODE, &pctx)) {
if (reconnect_file(fs, i))
if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
if (reconnect_file(ctx, i))
ext2fs_unmark_valid(fs);
} else {
/*
@ -74,8 +75,9 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
}
void pass4(ext2_filsys fs)
void pass4(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ino_t i;
struct ext2_inode inode;
struct resource_track rtrack;
@ -88,52 +90,50 @@ void pass4(ext2_filsys fs)
mtrace_print("Pass 4");
#endif
if (!preen)
printf("Pass 4: Checking reference counts\n");
clear_problem_context(&pctx);
if (!(ctx->options & E2F_OPT_PREEN))
fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (i == EXT2_BAD_INO ||
(i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
continue;
if (!(ext2fs_test_inode_bitmap(inode_used_map, i)) ||
(inode_bb_map &&
ext2fs_test_inode_bitmap(inode_bb_map, i)))
if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
(ctx->inode_bb_map &&
ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
continue;
ext2fs_icount_fetch(inode_link_info, i, &link_count);
ext2fs_icount_fetch(inode_count, i, &link_counted);
ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
if (link_counted == 0) {
if (disconnect_inode(fs, i))
if (disconnect_inode(ctx, i))
continue;
ext2fs_icount_fetch(inode_link_info, i, &link_count);
ext2fs_icount_fetch(inode_count, i, &link_counted);
ext2fs_icount_fetch(ctx->inode_link_info, i,
&link_count);
ext2fs_icount_fetch(ctx->inode_count, i,
&link_counted);
}
if (link_counted != link_count) {
e2fsck_read_inode(fs, i, &inode, "pass4");
pctx.ino = i;
pctx.inode = &inode;
if (link_count != inode.i_links_count) {
printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
"A MOUNTED (LIVE) FILESYSTEM.\n");
printf("inode_link_info[%ld] is %u, "
"inode.i_links_count is %d. "
"They should be the same!\n",
i, link_count,
inode.i_links_count);
pctx.num = link_count;
fix_problem(ctx,
PR_4_INCONSISTENT_COUNT, &pctx);
}
pctx.num = link_counted;
if (fix_problem(fs, PR_4_BAD_REF_COUNT, &pctx)) {
if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
inode.i_links_count = link_counted;
e2fsck_write_inode(fs, i, &inode, "pass4");
}
}
}
ext2fs_free_icount(inode_link_info); inode_link_info = 0;
ext2fs_free_icount(inode_count); inode_count = 0;
ext2fs_free_inode_bitmap(inode_bb_map);
if (tflag > 1) {
printf("Pass 4: ");
print_resource_track(&rtrack);
}
ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
ext2fs_free_inode_bitmap(ctx->inode_bb_map);
ctx->inode_bb_map = 0;
if (ctx->options & E2F_OPT_TIME2)
print_resource_track("Pass 4", &rtrack);
}

View File

@ -10,21 +10,18 @@
*
*/
#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
static void check_block_bitmaps(ext2_filsys fs);
static void check_inode_bitmaps(ext2_filsys fs);
static void check_inode_end(ext2_filsys fs);
static void check_block_end(ext2_filsys fs);
static void check_block_bitmaps(e2fsck_t ctx);
static void check_inode_bitmaps(e2fsck_t ctx);
static void check_inode_end(e2fsck_t ctx);
static void check_block_end(e2fsck_t ctx);
static int do_fix = -1;
static const char *fix_question = "Fix summary information";
void pass5(ext2_filsys fs)
void pass5(e2fsck_t ctx)
{
struct resource_track rtrack;
struct problem_context pctx;
#ifdef MTRACE
mtrace_print("Pass 5");
@ -32,28 +29,32 @@ void pass5(ext2_filsys fs)
init_resource_track(&rtrack);
if (!preen)
printf("Pass 5: Checking group summary information\n");
clear_problem_context(&pctx);
read_bitmaps(fs);
if (!(ctx->options & E2F_OPT_PREEN))
fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
check_block_bitmaps(fs);
check_inode_bitmaps(fs);
check_inode_end(fs);
check_block_end(fs);
read_bitmaps(ctx);
ext2fs_free_inode_bitmap(inode_used_map);
ext2fs_free_inode_bitmap(inode_dir_map);
ext2fs_free_block_bitmap(block_found_map);
check_block_bitmaps(ctx);
check_inode_bitmaps(ctx);
check_inode_end(ctx);
check_block_end(ctx);
if (tflag > 1) {
printf("Pass 5: ");
print_resource_track(&rtrack);
}
ext2fs_free_inode_bitmap(ctx->inode_used_map);
ctx->inode_used_map = 0;
ext2fs_free_inode_bitmap(ctx->inode_dir_map);
ctx->inode_dir_map = 0;
ext2fs_free_block_bitmap(ctx->block_found_map);
ctx->block_found_map = 0;
if (ctx->options & E2F_OPT_TIME2)
print_resource_track("Pass 5", &rtrack);
}
static void check_block_bitmaps(ext2_filsys fs)
static void check_block_bitmaps(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
blk_t i;
int *free_array;
int group = 0;
@ -61,21 +62,25 @@ static void check_block_bitmaps(ext2_filsys fs)
int free_blocks = 0;
int group_free = 0;
int actual, bitmap;
const char *print_header = "Block bitmap differences:";
struct problem_context pctx;
int problem, fixit;
errcode_t retval;
clear_problem_context(&pctx);
free_array = allocate_memory(fs->group_desc_count * sizeof(int),
"free block count array");
if ((fs->super->s_first_data_block <
ext2fs_get_block_bitmap_start(block_found_map)) ||
ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
(fs->super->s_blocks_count-1 >
ext2fs_get_block_bitmap_end(block_found_map))) {
printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
"don't match block_found_map endpoints (%d, %d).\n",
fs->super->s_first_data_block,
fs->super->s_blocks_count -1,
ext2fs_get_block_bitmap_start(block_found_map),
ext2fs_get_block_bitmap_end(block_found_map));
ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
pctx.num = 1;
pctx.blk = fs->super->s_first_data_block;
pctx.blk2 = fs->super->s_blocks_count -1;
pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
/* fatal */
fatal_error(0);
}
@ -83,56 +88,40 @@ static void check_block_bitmaps(ext2_filsys fs)
ext2fs_get_block_bitmap_start(fs->block_map)) ||
(fs->super->s_blocks_count-1 >
ext2fs_get_block_bitmap_end(fs->block_map))) {
printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
"don't match fs->block_map endpoints (%d, %d).\n",
fs->super->s_first_data_block,
fs->super->s_blocks_count -1,
ext2fs_get_block_bitmap_start(fs->block_map),
ext2fs_get_block_bitmap_end(fs->block_map));
pctx.num = 2;
pctx.blk = fs->super->s_first_data_block;
pctx.blk2 = fs->super->s_blocks_count -1;
pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
/* fatal */
fatal_error(0);
}
redo_counts:
for (i = fs->super->s_first_data_block;
i < fs->super->s_blocks_count;
i++) {
actual = ext2fs_fast_test_block_bitmap(block_found_map, i);
actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
if (actual == bitmap)
goto do_counts;
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen && print_header) {
printf(print_header);
print_header = 0;
}
if (!actual && bitmap) {
/*
* Block not used, but marked in use in the bitmap.
*/
if (!preen)
printf(" -%u", i);
if (do_fix)
ext2fs_unmark_block_bitmap(fs->block_map,
i);
problem = PR_5_UNUSED_BLOCK;
} else {
/*
* Block used, but not marked in use in the bitmap.
*/
if (!preen)
printf(" +%u", i);
if (do_fix)
ext2fs_mark_block_bitmap(fs->block_map,
i);
problem = PR_5_BLOCK_USED;
}
if (do_fix) {
ext2fs_mark_bb_dirty(fs);
bitmap = actual;
} else
ext2fs_unmark_valid(fs);
pctx.blk = i;
fix_problem(ctx, problem, &pctx);
do_counts:
if (!bitmap) {
group_free++;
@ -147,18 +136,30 @@ static void check_block_bitmaps(ext2_filsys fs)
group_free = 0;
}
}
if (!print_header)
printf(". %s\n", fix_msg[do_fix]);
fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
if (fixit == 1) {
ext2fs_free_block_bitmap(fs->block_map);
retval = ext2fs_copy_bitmap(ctx->block_found_map,
&fs->block_map);
/* XXX check retval --- should never fail! */
ext2fs_set_bitmap_padding(fs->block_map);
ext2fs_mark_bb_dirty(fs);
/* Redo the counts */
blocks = 0; free_blocks = 0; group_free = 0; group = 0;
memset(free_array, 0, fs->group_desc_count * sizeof(int));
goto redo_counts;
} else if (fixit == 0)
ext2fs_unmark_valid(fs);
for (i = 0; i < fs->group_desc_count; i++) {
if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen)
printf("Free blocks count wrong for "
"group %u (%u, counted=%d). %s\n", i,
fs->group_desc[i].bg_free_blocks_count,
free_array[i], fix_msg[do_fix]);
if (do_fix) {
pctx.group = i;
pctx.blk = fs->group_desc[i].bg_free_blocks_count;
pctx.blk2 = free_array[i];
if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
&pctx)) {
fs->group_desc[i].bg_free_blocks_count =
free_array[i];
ext2fs_mark_super_dirty(fs);
@ -167,14 +168,11 @@ static void check_block_bitmaps(ext2_filsys fs)
}
}
if (free_blocks != fs->super->s_free_blocks_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen)
printf("Free blocks count wrong "
"(%u, counted=%d). %s\n",
fs->super->s_free_blocks_count, free_blocks,
fix_msg[do_fix]);
if (do_fix) {
pctx.group = 0;
pctx.blk = fs->super->s_free_blocks_count;
pctx.blk2 = free_blocks;
if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
fs->super->s_free_blocks_count = free_blocks;
ext2fs_mark_super_dirty(fs);
} else
@ -183,8 +181,9 @@ static void check_block_bitmaps(ext2_filsys fs)
free(free_array);
}
static void check_inode_bitmaps(ext2_filsys fs)
static void check_inode_bitmaps(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ino_t i;
int free_inodes = 0;
int group_free = 0;
@ -194,77 +193,70 @@ static void check_inode_bitmaps(ext2_filsys fs)
int *free_array;
int *dir_array;
int actual, bitmap;
const char *print_header = "Inode bitmap differences:";
errcode_t retval;
struct problem_context pctx;
int problem, fixit;
clear_problem_context(&pctx);
free_array = allocate_memory(fs->group_desc_count * sizeof(int),
"free inode count array");
dir_array = allocate_memory(fs->group_desc_count * sizeof(int),
"directory count array");
if ((1 < ext2fs_get_inode_bitmap_start(inode_used_map)) ||
if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
(fs->super->s_inodes_count >
ext2fs_get_inode_bitmap_end(inode_used_map))) {
printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
"don't match inode_used_map endpoints (%d, %d).\n",
1, fs->super->s_inodes_count,
ext2fs_get_inode_bitmap_start(inode_used_map),
ext2fs_get_inode_bitmap_end(inode_used_map));
ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
pctx.num = 3;
pctx.blk = 1;
pctx.blk2 = fs->super->s_inodes_count;
pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
/* fatal */
fatal_error(0);
}
if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
(fs->super->s_inodes_count >
ext2fs_get_inode_bitmap_end(fs->inode_map))) {
printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
"don't match fs->inode_map endpoints (%d, %d).\n",
1, fs->super->s_inodes_count,
ext2fs_get_inode_bitmap_start(fs->inode_map),
ext2fs_get_inode_bitmap_end(fs->inode_map));
pctx.num = 4;
pctx.blk = 1;
pctx.blk2 = fs->super->s_inodes_count;
pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
/* fatal */
fatal_error(0);
}
redo_counts:
for (i = 1; i <= fs->super->s_inodes_count; i++) {
actual = ext2fs_fast_test_inode_bitmap(inode_used_map, i);
actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
if (actual == bitmap)
goto do_counts;
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen && print_header) {
printf(print_header);
print_header = 0;
}
if (!actual && bitmap) {
/*
* Inode wasn't used, but marked in bitmap
*/
if (!preen)
printf(" -%lu", i);
if (do_fix)
ext2fs_unmark_inode_bitmap(fs->inode_map, i);
} else if (actual && !bitmap) {
problem = PR_5_UNUSED_INODE;
} else /* if (actual && !bitmap) */ {
/*
* Inode used, but not in bitmap
*/
if (!preen)
printf (" +%lu", i);
if (do_fix)
ext2fs_mark_inode_bitmap(fs->inode_map, i);
problem = PR_5_INODE_USED;
}
if (do_fix) {
ext2fs_mark_ib_dirty(fs);
bitmap = actual;
} else
ext2fs_unmark_valid(fs);
pctx.ino = i;
fix_problem(ctx, problem, &pctx);
do_counts:
if (!bitmap) {
group_free++;
free_inodes++;
} else {
if (ext2fs_test_inode_bitmap(inode_dir_map, i))
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
dirs_count++;
}
inodes++;
@ -278,19 +270,31 @@ do_counts:
dirs_count = 0;
}
}
if (!print_header)
printf(". %s\n", fix_msg[do_fix]);
fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
if (fixit == 1) {
ext2fs_free_inode_bitmap(fs->inode_map);
retval = ext2fs_copy_bitmap(ctx->inode_used_map,
&fs->inode_map);
/* XXX check retval --- should never fail! */
ext2fs_set_bitmap_padding(fs->inode_map);
ext2fs_mark_ib_dirty(fs);
/* redo counts */
inodes = 0; free_inodes = 0; group_free = 0;
dirs_count = 0; group = 0;
memset(free_array, 0, fs->group_desc_count * sizeof(int));
memset(dir_array, 0, fs->group_desc_count * sizeof(int));
goto redo_counts;
} else if (fixit == 0)
ext2fs_unmark_valid(fs);
for (i = 0; i < fs->group_desc_count; i++) {
if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen)
printf ("Free inodes count wrong for "
"group #%lu (%u, counted=%d). %s\n", i,
fs->group_desc[i].bg_free_inodes_count,
free_array[i], fix_msg[do_fix]);
if (do_fix) {
pctx.group = i;
pctx.ino = fs->group_desc[i].bg_free_inodes_count;
pctx.ino2 = free_array[i];
if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
&pctx)) {
fs->group_desc[i].bg_free_inodes_count =
free_array[i];
ext2fs_mark_super_dirty(fs);
@ -298,14 +302,12 @@ do_counts:
ext2fs_unmark_valid(fs);
}
if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen)
printf ("Directories count wrong for "
"group #%lu (%u, counted=%d). %s\n", i,
fs->group_desc[i].bg_used_dirs_count,
dir_array[i], fix_msg[do_fix]);
if (do_fix) {
pctx.group = i;
pctx.ino = fs->group_desc[i].bg_used_dirs_count;
pctx.ino2 = dir_array[i];
if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
&pctx)) {
fs->group_desc[i].bg_used_dirs_count =
dir_array[i];
ext2fs_mark_super_dirty(fs);
@ -314,14 +316,11 @@ do_counts:
}
}
if (free_inodes != fs->super->s_free_inodes_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (!preen)
printf("Free inodes count wrong "
"(%u, counted=%d). %s\n",
fs->super->s_free_inodes_count, free_inodes,
fix_msg[do_fix]);
if (do_fix) {
pctx.group = -1;
pctx.ino = fs->super->s_free_inodes_count;
pctx.ino2 = free_inodes;
if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
fs->super->s_free_inodes_count = free_inodes;
ext2fs_mark_super_dirty(fs);
} else
@ -331,17 +330,20 @@ do_counts:
free(dir_array);
}
static void check_inode_end(ext2_filsys fs)
static void check_inode_end(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ino_t end, save_inodes_count, i;
errcode_t retval;
struct problem_context pctx;
clear_problem_context(&pctx);
end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
&save_inodes_count);
if (retval) {
com_err("check_inode_end", retval,
"while trying to fudge end of inode bitmap");
pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
&save_inodes_count);
if (pctx.errcode) {
pctx.num = 1;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
if (save_inodes_count == end)
@ -349,8 +351,7 @@ static void check_inode_end(ext2_filsys fs)
for (i = save_inodes_count + 1; i <= end; i++) {
if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
printf("Padding at end of inode bitmap is not set. ");
if (ask("Fix", 1)) {
if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
for (i = save_inodes_count + 1; i <= end; i++)
ext2fs_mark_inode_bitmap(fs->inode_map,
i);
@ -361,27 +362,30 @@ static void check_inode_end(ext2_filsys fs)
}
}
retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
save_inodes_count, 0);
if (retval) {
com_err("check_inode_end", retval,
"while trying to fudge end of inode bitmap back");
pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
save_inodes_count, 0);
if (pctx.errcode) {
pctx.num = 2;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
}
static void check_block_end(ext2_filsys fs)
static void check_block_end(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
blk_t end, save_blocks_count, i;
errcode_t retval;
struct problem_context pctx;
clear_problem_context(&pctx);
end = fs->block_map->start +
(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
retval = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
&save_blocks_count);
if (retval) {
com_err("check_block_end", retval,
"while trying to fudge end of block bitmap");
pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
&save_blocks_count);
if (pctx.errcode) {
pctx.num = 3;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
if (save_blocks_count == end)
@ -389,9 +393,7 @@ static void check_block_end(ext2_filsys fs)
for (i = save_blocks_count + 1; i <= end; i++) {
if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
printf("Padding at end of block bitmap is not set. ");
if (ask("Fix", 1)) {
if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
for (i = save_blocks_count + 1; i < end; i++)
ext2fs_mark_block_bitmap(fs->block_map,
i);
@ -402,12 +404,14 @@ static void check_block_end(ext2_filsys fs)
}
}
retval = ext2fs_fudge_block_bitmap_end(fs->block_map,
save_blocks_count, 0);
if (retval) {
com_err("check_block_end", retval,
"while trying to fudge end of block bitmap back");
pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
save_blocks_count, 0);
if (pctx.errcode) {
pctx.num = 4;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
}

View File

@ -19,71 +19,152 @@
#include "problem.h"
#define PROMPT_FIX 0
#define PROMPT_CLEAR 1
#define PROMPT_RELOCATE 2
#define PROMPT_ALLOCATE 3
#define PROMPT_EXPAND 4
#define PROMPT_CONNECT 5
#define PROMPT_CREATE 6
#define PROMPT_SALVAGE 7
#define PROMPT_TRUNCATE 8
#define PROMPT_CLEAR_INODE 9
#define PROMPT_NONE 0
#define PROMPT_FIX 1
#define PROMPT_CLEAR 2
#define PROMPT_RELOCATE 3
#define PROMPT_ALLOCATE 4
#define PROMPT_EXPAND 5
#define PROMPT_CONNECT 6
#define PROMPT_CREATE 7
#define PROMPT_SALVAGE 8
#define PROMPT_TRUNCATE 9
#define PROMPT_CLEAR_INODE 10
#define PROMPT_ABORT 11
#define PROMPT_SPLIT 12
#define PROMPT_CONTINUE 13
#define PROMPT_CLONE 14
#define PROMPT_DELETE 15
/*
* These are the prompts which are used to ask the user if they want
* to fix a problem.
*/
static const char *prompt[] = {
"Fix", /* 0 */
"Clear", /* 1 */
"Relocate", /* 2 */
"Allocate", /* 3 */
"Expand", /* 4 */
"Connect to /lost+found", /* 5 */
"Create", /* 6 */
"Salvage", /* 7 */
"Truncate", /* 8 */
"Clear inode" /* 9 */
};
"(no prompt)", /* 0 */
"Fix", /* 1 */
"Clear", /* 2 */
"Relocate", /* 3 */
"Allocate", /* 4 */
"Expand", /* 5 */
"Connect to /lost+found", /* 6 */
"Create", /* 7 */
"Salvage", /* 8 */
"Truncate", /* 9 */
"Clear inode", /* 10 */
"Abort", /* 11 */
"Split", /* 12 */
"Continue", /* 13 */
"Clone duplicate/bad blocks", /* 14 */
"Delete file", /* 15 */
};
/*
* These messages are printed when we are preen mode and we will be
* automatically fixing the problem.
*/
static const char *preen_msg[] = {
"FIXED", /* 0 */
"CLEARED", /* 1 */
"RELOCATED", /* 2 */
"ALLOCATED", /* 3 */
"EXPANDED", /* 4 */
"RECONNECTED", /* 5 */
"CREATED", /* 6 */
"SALVAGED", /* 7 */
"TRUNCATED", /* 8 */
"INODE CLEARED" /* 9 */
"(NONE)", /* 0 */
"FIXED", /* 1 */
"CLEARED", /* 2 */
"RELOCATED", /* 3 */
"ALLOCATED", /* 4 */
"EXPANDED", /* 5 */
"RECONNECTED", /* 6 */
"CREATED", /* 7 */
"SALVAGED", /* 8 */
"TRUNCATED", /* 9 */
"INODE CLEARED", /* 10 */
"ABORTED", /* 11 */
"SPLIT", /* 12 */
"CONTINUING", /* 13 */
"DUPLICATE/BAD BLOCKS CLONED", /* 14 */
"FILE DELETED", /* 15 */
};
static struct e2fsck_problem problem_table[] = {
static const struct e2fsck_problem problem_table[] = {
/* Pre-Pass 1 errors */
/* Block bitmap not in group */
{ PR_0_BB_NOT_GROUP, "@b @B for @g %g is not in @g. (@b %b)\n",
PROMPT_RELOCATE, 0 },
PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Inode bitmap not in group */
{ PR_0_IB_NOT_GROUP, "@i @B for @g %g is not in @g. (@b %b)\n",
PROMPT_RELOCATE, 0 },
PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Inode table not in group */
{ PR_0_ITABLE_NOT_GROUP,
"@i table for @g %g is not in @g. (@b %b)\n"
"WARNING: SEVERE DATA LOSS POSSIBLE.\n",
PROMPT_RELOCATE, 0 },
PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Superblock corrupt */
{ PR_0_SB_CORRUPT,
"\nThe @S could not be read or does not describe a correct ext2\n"
"@f. If the device is valid and it really contains an ext2\n"
"@f (and not swap or ufs or something else), then the @S\n"
"is corrupt, and you might try running e2fsck with an alternate @S:\n"
" e2fsck -b %S <device>\n\n",
PROMPT_NONE, PR_FATAL },
/* Filesystem size is wrong */
{ PR_0_FS_SIZE_WRONG,
"The @f size (according to the @S) is %b @bs\n"
"The physical size of the device is %c @bs\n"
"Either the @S or the partition table is likely to be corrupt!\n",
PROMPT_ABORT, 0 },
/* Fragments not supported */
{ PR_0_NO_FRAGMENTS,
"@S @b_size = %b, fragsize = %c.\n"
"This version of e2fsck does not support fragment sizes different\n"
"from the @b size.\n",
PROMPT_NONE, PR_FATAL },
/* Bad blocks_per_group */
{ PR_0_BLOCKS_PER_GROUP,
"@S @bs_per_group = %b, should have been %c\n",
PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
/* Bad first_data_block */
{ PR_0_FIRST_DATA_BLOCK,
"@S first_data_@b = %b, should have been %c\n",
PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
/* Adding UUID to filesystem */
{ PR_0_ADD_UUID,
"@f did not have a UUID; generating one.\n\n",
PROMPT_NONE, 0 },
/* Relocate hint */
{ PR_0_RELOCATE_HINT,
"Note: if there is several inode or block bitmap blocks\n"
"which require relocation, or one part of the inode table\n"
"which must be moved, you may wish to try running e2fsck\n"
"with the '-b %S' option first. The problem may lie only\n"
"with the primary block group descriptor, and the backup\n"
"block group descriptor may be OK.\n\n",
PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
/* Miscellaneous superblock corruption */
{ PR_0_MISC_CORRUPT_SUPER,
"Corruption found in @S. (%s = %N).\n",
PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
/* Error determing physical device size of filesystem */
{ PR_0_GETSIZE_ERROR,
"Error determining size of the physical device: %m\n",
PROMPT_NONE, PR_FATAL },
/* Pass 1 errors */
/* Pass 1: Checking inodes, blocks, and sizes */
{ PR_1_PASS_HEADER,
"Pass 1: Checking @is, @bs, and sizes\n",
PROMPT_NONE, 0 },
/* Root directory is not an inode */
{ PR_1_ROOT_NO_DIR, "@r is not a @d. ",
PROMPT_CLEAR, 0 },
@ -141,12 +222,12 @@ static struct e2fsck_problem problem_table[] = {
/* Inode has incorrect i_size */
{ PR_1_BAD_I_SIZE,
"@i %i, i_size is %Is, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
PROMPT_FIX, PR_PREEN_OK },
/* Inode has incorrect i_blocks */
{ PR_1_BAD_I_BLOCKS,
"@i %i, i_blocks is %Ib, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
"@i %i, i_@bs is %Ib, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
/* Illegal block number in inode */
{ PR_1_ILLEGAL_BLOCK_NUM,
@ -155,7 +236,7 @@ static struct e2fsck_problem problem_table[] = {
/* Block number overlaps fs metadata */
{ PR_1_BLOCK_OVERLAPS_METADATA,
"@b #%B (%b) overlaps filesystem metadata in @i %i. ",
"@b #%B (%b) overlaps @f metadata in @i %i. ",
PROMPT_CLEAR, PR_LATCH_BLOCK },
/* Inode has illegal blocks (latch question) */
@ -178,26 +259,230 @@ static struct e2fsck_problem problem_table[] = {
"Bad @b @i has illegal @b(s). ",
PROMPT_CLEAR, 0 },
/* Duplicate or bad blocks in use! */
{ PR_1_DUP_BLOCKS_PREENSTOP,
"Duplicate or bad @b in use!\n",
PROMPT_NONE, 0 },
/* Bad block used as bad block indirect block */
{ PR_1_BBINODE_BAD_METABLOCK,
"Bad @b %b used as bad @b indirect @b?!?\n",
PROMPT_NONE, PR_AFTER_CODE, PR_1_BBINODE_BAD_METABLOCK_PROMPT },
/* Inconsistency can't be fixed prompt */
{ PR_1_BBINODE_BAD_METABLOCK_PROMPT,
"\nThis inconsistency can not be fixed with e2fsck; to fix it, use\n"
"""dumpe2fs -b"" to dump out the bad @b "
"list and ""e2fsck -L filename""\n"
"to read it back in again.\n",
PROMPT_CONTINUE, PR_PREEN_NOMSG },
/* Bad primary block */
{ PR_1_BAD_PRIMARY_BLOCK,
"\nIf the @b is really bad, the @f can not be fixed.\n",
PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
/* Bad primary block prompt */
{ PR_1_BAD_PRIMARY_BLOCK_PROMPT,
"You can clear the this @b (and hope for the best) from the\n"
"bad @b list and hope that @b is really OK, but there are no\n"
"guarantees.\n\n",
PROMPT_CLEAR, PR_PREEN_NOMSG },
/* Bad primary superblock */
{ PR_1_BAD_PRIMARY_SUPERBLOCK,
"The primary @S (%b) is on the bad @b list.\n",
PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
/* Bad primary block group descriptors */
{ PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
"Block %b in the primary @g descriptors "
"is on the bad block list\n",
PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
/* Bad superblock in group */
{ PR_1_BAD_SUPERBLOCK,
"Warning: Group %g's @S (%b) is bad.\n",
PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Bad block group descriptors in group */
{ PR_1_BAD_GROUP_DESCRIPTORS,
"Warning: Group %d's copy of the @g descriptors has a bad "
"@b (%b).\n",
PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Block claimed for no reason */
{ PR_1_PROGERR_CLAIMED_BLOCK,
"Programming error? @b #%b claimed for no reason in "
"process_bad_@b.\n",
PROMPT_NONE, PR_PREEN_OK },
/* Could not allocate blocks for relocating metadata */
{ PR_1_RELOC_BLOCK_ALLOCATE,
"Could not allocate %N @b(s) for %s: %m\n",
PROMPT_NONE, PR_PREEN_OK },
/* Could not allocate memory during relocation process */
{ PR_1_RELOC_MEMORY_ALLOCATE,
"Could not allocate @b buffer for relocating %s\n",
PROMPT_NONE, PR_PREEN_OK },
/* Relocating metadata group information from X to Y */
{ PR_1_RELOC_FROM_TO,
"Relocating @g %g's %s from %b to %c...\n",
PROMPT_NONE, PR_PREEN_OK },
/* Relocating metatdata group information to X */
{ PR_1_RELOC_TO,
"Relocating @g %g's %s to %c...\n",
PROMPT_NONE, PR_PREEN_OK },
/* Block read error during relocation process */
{ PR_1_RELOC_READ_ERR,
"Warning: could not read @b %b of %s: %m\n",
PROMPT_NONE, PR_PREEN_OK },
/* Block write error during relocation process */
{ PR_1_RELOC_WRITE_ERR,
"Warning: could not write @b %b for %s: %m\n",
PROMPT_NONE, PR_PREEN_OK },
/* Error allocating inode bitmap */
{ PR_1_ALLOCATE_IBITMAP_ERROR,
"Error allocating @i @B (%N): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error allocating block bitmap */
{ PR_1_ALLOCATE_BBITMAP_ERROR,
"Error allocating @b @B (%N): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error allocating icount structure */
{ PR_1_ALLOCATE_ICOUNT,
"Error allocating icount link information: %m\n",
PROMPT_NONE, PR_FATAL },
/* Error allocating dbcount */
{ PR_1_ALLOCATE_DBCOUNT,
"Error allocating directory @b array: %m\n",
PROMPT_NONE, PR_FATAL },
/* Error while scanning inodes */
{ PR_1_ISCAN_ERROR,
"Error while scanning inodes (%i): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error while iterating over blocks */
{ PR_1_BLOCK_ITERATE,
"Error while iterating over blocks in inode %i: %m\n",
PROMPT_NONE, PR_FATAL },
/* Error while storing inode count information */
{ PR_1_ICOUNT_STORE,
"Error storing inode count information (inode=%i, count=%N): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error while storing directory block information */
{ PR_1_ADD_DBLOCK,
"Error storing dir block information "
"(inode=%i, block=%b, num=%N): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error while reading inode (for clearing) */
{ PR_1_READ_INODE,
"Error reading inode %i: %m\n",
PROMPT_NONE, PR_FATAL },
/* Pass 1b errors */
/* Pass 1B: Rescan for duplicate/bad blocks */
{ PR_1B_PASS_HEADER,
"Duplicate @bs found... invoking duplicate @b passes.\n"
"Pass 1B: Rescan for duplicate/bad @bs\n",
PROMPT_NONE, 0 },
/* Duplicate/bad block(s) header */
{ PR_1B_DUP_BLOCK_HEADER,
"Duplicate/bad @b(s) in @i %i:",
PROMPT_NONE, 0 },
/* Duplicate/bad block(s) in inode */
{ PR_1B_DUP_BLOCK,
" %b",
PROMPT_NONE, PR_LATCH_DBLOCK },
/* Duplicate/bad block(s) end */
{ PR_1B_DUP_BLOCK_END,
"\n",
PROMPT_NONE, 0 },
/* Error while scanning inodes */
{ PR_1B_ISCAN_ERROR,
"Error while scanning inodes (%i): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error allocating inode bitmap */
{ PR_1B_ALLOCATE_IBITMAP_ERROR,
"Error allocating @i @B (inode_dup_map): %m\n",
PROMPT_NONE, PR_FATAL },
/* Pass 1C: Scan directories for inodes with dup blocks. */
{ PR_1C_PASS_HEADER,
"Pass 1C: Scan directories for @is with dup @bs.\n",
PROMPT_NONE, 0 },
/* Pass 1D: Reconciling duplicate blocks */
{ PR_1D_PASS_HEADER,
"Pass 1D: Reconciling duplicate @bs\n",
PROMPT_NONE, 0 },
/* File has duplicate blocks */
{ PR_1B_DUP_FILE,
{ PR_1D_DUP_FILE,
"File %Q (@i #%i, mod time %IM) \n"
" has %B duplicate @b(s), shared with %N file(s):\n",
PROMPT_FIX, PR_MSG_ONLY },
PROMPT_NONE, 0 },
/* List of files sharing duplicate blocks */
{ PR_1B_DUP_FILE_LIST,
{ PR_1D_DUP_FILE_LIST,
"\t%Q (@i #%i, mod time %IM)\n",
PROMPT_FIX, PR_MSG_ONLY },
PROMPT_NONE, 0 },
/* File sharing blocks with filesystem metadata */
{ PR_1B_SHARE_METADATA,
"\t<filesystem metadata>\n",
PROMPT_FIX, PR_MSG_ONLY },
{ PR_1D_SHARE_METADATA,
"\t<@f metadata>\n",
PROMPT_NONE, 0 },
/* Report of how many duplicate/bad inodes */
{ PR_1D_NUM_DUP_INODES,
"(There are %N @is containing duplicate/bad @bs.)\n\n",
PROMPT_NONE, 0 },
/* Duplicated blocks already reassigned or cloned. */
{ PR_1D_DUP_BLOCKS_DEALT,
"Duplicated @bs already reassigned or cloned.\n\n",
PROMPT_NONE, 0 },
/* Clone duplicate/bad blocks? */
{ PR_1D_CLONE_QUESTION,
"", PROMPT_CLONE, PR_NO_OK },
/* Delete file? */
{ PR_1D_DELETE_QUESTION,
"", PROMPT_DELETE, 0 },
/* Couldn't clone file (error) */
{ PR_1D_CLONE_ERROR,
"Couldn't clone file: %m\n", PROMPT_NONE, 0 },
/* Pass 2 errors */
/* Pass 2: Checking directory structure */
{ PR_2_PASS_HEADER,
"Pass 2: Checking @d structure\n",
PROMPT_NONE, 0 },
/* Bad inode number for '.' */
{ PR_2_BAD_INODE_DOT,
"Bad @i number for '.' in @d @i %i.\n",
@ -323,8 +608,64 @@ static struct e2fsck_problem problem_table[] = {
"@i %i (%Q) is an @I @b device.\n",
PROMPT_CLEAR, 0 },
/* Pass 3 errors */
/* Duplicate '.' entry */
{ PR_2_DUP_DOT,
"@E is duplicate '.' @e.\n",
PROMPT_FIX, 0 },
/* Duplicate '..' entry */
{ PR_2_DUP_DOT_DOT,
"@E is duplicate '..' @e.\n",
PROMPT_FIX, 0 },
/* Internal error: couldn't find dir_info */
{ PR_2_NO_DIRINFO,
"Internal error: couldn't find dir_info for %i.\n",
PROMPT_NONE, PR_FATAL },
/* Final rec_len is wrong */
{ PR_2_FINAL_RECLEN,
"@E has rec_len of %dr, should be %N.\n",
PROMPT_FIX, 0 },
/* Error allocating icount structure */
{ PR_2_ALLOCATE_ICOUNT,
"Error allocating icount structure: %m\n",
PROMPT_NONE, PR_FATAL },
/* Error iterating over directory blocks */
{ PR_2_DBLIST_ITERATE,
"Error interating over directory blocks: %m\n",
PROMPT_NONE, PR_FATAL },
/* Error reading directory block */
{ PR_2_READ_DIRBLOCK,
"Error reading directory block %b (inode %i): %m\n",
PROMPT_CONTINUE, 0 },
/* Error writing directory block */
{ PR_2_WRITE_DIRBLOCK,
"Error writing directory block %b (inode %i): %m\n",
PROMPT_CONTINUE, 0 },
/* Error allocating new directory block */
{ PR_2_ALLOC_DIRBOCK,
"Error allocating new directory block for inode %i (%s): %m\n",
PROMPT_NONE, 0 },
/* Error deallocating inode */
{ PR_2_DEALLOC_INODE,
"Error deallocating inode %i: %m\n",
PROMPT_NONE, PR_FATAL },
/* Pass 3 errors */
/* Pass 3: Checking directory connectivity */
{ PR_3_PASS_HEADER,
"Pass 3: Checking @d connectivity\n",
PROMPT_NONE, 0 },
/* Root inode not allocated */
{ PR_3_NO_ROOT_INODE,
"@r not allocated. ",
@ -350,8 +691,83 @@ static struct e2fsck_problem problem_table[] = {
"'..' in %Q (%i) is %P (%j), @s %q (%d).\n",
PROMPT_FIX, 0 },
/* Bad or non-existent /lost+found. Cannot reconnect */
{ PR_3_NO_LPF,
"Bad or non-existent /@l. Cannot reconnect\n",
PROMPT_NONE, 0 },
/* Could not expand /lost+found */
{ PR_3_CANT_EXPAND_LPF,
"Could not expand /@l: %m\n",
PROMPT_NONE, 0 },
/* Could not reconnect inode */
{ PR_3_CANT_RECONNECT,
"Could not reconnect %i: %m\n",
PROMPT_NONE, 0 },
/* Error while trying to find /lost+found */
{ PR_3_ERR_FIND_LPF,
"Error while trying to find /@l: %m\n",
PROMPT_NONE, 0 },
/* Error in ext2fs_new_block while creating /lost+found */
{ PR_3_ERR_LPF_NEW_BLOCK,
"ext2fs_new_@b: %m while trying to create /@l @d\n",
PROMPT_NONE, 0 },
/* Error in ext2fs_new_inode while creating /lost+found */
{ PR_3_ERR_LPF_NEW_INODE,
"ext2fs_new_@i: %m while trying to create /@l @d\n",
PROMPT_NONE, 0 },
/* Error in ext2fs_new_dir_block while creating /lost+found */
{ PR_3_ERR_LPF_NEW_DIR_BLOCK,
"ext2fs_new_dir_@b: %m while creating new @d @b\n",
PROMPT_NONE, 0 },
/* Error while writing directory block for /lost+found */
{ PR_3_ERR_LPF_WRITE_BLOCK,
"ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n",
PROMPT_NONE, 0 },
/* Error while adjusting inode count */
{ PR_3_ADJUST_INODE,
"Error while adjusting @i count on @i %i\n",
PROMPT_NONE, 0 },
/* Couldn't fix parent directory -- error */
{ PR_3_FIX_PARENT_ERR,
"Couldn't fix parent of @i %i: %m\n\n",
PROMPT_NONE, 0 },
/* Couldn't fix parent directory -- couldn't find it */
{ PR_3_FIX_PARENT_NOFIND,
"Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n",
PROMPT_NONE, 0 },
/* Error allocating inode bitmap */
{ PR_3_ALLOCATE_IBITMAP_ERROR,
"Error allocating @i @B (%N): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error creating root directory */
{ PR_3_CREATE_ROOT_ERROR,
"Error creating root @d (%s): %m\n",
PROMPT_NONE, PR_FATAL },
/* Error creating lost and found directory */
{ PR_3_CREATE_LPF_ERROR,
"Error creating /@l @d (%s): %m\n",
PROMPT_NONE, PR_FATAL },
/* Pass 4 errors */
/* Pass 4: Checking reference counts */
{ PR_4_PASS_HEADER,
"Pass 4: Checking reference counts\n",
PROMPT_NONE, 0 },
/* Unattached zero-length inode */
{ PR_4_ZERO_LEN_INODE,
"@u @z @i %i. ",
@ -366,7 +782,107 @@ static struct e2fsck_problem problem_table[] = {
{ PR_4_BAD_REF_COUNT,
"@i %i ref count is %Il, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
{ PR_4_INCONSISTENT_COUNT,
"WARNING: PROGRAMMING BUG IN E2FSCK!\n"
"\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
"@i_link_info[%i] is %N, @i.i_links_count is %Il. "
"They should be the same!\n",
PROMPT_NONE, 0 },
/* Pass 5 errors */
/* Pass 5: Checking group summary information */
{ PR_5_PASS_HEADER,
"Pass 5: Checking @g summary information\n",
PROMPT_NONE, 0 },
/* Padding at end of inode bitmap is not set. */
{ PR_5_INODE_BMAP_PADDING,
"Padding at end of @i @B is not set. ",
PROMPT_FIX, PR_PREEN_OK },
/* Padding at end of block bitmap is not set. */
{ PR_5_BLOCK_BMAP_PADDING,
"Padding at end of @b @B is not set. ",
PROMPT_FIX, PR_PREEN_OK },
/* Block bitmap differences header */
{ PR_5_BLOCK_BITMAP_HEADER,
"@b @B differences: ",
PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
/* Block not used, but marked in bitmap */
{ PR_5_UNUSED_BLOCK,
" -%b",
PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
/* Block used, but not marked used in bitmap */
{ PR_5_BLOCK_USED,
" +%b",
PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
/* Block bitmap differences end */
{ PR_5_BLOCK_BITMAP_END,
"\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Inode bitmap differences header */
{ PR_5_INODE_BITMAP_HEADER,
"@i @B differences: ",
PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Inode not used, but marked in bitmap */
{ PR_5_UNUSED_INODE,
" -%i",
PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
/* Inode used, but not marked used in bitmap */
{ PR_5_INODE_USED,
" +%i",
PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
/* Inode bitmap differences end */
{ PR_5_INODE_BITMAP_END,
"\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Free inodes count for group wrong */
{ PR_5_FREE_INODE_COUNT_GROUP,
"Free @is count wrong for @g #%g (%i, counted=%j).\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Directories count for group wrong */
{ PR_5_FREE_DIR_COUNT_GROUP,
"Directories count wrong for @g #%g (%i, counted=%j).\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Free inodes count wrong */
{ PR_5_FREE_INODE_COUNT,
"Free @is count wrong (%i, counted=%j).\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Free blocks count for group wrong */
{ PR_5_FREE_BLOCK_COUNT_GROUP,
"Free @bs count wrong for @g #%g (%b, counted=%c).\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Free blocks count wrong */
{ PR_5_FREE_BLOCK_COUNT,
"Free @bs count wrong (%b, counted=%c).\n",
PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
/* Programming error: bitmap endpoints don't match */
{ PR_5_BMAP_ENDPOINTS,
"PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
"match calculated @B endpoints (%i, %j)\n",
PROMPT_NONE, PR_FATAL },
/* Internal error: fudging end of bitmap */
{ PR_5_FUDGE_BITMAP_ERROR,
"Internal error: fudging end of bitmap (%N)\n",
PROMPT_NONE, PR_FATAL },
{ 0 }
};
@ -376,14 +892,17 @@ static struct e2fsck_problem problem_table[] = {
* question for the set of problems, and all of the associated
* problems will be either fixed or not fixed.
*/
char pr_latch[7]; /* Latch flags register */
char pr_suppress[7]; /* Latch groups which are suppressed */
int latch_question[7] = {
PR_1_INODE_BLOCK_LATCH,
PR_1_INODE_BBLOCK_LATCH
static struct latch_descr pr_latch_info[] = {
{ PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
{ PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
{ PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
{ PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
{ PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
{ PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
{ -1, 0, 0 },
};
static struct e2fsck_problem *find_problem(int code)
static const struct e2fsck_problem *find_problem(int code)
{
int i;
@ -394,15 +913,53 @@ static struct e2fsck_problem *find_problem(int code)
return 0;
}
void reset_problem_latch(int mask)
static struct latch_descr *find_latch(int code)
{
pr_latch[PR_LATCH(mask)] = 0;
pr_suppress[PR_LATCH(mask)] = 0;
int i;
for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
if (pr_latch_info[i].latch_code == code)
return &pr_latch_info[i];
}
return 0;
}
void suppress_latch_group(int mask, int value)
int end_problem_latch(e2fsck_t ctx, int mask)
{
pr_suppress[PR_LATCH(mask)] = value;
struct latch_descr *ldesc;
struct problem_context pctx;
int answer = -1;
ldesc = find_latch(mask);
if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
clear_problem_context(&pctx);
answer = fix_problem(ctx, ldesc->end_message, &pctx);
}
ldesc->flags &= ~(PRL_VARIABLE);
return answer;
}
int set_latch_flags(int mask, int setflags, int clearflags)
{
struct latch_descr *ldesc;
ldesc = find_latch(mask);
if (!ldesc)
return -1;
ldesc->flags |= setflags;
ldesc->flags &= ~clearflags;
return 0;
}
int get_latch_flags(int mask, int *value)
{
struct latch_descr *ldesc;
ldesc = find_latch(mask);
if (!ldesc)
return -1;
*value = ldesc->flags;
return 0;
}
void clear_problem_context(struct problem_context *ctx)
@ -412,11 +969,13 @@ void clear_problem_context(struct problem_context *ctx)
ctx->group = -1;
}
int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx)
int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
{
struct e2fsck_problem *ptr;
int def_yn, answer;
int latch;
ext2_filsys fs = ctx->fs;
const struct e2fsck_problem *ptr;
struct latch_descr *ldesc = 0;
const char *message;
int def_yn, answer, ans;
int print_answer = 0;
int suppress = 0;
@ -432,45 +991,72 @@ int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx)
* latch question, if it exists
*/
if (ptr->flags & PR_LATCH_MASK) {
latch = PR_LATCH(ptr->flags);
if (latch_question[latch] && !pr_latch[latch])
pr_latch[latch] = fix_problem(fs,
latch_question[latch],
ctx) + 1;
if (pr_suppress[latch])
ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
ans = fix_problem(ctx, ldesc->question, pctx);
if (ans == 1)
ldesc->flags |= PRL_YES;
if (ans == 0)
ldesc->flags |= PRL_NO;
ldesc->flags |= PRL_LATCHED;
}
if (ldesc->flags & PRL_SUPPRESS)
suppress++;
}
if ((ptr->flags & PR_PREEN_NOMSG) &&
(ctx->options & E2F_OPT_PREEN))
suppress++;
if (!suppress) {
if (preen)
printf("%s: ", device_name);
print_e2fsck_message(fs, ptr->e2p_description, ctx, 1);
message = ptr->e2p_description;
if (ctx->options & E2F_OPT_PREEN) {
printf("%s: ", ctx->device_name);
#if 0
if (ptr->e2p_preen_msg)
message = ptr->e2p_preen_msg;
#endif
}
print_e2fsck_message(ctx, message, pctx, 1);
}
if (!(ptr->flags & PR_PREEN_OK))
preenhalt(fs);
if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
preenhalt(ctx);
if (ptr->flags & PR_MSG_ONLY)
return 1;
if (preen) {
answer = def_yn;
print_answer = 1;
} else if (ptr->flags & PR_LATCH_MASK) {
latch = PR_LATCH(ptr->flags);
if (!pr_latch[latch])
pr_latch[latch] =
ask(prompt[(int) ptr->prompt], def_yn) + 1;
if (ptr->flags & PR_FATAL)
fatal_error(0);
if (ptr->prompt == PROMPT_NONE) {
if (ptr->flags & PR_NOCOLLATE)
answer = -1;
else
print_answer = 1;
answer = pr_latch[latch] - 1;
} else
answer = ask(prompt[(int) ptr->prompt], def_yn);
if (!answer && !(ptr->flags & PR_NO_OK))
ext2fs_unmark_valid(fs);
answer = def_yn;
} else {
if (ctx->options & E2F_OPT_PREEN) {
answer = def_yn;
if (!(ptr->flags & PR_PREEN_NOMSG))
print_answer = 1;
} else if ((ptr->flags & PR_LATCH_MASK) &&
(ldesc->flags & (PRL_YES | PRL_NO))) {
if (!suppress)
print_answer = 1;
if (ldesc->flags & PRL_YES)
answer = 1;
else
answer = 0;
} else
answer = ask(ctx, prompt[(int) ptr->prompt], def_yn);
if (!answer && !(ptr->flags & PR_NO_OK))
ext2fs_unmark_valid(fs);
if (print_answer)
printf("%s.\n",
answer ? preen_msg[(int) ptr->prompt] : "IGNORED");
if (print_answer)
printf("%s.\n", answer ?
preen_msg[(int) ptr->prompt] : "IGNORED");
}
if (ptr->flags & PR_AFTER_CODE)
(void) fix_problem(ctx, ptr->second_code, pctx);
if (ptr->prompt == PROMPT_ABORT)
fatal_error(0);
return answer;
}

View File

@ -9,26 +9,43 @@
* %End-Header%
*/
typedef __u32 problem_t;
struct problem_context {
errcode_t errcode;
ino_t ino, ino2, dir;
struct ext2_inode *inode;
struct ext2_dir_entry *dirent;
blk_t blk;
blk_t blk, blk2;
int blkcount, group;
__u32 num;
const char *str;
};
struct e2fsck_problem {
int e2p_code;
problem_t e2p_code;
const char * e2p_description;
char prompt;
short flags;
problem_t second_code;
};
struct latch_descr {
int latch_code;
problem_t question;
problem_t end_message;
int flags;
};
#define PR_PREEN_OK 0x0001 /* Don't need to do preenhalt */
#define PR_NO_OK 0x0002 /* If user answers no, don't make fs invalid */
#define PR_NO_DEFAULT 0x0004 /* Default to no */
#define PR_MSG_ONLY 0x0008 /* Print message only */
#define PR_FATAL 0x0080 /* Fatal error */
#define PR_AFTER_CODE 0x0100 /* After asking the first question, */
/* ask another */
#define PR_PREEN_NOMSG 0x0200 /* Don't print a message if we're preening */
#define PR_NOCOLLATE 0x0400 /* Don't collate answers for this latch */
/*
* We define a set of "latch groups"; these are problems which are
@ -38,9 +55,23 @@ struct e2fsck_problem {
#define PR_LATCH_MASK 0x0070 /* Latch mask */
#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
/*
* Latch group descriptor flags
*/
#define PRL_YES 0x0001 /* Answer yes */
#define PRL_NO 0x0002 /* Answer no */
#define PRL_LATCHED 0x0004 /* The latch group is latched */
#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
/*
* Pre-Pass 1 errors
*/
@ -54,84 +85,234 @@ struct e2fsck_problem {
/* Inode table not in group */
#define PR_0_ITABLE_NOT_GROUP 0x000003
/* Superblock corrupt */
#define PR_0_SB_CORRUPT 0x000004
/* Filesystem size is wrong */
#define PR_0_FS_SIZE_WRONG 0x000005
/* Fragments not supported */
#define PR_0_NO_FRAGMENTS 0x000006
/* Bad blocks_per_group */
#define PR_0_BLOCKS_PER_GROUP 0x000007
/* Bad first_data_block */
#define PR_0_FIRST_DATA_BLOCK 0x000008
/* Adding UUID to filesystem */
#define PR_0_ADD_UUID 0x000009
/* Relocate hint */
#define PR_0_RELOCATE_HINT 0x00000A
/* Miscellaneous superblock corruption */
#define PR_0_MISC_CORRUPT_SUPER 0x00000B
/* Error determing physical device size of filesystem */
#define PR_0_GETSIZE_ERROR 0x00000C
/*
* Pass 1 errors
*/
/* Pass 1: Checking inodes, blocks, and sizes */
#define PR_1_PASS_HEADER 0x010000
/* Root directory is not an inode */
#define PR_1_ROOT_NO_DIR 0x010001
#define PR_1_ROOT_NO_DIR 0x010001
/* Root directory has dtime set */
#define PR_1_ROOT_DTIME 0x010002
#define PR_1_ROOT_DTIME 0x010002
/* Reserved inode has bad mode */
#define PR_1_RESERVED_BAD_MODE 0x010003
#define PR_1_RESERVED_BAD_MODE 0x010003
/* Deleted inode has zero dtime */
#define PR_1_ZERO_DTIME 0x010004
#define PR_1_ZERO_DTIME 0x010004
/* Inode in use, but dtime set */
#define PR_1_SET_DTIME 0x010005
#define PR_1_SET_DTIME 0x010005
/* Zero-length directory */
#define PR_1_ZERO_LENGTH_DIR 0x010006
#define PR_1_ZERO_LENGTH_DIR 0x010006
/* Block bitmap conflicts with some other fs block */
#define PR_1_BB_CONFLICT 0x010007
#define PR_1_BB_CONFLICT 0x010007
/* Inode bitmap conflicts with some other fs block */
#define PR_1_IB_CONFLICT 0x010008
#define PR_1_IB_CONFLICT 0x010008
/* Inode table conflicts with some other fs block */
#define PR_1_ITABLE_CONFLICT 0x010009
#define PR_1_ITABLE_CONFLICT 0x010009
/* Block bitmap is on a bad block */
#define PR_1_BB_BAD_BLOCK 0x01000A
#define PR_1_BB_BAD_BLOCK 0x01000A
/* Inode bitmap is on a bad block */
#define PR_1_IB_BAD_BLOCK 0x01000B
#define PR_1_IB_BAD_BLOCK 0x01000B
/* Inode has incorrect i_size */
#define PR_1_BAD_I_SIZE 0x01000C
#define PR_1_BAD_I_SIZE 0x01000C
/* Inode has incorrect i_blocks */
#define PR_1_BAD_I_BLOCKS 0x01000D
#define PR_1_BAD_I_BLOCKS 0x01000D
/* Illegal block number in inode */
#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
/* Block number overlaps fs metadata */
#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F
/* Inode has illegal blocks (latch question) */
#define PR_1_INODE_BLOCK_LATCH 0x010010
#define PR_1_INODE_BLOCK_LATCH 0x010010
/* Too many bad blocks in inode */
#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
/* Illegal block number in bad block inode */
#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
/* Bad block inode has illegal blocks (latch question) */
#define PR_1_INODE_BBLOCK_LATCH 0x010013
#define PR_1_INODE_BBLOCK_LATCH 0x010013
/* Duplicate or bad blocks in use! */
#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014
/* Bad block used as bad block indirect block */
#define PR_1_BBINODE_BAD_METABLOCK 0x010015
/* Inconsistency can't be fixed prompt */
#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
/* Bad primary block */
#define PR_1_BAD_PRIMARY_BLOCK 0x0100017
/* Bad primary block prompt */
#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x0100018
/* Bad primary superblock */
#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x0100019
/* Bad primary block group descriptors */
#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x010001A
/* Bad superblock in group */
#define PR_1_BAD_SUPERBLOCK 0x010001B
/* Bad block group descriptors in group */
#define PR_1_BAD_GROUP_DESCRIPTORS 0x010001C
/* Block claimed for no reason */
#define PR_1_PROGERR_CLAIMED_BLOCK 0x010001D
/* Could not allocate blocks for relocating metadata */
#define PR_1_RELOC_BLOCK_ALLOCATE 0x010001E
/* Could not allocate memory during relocation process */
#define PR_1_RELOC_MEMORY_ALLOCATE 0x010001F
/* Relocating metadata group information from X to Y */
#define PR_1_RELOC_FROM_TO 0x0100020
/* Relocating metatdata group information to X */
#define PR_1_RELOC_TO 0x0100021
/* Block read error during relocation process */
#define PR_1_RELOC_READ_ERR 0x0100022
/* Block write error during relocation process */
#define PR_1_RELOC_WRITE_ERR 0x0100023
/* Error allocating inode bitmap */
#define PR_1_ALLOCATE_IBITMAP_ERROR 0x0100024
/* Error allocating block bitmap */
#define PR_1_ALLOCATE_BBITMAP_ERROR 0x0100025
/* Error allocating icount structure */
#define PR_1_ALLOCATE_ICOUNT 0x0100026
/* Error allocating dbcount */
#define PR_1_ALLOCATE_DBCOUNT 0x0100027
/* Error while scanning inodes */
#define PR_1_ISCAN_ERROR 0x0100028
/* Error while iterating over blocks */
#define PR_1_BLOCK_ITERATE 0x0100029
/* Error while storing inode count information */
#define PR_1_ICOUNT_STORE 0x010002A
/* Error while storing directory block information */
#define PR_1_ADD_DBLOCK 0x010002B
/* Error while reading inode (for clearing) */
#define PR_1_READ_INODE 0x010002C
/*
* Pass 1b errors
*/
/* Pass 1B: Rescan for duplicate/bad blocks */
#define PR_1B_PASS_HEADER 0x011000
/* Duplicate/bad block(s) header */
#define PR_1B_DUP_BLOCK_HEADER 0x011001
/* Duplicate/bad block(s) in inode */
#define PR_1B_DUP_BLOCK 0x011002
/* Duplicate/bad block(s) end */
#define PR_1B_DUP_BLOCK_END 0x011003
/* Error while scanning inodes */
#define PR_1B_ISCAN_ERROR 0x011004
/* Error allocating inode bitmap */
#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
/* Pass 1C: Scan directories for inodes with dup blocks. */
#define PR_1C_PASS_HEADER 0x012000
/* Pass 1D: Reconciling duplicate blocks */
#define PR_1D_PASS_HEADER 0x013000
/* File has duplicate blocks */
#define PR_1B_DUP_FILE 0x011001
#define PR_1D_DUP_FILE 0x013001
/* List of files sharing duplicate blocks */
#define PR_1B_DUP_FILE_LIST 0x011002
#define PR_1D_DUP_FILE_LIST 0x013002
/* File sharing blocks with filesystem metadata */
#define PR_1B_SHARE_METADATA 0x011003
#define PR_1D_SHARE_METADATA 0x013003
/* Report of how many duplicate/bad inodes */
#define PR_1D_NUM_DUP_INODES 0x013004
/* Duplicated blocks already reassigned or cloned. */
#define PR_1D_DUP_BLOCKS_DEALT 0x013005
/* Clone duplicate/bad blocks? */
#define PR_1D_CLONE_QUESTION 0x013006
/* Delete file? */
#define PR_1D_DELETE_QUESTION 0x013007
/* Couldn't clone file (error) */
#define PR_1D_CLONE_ERROR 0x013008
/*
* Pass 2 errors
*/
/* Pass 2: Checking directory structure */
#define PR_2_PASS_HEADER 0x020000
/* Bad inode number for '.' */
#define PR_2_BAD_INODE_DOT 0x020001
@ -207,30 +388,107 @@ struct e2fsck_problem {
/* Illegal block device in inode */
#define PR_2_BAD_BLOCK_DEV 0x020019
/* Duplicate '.' entry */
#define PR_2_DUP_DOT 0x02001A
/* Duplicate '..' entry */
#define PR_2_DUP_DOT_DOT 0x02001B
/* Internal error: couldn't find dir_info */
#define PR_2_NO_DIRINFO 0x02001C
/* Final rec_len is wrong */
#define PR_2_FINAL_RECLEN 0x02001D
/* Error allocating icount structure */
#define PR_2_ALLOCATE_ICOUNT 0x02001E
/* Error iterating over directory blocks */
#define PR_2_DBLIST_ITERATE 0x02001F
/* Error reading directory block */
#define PR_2_READ_DIRBLOCK 0x020020
/* Error writing directory block */
#define PR_2_WRITE_DIRBLOCK 0x020021
/* Error allocating new directory block */
#define PR_2_ALLOC_DIRBOCK 0x020022
/* Error deallocating inode */
#define PR_2_DEALLOC_INODE 0x020023
/*
* Pass 3 errors
*/
/* Pass 3: Checking directory connectivity */
#define PR_3_PASS_HEADER 0x030000
/* Root inode not allocated */
#define PR_3_NO_ROOT_INODE 0x030001
#define PR_3_NO_ROOT_INODE 0x030001
/* No room in lost+found */
#define PR_3_EXPAND_LF_DIR 0x030002
#define PR_3_EXPAND_LF_DIR 0x030002
/* Unconnected directory inode */
#define PR_3_UNCONNECTED_DIR 0x030003
#define PR_3_UNCONNECTED_DIR 0x030003
/* /lost+found not found */
#define PR_3_NO_LF_DIR 0x030004
#define PR_3_NO_LF_DIR 0x030004
/* .. entry is incorrect */
#define PR_3_BAD_DOT_DOT 0x030005
#define PR_3_BAD_DOT_DOT 0x030005
/* Bad or non-existent /lost+found. Cannot reconnect */
#define PR_3_NO_LPF 0x030006
/* Could not expand /lost+found */
#define PR_3_CANT_EXPAND_LPF 0x030007
/* Could not reconnect inode */
#define PR_3_CANT_RECONNECT 0x030008
/* Error while trying to find /lost+found */
#define PR_3_ERR_FIND_LPF 0x030009
/* Error in ext2fs_new_block while creating /lost+found */
#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A
/* Error in ext2fs_new_inode while creating /lost+found */
#define PR_3_ERR_LPF_NEW_INODE 0x03000B
/* Error in ext2fs_new_dir_block while creating /lost+found */
#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C
/* Error while writing directory block for /lost+found */
#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D
/* Error while adjusting inode count */
#define PR_3_ADJUST_INODE 0x03000E
/* Couldn't fix parent directory -- error */
#define PR_3_FIX_PARENT_ERR 0x03000F
/* Couldn't fix parent directory -- couldn't find it */
#define PR_3_FIX_PARENT_NOFIND 0x030010
/* Error allocating inode bitmap */
#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011
/* Error creating root directory */
#define PR_3_CREATE_ROOT_ERROR 0x030012
/* Error creating lost and found directory */
#define PR_3_CREATE_LPF_ERROR 0x030013
/*
* Pass 4 errors
*/
/* Pass 4: Checking reference counts */
#define PR_4_PASS_HEADER 0x040000
/* Unattached zero-length inode */
#define PR_4_ZERO_LEN_INODE 0x040001
@ -240,19 +498,77 @@ struct e2fsck_problem {
/* Inode ref count wrong */
#define PR_4_BAD_REF_COUNT 0x040003
/* Inconsistent inode count information cached */
#define PR_4_INCONSISTENT_COUNT 0x040004
/*
* Pass 5 errors
*/
/* Pass 5: Checking group summary information */
#define PR_5_PASS_HEADER 0x050000
/* Padding at end of inode bitmap is not set. */
#define PR_5_INODE_BMAP_PADDING 0x050001
/* Padding at end of block bitmap is not set. */
#define PR_5_BLOCK_BMAP_PADDING 0x050002
/* Block bitmap differences header */
#define PR_5_BLOCK_BITMAP_HEADER 0x050003
/* Block not used, but marked in bitmap */
#define PR_5_UNUSED_BLOCK 0x050004
/* Block used, but not marked used in bitmap */
#define PR_5_BLOCK_USED 0x050005
/* Block bitmap differences end */
#define PR_5_BLOCK_BITMAP_END 0x050006
/* Inode bitmap differences header */
#define PR_5_INODE_BITMAP_HEADER 0x050007
/* Inode not used, but marked in bitmap */
#define PR_5_UNUSED_INODE 0x050008
/* Inode used, but not marked used in bitmap */
#define PR_5_INODE_USED 0x050009
/* Inode bitmap differences end */
#define PR_5_INODE_BITMAP_END 0x05000A
/* Free inodes count for group wrong */
#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B
/* Directories count for group wrong */
#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C
/* Free inodes count wrong */
#define PR_5_FREE_INODE_COUNT 0x05000D
/* Free blocks count for group wrong */
#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E
/* Free blocks count wrong */
#define PR_5_FREE_BLOCK_COUNT 0x05000F
/* Programming error: bitmap endpoints don't match */
#define PR_5_BMAP_ENDPOINTS 0x050010
/* Internal error: fudging end of bitmap */
#define PR_5_FUDGE_BITMAP_ERROR 0x050011
/*
* Function declarations
*/
int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx);
void reset_problem_latch(int mask);
void suppress_latch_group(int mask, int value);
int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
int end_problem_latch(e2fsck_t ctx, int mask);
int set_latch_flags(int mask, int setflags, int clearflags);
int get_latch_flags(int mask, int *value);
void clear_problem_context(struct problem_context *ctx);
/* message.c */
void print_e2fsck_message(ext2_filsys fs, const char *msg,
struct problem_context *ctx, int first);
void print_e2fsck_message(e2fsck_t ctx, const char *msg,
struct problem_context *pctx, int first);

View File

@ -72,7 +72,7 @@ static __inline__ float timeval_subtract(struct timeval *tv1,
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
void print_resource_track(struct resource_track *track)
static void print_resource_track(struct resource_track *track)
{
struct rusage r;
struct timeval time_end;

204
e2fsck/super.c Normal file
View File

@ -0,0 +1,204 @@
/*
* e2fsck.c - superblock checks
*
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <time.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <unistd.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <sys/ioctl.h>
#include <malloc.h>
#include "uuid/uuid.h"
#include "e2fsck.h"
#include "problem.h"
#include "../version.h"
#define MIN_CHECK 1
#define MAX_CHECK 2
static void check_super_value(e2fsck_t ctx, const char *descr,
unsigned long value, int flags,
unsigned long min, unsigned long max)
{
struct problem_context pctx;
if (((flags & MIN_CHECK) && (value < min)) ||
((flags & MAX_CHECK) && (value > max))) {
clear_problem_context(&pctx);
pctx.num = value;
pctx.str = descr;
fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
fatal_error(0); /* never get here! */
}
}
void check_super_block(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
blk_t first_block, last_block;
struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super;
blk_t blocks_per_group = fs->super->s_blocks_per_group;
int i;
blk_t should_be;
struct problem_context pctx;
ctx->invalid_inode_bitmap_flag = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_inode_bitmap");
ctx->invalid_block_bitmap_flag = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_block_bitmap");
ctx->invalid_inode_table_flag = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_inode_table");
clear_problem_context(&pctx);
/*
* Verify the super block constants...
*/
check_super_value(ctx, "inodes_count", s->s_inodes_count,
MIN_CHECK, 1, 0);
check_super_value(ctx, "blocks_count", s->s_blocks_count,
MIN_CHECK, 1, 0);
check_super_value(ctx, "first_data_block", s->s_first_data_block,
MAX_CHECK, 0, s->s_blocks_count);
check_super_value(ctx, "log_frag_size", s->s_log_frag_size,
MAX_CHECK, 0, 2);
check_super_value(ctx, "log_block_size", s->s_log_block_size,
MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
2);
check_super_value(ctx, "frags_per_group", s->s_frags_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value(ctx, "blocks_per_group", s->s_blocks_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value(ctx, "inodes_per_group", s->s_inodes_per_group,
MIN_CHECK, 1, 0);
check_super_value(ctx, "r_blocks_count", s->s_r_blocks_count,
MAX_CHECK, 0, s->s_blocks_count);
pctx.errcode = ext2fs_get_device_size(ctx->filesystem_name,
EXT2_BLOCK_SIZE(s),
&should_be);
if (pctx.errcode) {
fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
fatal_error(0);
}
if (should_be < s->s_blocks_count) {
pctx.blk = s->s_blocks_count;
pctx.blk2 = should_be;
if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx))
fatal_error(0);
}
if (s->s_log_block_size != s->s_log_frag_size) {
pctx.blk = EXT2_BLOCK_SIZE(s);
pctx.blk2 = EXT2_FRAG_SIZE(s);
fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
fatal_error(0);
}
should_be = s->s_frags_per_group /
(s->s_log_block_size - s->s_log_frag_size + 1);
if (s->s_blocks_per_group != should_be) {
pctx.blk = s->s_blocks_per_group;
pctx.blk2 = should_be;
fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
fatal_error(0);
}
should_be = (s->s_log_block_size == 0) ? 1 : 0;
if (s->s_first_data_block != should_be) {
pctx.blk = s->s_first_data_block;
pctx.blk2 = should_be;
fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
fatal_error(0);
}
/*
* Verify the group descriptors....
*/
first_block = fs->super->s_first_data_block;
last_block = first_block + blocks_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
pctx.group = i;
if (i == fs->group_desc_count - 1)
last_block = fs->super->s_blocks_count;
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
pctx.blk = fs->group_desc[i].bg_block_bitmap;
if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_block_bitmap = 0;
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_bitmap = 0;
ctx->invalid_inode_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
}
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
pctx.blk = fs->group_desc[i].bg_inode_table;
if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_table = 0;
ctx->invalid_inode_table_flag[i]++;
ctx->invalid_bitmaps++;
}
}
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
}
/*
* If we have invalid bitmaps, set the error state of the
* filesystem.
*/
if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
}
/*
* If the UUID field isn't assigned, assign it.
*/
if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(s->s_uuid)) {
clear_problem_context(&pctx);
if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
uuid_generate(s->s_uuid);
ext2fs_mark_super_dirty(fs);
}
}
return;
}

View File

@ -102,8 +102,9 @@ static void swap_inode_blocks(ext2_filsys fs, ino_t ino, char *block_buf,
}
}
static void swap_inodes(ext2_filsys fs)
static void swap_inodes(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
int i, group;
ino_t ino = 1;
char *buf, *block_buf;
@ -135,8 +136,8 @@ static void swap_inodes(ext2_filsys fs)
inode = (struct ext2_inode *) buf;
for (i=0; i < fs->super->s_inodes_per_group;
i++, ino++, inode++) {
stashed_ino = ino;
stashed_inode = inode;
ctx->stashed_ino = ino;
ctx->stashed_inode = inode;
if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
ext2fs_swap_inode(fs, inode, inode, 0);
@ -173,13 +174,14 @@ static void swap_inodes(ext2_filsys fs)
fs->get_blocks = 0;
}
void swap_filesys(ext2_filsys fs)
void swap_filesys(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
struct resource_track rtrack;
init_resource_track(&rtrack);
if (!preen)
if (!(ctx->options & E2F_OPT_PREEN))
printf("Pass 0: Doing byte-swap of filesystem\n");
#ifdef MTRACE
@ -190,7 +192,7 @@ void swap_filesys(ext2_filsys fs)
fprintf(stderr, "%s: the filesystem must be freshly "
"checked using fsck\n"
"and not mounted before trying to "
"byte-swap it.\n", device_name);
"byte-swap it.\n", ctx->device_name);
fatal_error(0);
}
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
@ -201,17 +203,15 @@ void swap_filesys(ext2_filsys fs)
fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
}
swap_inodes(fs);
swap_inodes(ctx);
if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
fs->flags |= EXT2_FLAG_SWAP_BYTES;
fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
EXT2_FLAG_SWAP_BYTES_WRITE);
ext2fs_flush(fs);
if (tflag > 1) {
printf("Byte swap: ");
print_resource_track(&rtrack);
}
if (ctx->options & E2F_OPT_TIME2)
print_resource_track("Byte swap", &rtrack);
}

651
e2fsck/unix.c Normal file
View File

@ -0,0 +1,651 @@
/*
* unix.c - The unix-specific code for e2fsck
*
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <time.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <unistd.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <sys/ioctl.h>
#include <malloc.h>
#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
#include "../version.h"
extern int isatty(int);
/* Command line options */
static int blocksize = 0;
static int swapfs = 0;
static int normalize_swapfs = 0;
static int cflag = 0; /* check disk */
static int show_version_only = 0;
static int force = 0;
static int verbose = 0;
static int replace_bad_blocks = 0;
static char *bad_blocks_file = 0;
static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0};
static int root_filesystem = 0;
static int read_only_root = 0;
int restart_e2fsck = 0;
static void usage(e2fsck_t ctx)
{
fprintf(stderr,
"Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n"
"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
"\t\t[-l|-L bad_blocks_file] device\n", ctx->program_name);
exit(FSCK_USAGE);
}
static void show_stats(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
int inodes, inodes_used, blocks, blocks_used;
int dir_links;
int num_files, num_links;
int frag_percent;
dir_links = 2 * ctx->fs_directory_count - 1;
num_files = ctx->fs_total_count - dir_links;
num_links = ctx->fs_links_count - dir_links;
inodes = fs->super->s_inodes_count;
inodes_used = (fs->super->s_inodes_count -
fs->super->s_free_inodes_count);
blocks = fs->super->s_blocks_count;
blocks_used = (fs->super->s_blocks_count -
fs->super->s_free_blocks_count);
frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
frag_percent = (frag_percent + 5) / 10;
if (!verbose) {
printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
ctx->device_name, inodes_used, inodes,
frag_percent / 10, frag_percent % 10,
blocks_used, blocks);
return;
}
printf ("\n%8d inode%s used (%d%%)\n", inodes_used,
(inodes_used != 1) ? "s" : "",
100 * inodes_used / inodes);
printf ("%8d non-contiguous inodes (%0d.%d%%)\n",
ctx->fs_fragmented, frag_percent / 10, frag_percent % 10);
printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n",
ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
printf ("%8d block%s used (%d%%)\n"
"%8d bad block%s\n", blocks_used,
(blocks_used != 1) ? "s" : "",
100 * blocks_used / blocks, ctx->fs_badblocks_count,
ctx->fs_badblocks_count != 1 ? "s" : "");
printf ("\n%8d regular file%s\n"
"%8d director%s\n"
"%8d character device file%s\n"
"%8d block device file%s\n"
"%8d fifo%s\n"
"%8d link%s\n"
"%8d symbolic link%s (%d fast symbolic link%s)\n"
"%8d socket%s\n"
"--------\n"
"%8d file%s\n",
ctx->fs_regular_count,
(ctx->fs_regular_count != 1) ? "s" : "",
ctx->fs_directory_count,
(ctx->fs_directory_count != 1) ? "ies" : "y",
ctx->fs_chardev_count,
(ctx->fs_chardev_count != 1) ? "s" : "",
ctx->fs_blockdev_count,
(ctx->fs_blockdev_count != 1) ? "s" : "",
ctx->fs_fifo_count,
(ctx->fs_fifo_count != 1) ? "s" : "",
ctx->fs_links_count - dir_links,
((ctx->fs_links_count - dir_links) != 1) ? "s" : "",
ctx->fs_symlinks_count,
(ctx->fs_symlinks_count != 1) ? "s" : "",
ctx->fs_fast_symlinks_count,
(ctx->fs_fast_symlinks_count != 1) ? "s" : "",
ctx->fs_sockets_count, (ctx->fs_sockets_count != 1) ? "s" : "",
ctx->fs_total_count - dir_links,
((ctx->fs_total_count - dir_links) != 1) ? "s" : "");
}
static void check_mount(e2fsck_t ctx)
{
errcode_t retval;
int mount_flags, cont, fd;
retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
if (retval) {
com_err("ext2fs_check_if_mount", retval,
"while determining whether %s is mounted.",
ctx->filesystem_name);
return;
}
if (!(mount_flags & EXT2_MF_MOUNTED))
return;
#if (defined(__linux__) && defined(HAVE_MNTENT_H))
/*
* If the root is mounted read-only, then /etc/mtab is
* probably not correct; so we won't issue a warning based on
* it.
*/
fd = open(MOUNTED, O_RDWR);
if (fd < 0) {
if (errno == EROFS)
return;
} else
close(fd);
#endif
if (ctx->options & E2F_OPT_READONLY) {
printf("Warning! %s is mounted.\n", ctx->device_name);
return;
}
printf("%s is mounted.\n\n", ctx->device_name);
printf("\a\a\a\aWARNING!!! Running e2fsck on a mounted filesystem "
"may cause\nSEVERE filesystem damage.\a\a\a\n\n");
if (isatty (0) && isatty (1))
cont = ask_yn("Do you really want to continue", -1);
else
cont = 0;
if (!cont) {
printf ("check aborted.\n");
exit (0);
}
return;
}
static void sync_disks(NOARGS)
{
sync();
sync();
sleep(1);
sync();
}
/*
* This routine checks to see if a filesystem can be skipped; if so,
* it will exit with E2FSCK_OK. Under some conditions it will print a
* message explaining why a check is being forced.
*/
static void check_if_skip(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
const char *reason = NULL;
if (force || bad_blocks_file || cflag || swapfs)
return;
if (fs->super->s_state & EXT2_ERROR_FS)
reason = "contains a file system with errors";
else if (fs->super->s_mnt_count >=
(unsigned) fs->super->s_max_mnt_count)
reason = "has reached maximal mount count";
else if (fs->super->s_checkinterval &&
time(0) >= (fs->super->s_lastcheck +
fs->super->s_checkinterval))
reason = "has gone too long without being checked";
else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
reason = "was not cleanly unmounted";
if (reason) {
printf("%s %s, check forced.\n", ctx->device_name, reason);
return;
}
printf("%s: clean, %d/%d files, %d/%d blocks\n", ctx->device_name,
fs->super->s_inodes_count - fs->super->s_free_inodes_count,
fs->super->s_inodes_count,
fs->super->s_blocks_count - fs->super->s_free_blocks_count,
fs->super->s_blocks_count);
ext2fs_close(fs);
exit(FSCK_OK);
}
#define PATH_SET "PATH=/sbin"
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
{
int flush = 0;
char c;
#ifdef MTRACE
extern void *mallwatch;
#endif
char *oldpath = getenv("PATH");
e2fsck_t ctx;
errcode_t retval;
retval = e2fsck_allocate_context(&ctx);
if (retval)
return retval;
*ret_ctx = ctx;
/* Update our PATH to include /sbin */
if (oldpath) {
char *newpath;
newpath = malloc(sizeof (PATH_SET) + 1 + strlen (oldpath));
if (!newpath)
fatal_error("Couldn't malloc() newpath");
strcpy (newpath, PATH_SET);
strcat (newpath, ":");
strcat (newpath, oldpath);
putenv (newpath);
} else
putenv (PATH_SET);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
initialize_ext2_error_table();
if (argc && *argv)
ctx->program_name = *argv;
else
ctx->program_name = "e2fsck";
while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF)
switch (c) {
case 'p':
case 'a':
ctx->options |= E2F_OPT_PREEN;
ctx->options &= ~(E2F_OPT_YES|E2F_OPT_NO);
break;
case 'n':
ctx->options |= E2F_OPT_NO;
ctx->options &= ~(E2F_OPT_YES|E2F_OPT_PREEN);
break;
case 'y':
ctx->options |= E2F_OPT_YES;
ctx->options &= ~(E2F_OPT_PREEN|E2F_OPT_NO);
break;
case 't':
if (ctx->options & E2F_OPT_TIME)
ctx->options |= E2F_OPT_TIME2;
else
ctx->options |= E2F_OPT_TIME;
break;
case 'c':
cflag++;
ctx->options |= E2F_OPT_CHECKBLOCKS;
break;
case 'r':
/* What we do by default, anyway! */
break;
case 'b':
ctx->use_superblock = atoi(optarg);
break;
case 'B':
blocksize = atoi(optarg);
break;
case 'I':
ctx->inode_buffer_blocks = atoi(optarg);
break;
case 'P':
ctx->process_inode_size = atoi(optarg);
break;
case 'L':
replace_bad_blocks++;
case 'l':
bad_blocks_file = malloc(strlen(optarg)+1);
if (!bad_blocks_file)
fatal_error("Couldn't malloc bad_blocks_file");
strcpy(bad_blocks_file, optarg);
break;
case 'd':
ctx->options |= E2F_OPT_DEBUG;
break;
case 'f':
force = 1;
break;
case 'F':
#ifdef BLKFLSBUF
flush = 1;
#else
fatal_error ("-F not supported");
#endif
break;
case 'v':
verbose = 1;
break;
case 'V':
show_version_only = 1;
break;
#ifdef MTRACE
case 'M':
mallwatch = (void *) strtol(optarg, NULL, 0);
break;
#endif
case 'N':
ctx->device_name = optarg;
break;
case 's':
normalize_swapfs = 1;
case 'S':
swapfs = 1;
break;
default:
usage(ctx);
}
if (show_version_only)
return 0;
if (optind != argc - 1)
usage(ctx);
if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
!cflag && !swapfs)
ctx->options |= E2F_OPT_READONLY;
ctx->filesystem_name = argv[optind];
if (ctx->device_name == 0)
ctx->device_name = ctx->filesystem_name;
if (flush) {
#ifdef BLKFLSBUF
int fd = open(ctx->filesystem_name, O_RDONLY, 0);
if (fd < 0) {
com_err("open", errno, "while opening %s for flushing",
ctx->filesystem_name);
exit(FSCK_ERROR);
}
if (ioctl(fd, BLKFLSBUF, 0) < 0) {
com_err("BLKFLSBUF", errno, "while trying to flush %s",
ctx->filesystem_name);
exit(FSCK_ERROR);
}
close(fd);
#else
fatal_error ("BLKFLSBUF not supported");
#endif /* BLKFLSBUF */
}
if (swapfs) {
if (cflag || bad_blocks_file) {
fprintf(stderr, "Incompatible options not "
"allowed when byte-swapping.\n");
fatal_error(0);
}
}
return 0;
}
static const char *my_ver_string = E2FSPROGS_VERSION;
static const char *my_ver_date = E2FSPROGS_DATE;
int main (int argc, char *argv[])
{
errcode_t retval = 0;
int exit_value = FSCK_OK;
int i;
ext2_filsys fs = 0;
io_manager io_ptr;
struct ext2fs_sb *s;
const char *lib_ver_date;
int my_ver, lib_ver;
e2fsck_t ctx;
struct problem_context pctx;
int flags;
clear_problem_context(&pctx);
#ifdef MTRACE
mtrace();
#endif
#ifdef MCHECK
mcheck(0);
#endif
my_ver = ext2fs_parse_version_string(my_ver_string);
lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
if (my_ver > lib_ver) {
fprintf( stderr, "Error: ext2fs library version "
"out of date!\n");
show_version_only++;
}
retval = PRS(argc, argv, &ctx);
if (retval) {
com_err("e2fsck", retval,
"while trying to initialize program");
exit(1);
}
init_resource_track(&ctx->global_rtrack);
if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
my_ver_string, my_ver_date, EXT2FS_VERSION,
EXT2FS_DATE);
if (show_version_only) {
fprintf(stderr, "\tUsing %s, %s\n",
error_message(EXT2_ET_BASE), lib_ver_date);
exit(0);
}
check_mount(ctx);
if (!(ctx->options & E2F_OPT_PREEN) &&
!(ctx->options & E2F_OPT_NO) &&
!(ctx->options & E2F_OPT_YES)) {
if (!isatty (0) || !isatty (1))
die ("need terminal for interactive repairs");
}
ctx->superblock = ctx->use_superblock;
restart:
#if 1
io_ptr = unix_io_manager;
#else
io_ptr = test_io_manager;
test_io_backing_manager = unix_io_manager;
#endif
sync_disks();
flags = (ctx->options & E2F_OPT_READONLY) ? 0 : EXT2_FLAG_RW;
if (ctx->superblock && blocksize) {
retval = ext2fs_open(ctx->filesystem_name, flags,
ctx->superblock, blocksize, io_ptr, &fs);
} else if (ctx->superblock) {
for (i=0; possible_block_sizes[i]; i++) {
retval = ext2fs_open(ctx->filesystem_name, flags,
ctx->superblock,
possible_block_sizes[i],
io_ptr, &fs);
if (!retval)
break;
}
} else
retval = ext2fs_open(ctx->filesystem_name, flags,
0, 0, io_ptr, &fs);
if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
((retval == EXT2_ET_BAD_MAGIC) ||
((retval == 0) && ext2fs_check_desc(fs)))) {
if (!fs || (fs->group_desc_count > 1)) {
printf("%s trying backup blocks...\n",
retval ? "Couldn't find ext2 superblock," :
"Group descriptors look bad...");
ctx->superblock = get_backup_sb(fs);
if (fs)
ext2fs_close(fs);
goto restart;
}
}
if (retval) {
com_err(ctx->program_name, retval, "while trying to open %s",
ctx->filesystem_name);
if (retval == EXT2_ET_REV_TOO_HIGH)
printf ("Get a newer version of e2fsck!\n");
else if (retval == EXT2_ET_SHORT_READ)
printf ("Could this be a zero-length partition?\n");
else if ((retval == EPERM) || (retval == EACCES))
printf("You must have %s access to the "
"filesystem or be root\n",
(ctx->options & E2F_OPT_READONLY) ?
"r/o" : "r/w");
else if (retval == ENXIO)
printf("Possibly non-existent or swap device?\n");
else
fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
fatal_error(0);
}
ctx->fs = fs;
fs->private = ctx;
#ifdef EXT2_CURRENT_REV
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
"while trying to open %s",
ctx->filesystem_name);
goto get_newer;
}
#endif
/*
* Check for compatibility with the feature sets. We need to
* be more stringent than ext2fs_open().
*/
s = (struct ext2fs_sb *) fs->super;
if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
(s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
"(%s)", ctx->filesystem_name);
get_newer:
printf ("Get a newer version of e2fsck!\n");
fatal_error(0);
}
if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
"(%s)", ctx->filesystem_name);
goto get_newer;
}
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
* superblock as dirty, so it can be written out.
*/
if (ctx->superblock &&
!(ctx->options & E2F_OPT_READONLY))
ext2fs_mark_super_dirty(fs);
/*
* Don't overwrite the backup superblock and block
* descriptors, until we're sure the filesystem is OK....
*/
fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
ehandler_init(fs->io);
if (ctx->superblock)
set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
check_super_block(ctx);
check_if_skip(ctx);
if (bad_blocks_file)
read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
else if (cflag)
test_disk(ctx);
if (normalize_swapfs) {
if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
ext2fs_native_flag()) {
fprintf(stderr, "%s: Filesystem byte order "
"already normalized.\n", ctx->device_name);
fatal_error(0);
}
}
if (swapfs)
swap_filesys(ctx);
/*
* Mark the system as valid, 'til proven otherwise
*/
ext2fs_mark_valid(fs);
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
if (retval) {
com_err(ctx->program_name, retval,
"while reading bad blocks inode");
preenhalt(ctx);
printf("This doesn't bode well, but we'll try to go on...\n");
}
pass1(ctx);
if (restart_e2fsck) {
ext2fs_close(fs);
printf("Restarting e2fsck from the beginning...\n");
restart_e2fsck = 0;
retval = e2fsck_reset_context(ctx);
if (retval) {
com_err(ctx->program_name, retval,
"while resetting context");
exit(1);
}
goto restart;
}
pass2(ctx);
pass3(ctx);
pass4(ctx);
pass5(ctx);
#ifdef MTRACE
mtrace_print("Cleanup");
#endif
if (ext2fs_test_changed(fs)) {
exit_value = FSCK_NONDESTRUCT;
if (!(ctx->options & E2F_OPT_PREEN))
printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
ctx->device_name);
if (root_filesystem && !read_only_root) {
printf("%s: ***** REBOOT LINUX *****\n",
ctx->device_name);
exit_value = FSCK_REBOOT;
}
}
if (ext2fs_test_valid(fs))
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
else
exit_value = FSCK_UNCORRECTED;
if (!(ctx->options & E2F_OPT_READONLY)) {
if (ext2fs_test_valid(fs)) {
if (!(fs->super->s_state & EXT2_VALID_FS))
exit_value = FSCK_NONDESTRUCT;
fs->super->s_state = EXT2_VALID_FS;
} else
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_mnt_count = 0;
fs->super->s_lastcheck = time(NULL);
ext2fs_mark_super_dirty(fs);
}
show_stats(ctx);
write_bitmaps(ctx);
ext2fs_close(fs);
sync_disks();
if (ctx->options & E2F_OPT_TIME)
print_resource_track(NULL, &ctx->global_rtrack);
e2fsck_free_context(ctx);
return exit_value;
}

View File

@ -20,12 +20,10 @@
#include <sys/time.h>
#include <sys/resource.h>
const char * fix_msg[2] = { "IGNORED", "FIXED" };
void fatal_error (const char *msg)
{
if (msg)
fprintf (stderr, "%s: %s\n", program_name, msg);
fprintf (stderr, "e2fsck: %s\n", msg);
exit(FSCK_ERROR);
}
@ -46,7 +44,6 @@ void *allocate_memory(int size, const char *description)
return ret;
}
int ask_yn(const char * string, int def)
{
int c;
@ -91,31 +88,32 @@ int ask_yn(const char * string, int def)
return def;
}
int ask (const char * string, int def)
int ask (e2fsck_t ctx, const char * string, int def)
{
if (nflag) {
if (ctx->options & E2F_OPT_NO) {
printf ("%s? no\n\n", string);
return 0;
}
if (yflag) {
if (ctx->options & E2F_OPT_YES) {
printf ("%s? yes\n\n", string);
return 1;
}
if (preen) {
if (ctx->options & E2F_OPT_PREEN) {
printf ("%s? %s\n\n", string, def ? "yes" : "no");
return def;
}
return ask_yn(string, def);
}
void read_bitmaps(ext2_filsys fs)
void read_bitmaps(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
if (invalid_bitmaps) {
com_err(program_name, 0,
if (ctx->invalid_bitmaps) {
com_err(ctx->program_name, 0,
"read_bitmaps: illegal bitmap block(s) for %s",
device_name);
ctx->device_name);
fatal_error(0);
}
@ -123,15 +121,16 @@ void read_bitmaps(ext2_filsys fs)
retval = ext2fs_read_bitmaps(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
com_err(ctx->program_name, retval,
"while retrying to read bitmaps for %s",
device_name);
ctx->device_name);
fatal_error(0);
}
}
void write_bitmaps(ext2_filsys fs)
void write_bitmaps(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
if (ext2fs_test_bb_dirty(fs)) {
@ -139,9 +138,9 @@ void write_bitmaps(ext2_filsys fs)
retval = ext2fs_write_block_bitmap(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
com_err(ctx->program_name, retval,
"while retrying to write block bitmaps for %s",
device_name);
ctx->device_name);
fatal_error(0);
}
}
@ -151,21 +150,23 @@ void write_bitmaps(ext2_filsys fs)
retval = ext2fs_write_inode_bitmap(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
com_err(ctx->program_name, retval,
"while retrying to write inode bitmaps for %s",
device_name);
ctx->device_name);
fatal_error(0);
}
}
}
void preenhalt(ext2_filsys fs)
void preenhalt(e2fsck_t ctx)
{
if (!preen)
ext2_filsys fs = ctx->fs;
if (!(ctx->options & E2F_OPT_PREEN))
return;
fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; "
"RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n",
device_name);
ctx->device_name);
if (fs != NULL) {
fs->super->s_state |= EXT2_ERROR_FS;
ext2fs_mark_super_dirty(fs);
@ -183,6 +184,9 @@ void init_resource_track(struct resource_track *track)
track->brk_start = sbrk(0);
gettimeofday(&track->time_start, 0);
#ifdef HAVE_GETRUSAGE
#ifdef solaris
memcpy(&r, 0, sizeof(struct rusage));
#endif
getrusage(RUSAGE_SELF, &r);
track->user_start = r.ru_utime;
track->system_start = r.ru_stime;
@ -205,7 +209,7 @@ static _INLINE_ float timeval_subtract(struct timeval *tv1,
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
void print_resource_track(struct resource_track *track)
void print_resource_track(const char *desc, struct resource_track *track)
{
#ifdef HAVE_GETRUSAGE
struct rusage r;
@ -213,6 +217,10 @@ void print_resource_track(struct resource_track *track)
struct timeval time_end;
gettimeofday(&time_end, 0);
if (desc)
printf("%s :", desc);
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_SELF, &r);
@ -265,4 +273,10 @@ void mtrace_print(char *mesg)
}
#endif
blk_t get_backup_sb(ext2_filsys fs)
{
if (!fs || !fs->super)
return 8193;
return fs->super->s_blocks_per_group + 1;
}

View File

@ -13,11 +13,15 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: +50
Fix? yes
Free blocks count wrong for group #0 (78, counted=77).
Fix? yes
Free blocks count wrong (78, counted=77).
Fix? yes
Block bitmap differences: +50. FIXED
Free blocks count wrong for group 0 (78, counted=77). FIXED
Free blocks count wrong (78, counted=77). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 23/100 blocks

View File

@ -36,12 +36,18 @@ Pass 4: Checking reference counts
Inode 12 ref count is 1, should be 2. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -22
Fix? yes
Free blocks count wrong (74, counted=75).
Fix? yes
Inode bitmap differences: -13
Fix? yes
Directories count wrong for group #0 (5, counted=4).
Fix? yes
Block bitmap differences: -22. FIXED
Free blocks count wrong (74, counted=75). FIXED
Inode bitmap differences: -13. FIXED
Directories count wrong for group #0 (5, counted=4). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 14/32 files (0.0% non-contiguous), 25/100 blocks

View File

@ -47,10 +47,12 @@ Fix? yes
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (70, counted=71).
Fix? yes
Free blocks count wrong (70, counted=71).
Fix? yes
Free blocks count wrong for group 0 (70, counted=71). FIXED
Free blocks count wrong (70, counted=71). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 18/32 files (0.0% non-contiguous), 29/100 blocks

View File

@ -20,13 +20,21 @@ Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -25
Fix? yes
Free blocks count wrong for group #0 (76, counted=77).
Fix? yes
Free blocks count wrong (76, counted=77).
Fix? yes
Free inodes count wrong for group #0 (17, counted=20).
Fix? yes
Free inodes count wrong (17, counted=20).
Fix? yes
Block bitmap differences: -25. FIXED
Free blocks count wrong for group 0 (76, counted=77). FIXED
Free blocks count wrong (76, counted=77). FIXED
Free inodes count wrong for group #0 (17, counted=20). FIXED
Free inodes count wrong (17, counted=20). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (0.0% non-contiguous), 23/100 blocks

View File

@ -4,18 +4,20 @@ Pass 1: Checking inodes, blocks, and sizes
The primary superblock (1) is on the bad block list.
If the block is really bad, the filesystem can not be fixed.
You can clear the this block from the bad block list
and hope that block is really OK, but there are no guarantees.
You can clear the this block (and hope for the best) from the
bad block list and hope that block is really OK, but there are no
guarantees.
Clear (and hope for the best)? yes
Clear? yes
Block 2 in the primary group descriptors is on the bad block list
If the block is really bad, the filesystem can not be fixed.
You can clear the this block from the bad block list
and hope that block is really OK, but there are no guarantees.
You can clear the this block (and hope for the best) from the
bad block list and hope that block is really OK, but there are no
guarantees.
Clear (and hope for the best)? yes
Clear? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity

View File

@ -23,13 +23,21 @@ Connect to /lost+found? yes
Inode 12 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (77, counted=76).
Fix? yes
Free blocks count wrong (77, counted=76).
Fix? yes
Free inodes count wrong for group #0 (20, counted=19).
Fix? yes
Directories count wrong for group #0 (2, counted=3).
Fix? yes
Free inodes count wrong (20, counted=19).
Fix? yes
Free blocks count wrong for group 0 (77, counted=76). FIXED
Free blocks count wrong (77, counted=76). FIXED
Free inodes count wrong for group #0 (20, counted=19). FIXED
Directories count wrong for group #0 (2, counted=3). FIXED
Free inodes count wrong (20, counted=19). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 13/32 files (0.0% non-contiguous), 24/100 blocks

View File

@ -16,15 +16,27 @@ Pass 4: Checking reference counts
Inode 2 ref count is 3, should be 2. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -11 -12 -13 -14 -15 -16 -17 -18 -19 -20
Fix? yes
Free blocks count wrong for group #0 (78, counted=88).
Fix? yes
Free blocks count wrong (78, counted=88).
Fix? yes
Inode bitmap differences: +12 +13 +14 +15 +16 +25 +26 +27 +28 +29 +30 +31 +32
Fix? yes
Free inodes count wrong for group #0 (21, counted=8).
Fix? yes
Directories count wrong for group #0 (2, counted=1).
Fix? yes
Free inodes count wrong (21, counted=8).
Fix? yes
Block bitmap differences: -11 -12 -13 -14 -15 -16 -17 -18 -19 -20. FIXED
Free blocks count wrong for group 0 (78, counted=88). FIXED
Free blocks count wrong (78, counted=88). FIXED
Inode bitmap differences: +12 +13 +14 +15 +16 +25 +26 +27 +28 +29 +30 +31 +32. FIXED
Free inodes count wrong for group #0 (21, counted=8). FIXED
Directories count wrong for group #0 (2, counted=1). FIXED
Free inodes count wrong (21, counted=8). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 24/32 files (0.0% non-contiguous), 12/100 blocks

View File

@ -18,28 +18,29 @@ File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
File /lost+found (inode #11, mod time Sun Jan 2 08:28:40 1994)
has 12 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
File / (inode #2, mod time Sun Jan 2 08:29:13 1994)
has 1 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: +43
Fix? yes
Free blocks count wrong for group #0 (57, counted=41).
Fix? yes
Free blocks count wrong (57, counted=41).
Fix? yes
Block bitmap differences: +43. FIXED
Free blocks count wrong for group 0 (57, counted=41). FIXED
Free blocks count wrong (57, counted=41). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (0.0% non-contiguous), 59/100 blocks

View File

@ -27,14 +27,24 @@ Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -83
Fix? yes
Free blocks count wrong for group #0 (1962, counted=1965).
Fix? yes
Free blocks count wrong (1962, counted=1965).
Fix? yes
Inode bitmap differences: +41 +42 +43 +44 +45 +46 +47 +48
Fix? yes
Free inodes count wrong for group #0 (485, counted=477).
Fix? yes
Free inodes count wrong (485, counted=477).
Fix? yes
Block bitmap differences: -83. FIXED
Free blocks count wrong for group 0 (1962, counted=1965). FIXED
Free blocks count wrong (1962, counted=1965). FIXED
Inode bitmap differences: +41 +42 +43 +44 +45 +46 +47 +48. FIXED
Free inodes count wrong for group #0 (485, counted=477). FIXED
Free inodes count wrong (485, counted=477). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 35/512 files (0.0% non-contiguous), 83/2048 blocks

View File

@ -5,10 +5,12 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: +12 -20 +41 -50
Fix? yes
Inode bitmap differences: +11 -15
Fix? yes
Block bitmap differences: +12 -20 +41 -50. FIXED
Inode bitmap differences: +11 -15. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (9.1% non-contiguous), 22/100 blocks

View File

@ -14,7 +14,6 @@ File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
Clone duplicate/bad blocks? yes
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
@ -24,10 +23,12 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (44, counted=60).
Fix? yes
Free blocks count wrong (62, counted=60).
Fix? yes
Free blocks count wrong for group 0 (44, counted=60). FIXED
Free blocks count wrong (62, counted=60). FIXED
Padding at end of block bitmap is not set. Fix? yes

View File

@ -15,14 +15,12 @@ File /pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Clone duplicate/bad blocks? yes
File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
has 4 duplicate block(s), shared with 2 file(s):
/pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
Clone duplicate/bad blocks? yes
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
@ -32,10 +30,12 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (8, counted=22).
Fix? yes
Free blocks count wrong (26, counted=22).
Fix? yes
Free blocks count wrong for group 0 (8, counted=22). FIXED
Free blocks count wrong (26, counted=22). FIXED
Padding at end of block bitmap is not set. Fix? yes

View File

@ -13,7 +13,6 @@ File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
<filesystem metadata>
Clone duplicate/bad blocks? yes
Pass 2: Checking directory structure
Directory inode 12, block 1, offset 0: directory corrupted
Salvage? yes
@ -27,10 +26,12 @@ Salvage? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (77, counted=74).
Fix? yes
Free blocks count wrong (77, counted=74).
Fix? yes
Free blocks count wrong for group 0 (77, counted=74). FIXED
Free blocks count wrong (77, counted=74). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (8.3% non-contiguous), 26/100 blocks

View File

@ -13,14 +13,13 @@ File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
<filesystem metadata>
Clone duplicate/bad blocks? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -29 -30 -31
Fix? yes
Block bitmap differences: -29 -30 -31. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (8.3% non-contiguous), 39/100 blocks

View File

@ -5,9 +5,9 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (44, counted=63).
Fix? yes
Free blocks count wrong for group 0 (44, counted=63). FIXED
Padding at end of block bitmap is not set. Fix? yes

View File

@ -518,13 +518,21 @@ Connect to /lost+found? yes
Inode 111 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (56, counted=55).
Fix? yes
Free blocks count wrong (56, counted=55).
Fix? yes
Free inodes count wrong for group #0 (89, counted=88).
Fix? yes
Directories count wrong for group #0 (2, counted=3).
Fix? yes
Free inodes count wrong (89, counted=88).
Fix? yes
Free blocks count wrong for group 0 (56, counted=55). FIXED
Free blocks count wrong (56, counted=55). FIXED
Free inodes count wrong for group #0 (89, counted=88). FIXED
Directories count wrong for group #0 (2, counted=3). FIXED
Free inodes count wrong (89, counted=88). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 112/200 files (0.0% non-contiguous), 145/200 blocks

View File

@ -16,11 +16,11 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21
Fix? yes
Block bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21. FIXED
Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
Padding at end of block bitmap is not set. Fix? yes
Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****

View File

@ -16,9 +16,9 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Inode bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11
Fix? yes
Inode bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks

View File

@ -23,15 +23,27 @@ Root inode not allocated. Allocate? yes
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
Fix? yes
Free blocks count wrong for group #0 (78, counted=90).
Fix? yes
Free blocks count wrong (78, counted=90).
Fix? yes
Inode bitmap differences: -11
Fix? yes
Free inodes count wrong for group #0 (21, counted=22).
Fix? yes
Directories count wrong for group #0 (2, counted=1).
Fix? yes
Free inodes count wrong (21, counted=22).
Fix? yes
Block bitmap differences: -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
Free blocks count wrong for group 0 (78, counted=90). FIXED
Free blocks count wrong (78, counted=90). FIXED
Inode bitmap differences: -11. FIXED
Free inodes count wrong for group #0 (21, counted=22). FIXED
Directories count wrong for group #0 (2, counted=1). FIXED
Free inodes count wrong (21, counted=22). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 10/32 files (0.0% non-contiguous), 10/100 blocks

View File

@ -25,14 +25,24 @@ Entry 'termcap' in / (2) has deleted/unused inode 12. Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -44 -45
Fix? yes
Free blocks count wrong for group #0 (41, counted=58).
Fix? yes
Free blocks count wrong (41, counted=58).
Fix? yes
Inode bitmap differences: -12
Fix? yes
Free inodes count wrong for group #0 (20, counted=21).
Fix? yes
Free inodes count wrong (20, counted=21).
Fix? yes
Block bitmap differences: -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -44 -45. FIXED
Free blocks count wrong for group 0 (41, counted=58). FIXED
Free blocks count wrong (41, counted=58). FIXED
Inode bitmap differences: -12. FIXED
Free inodes count wrong for group #0 (20, counted=21). FIXED
Free inodes count wrong (20, counted=21). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 42/100 blocks

View File

@ -24,16 +24,26 @@ Connect to /lost+found? yes
Inode 15 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: +22 +23 +49 +57 +58
Fix? yes
Block bitmap differences: +22 +23 +49 +57 +58. FIXED
Free blocks count wrong for group 0 (25, counted=33). FIXED
Free blocks count wrong (39, counted=33). FIXED
Inode bitmap differences: +13. FIXED
Free inodes count wrong for group #0 (2, counted=0). FIXED
Directories count wrong for group #0 (1, counted=2). FIXED
Free inodes count wrong (2, counted=0). FIXED
Padding at end of block bitmap is not set. Fix? yes
Free blocks count wrong for group #0 (25, counted=33).
Fix? yes
Free blocks count wrong (39, counted=33).
Fix? yes
Inode bitmap differences: +13
Fix? yes
Free inodes count wrong for group #0 (2, counted=0).
Fix? yes
Directories count wrong for group #0 (1, counted=2).
Fix? yes
Free inodes count wrong (2, counted=0).
Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****

View File

@ -24,11 +24,15 @@ Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -43 -44 -45 -46 -47 -48 -49
Fix? yes
Free blocks count wrong for group #0 (68, counted=75).
Fix? yes
Free blocks count wrong (68, counted=75).
Fix? yes
Block bitmap differences: -43 -44 -45 -46 -47 -48 -49. FIXED
Free blocks count wrong for group 0 (68, counted=75). FIXED
Free blocks count wrong (68, counted=75). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 29/32 files (3.4% non-contiguous), 25/100 blocks

View File

@ -21,15 +21,27 @@ Pass 4: Checking reference counts
Inode 2 ref count is 8, should be 4. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -8385 -8386 -8387 -8388 -8389 -8390 -8391 -8392 -8393 -8394 -8395 -8396 -8397 -8398 -8399 -8400 -8401 -8402 -8403 -8404 -8405
Fix? yes
Free blocks count wrong for group #0 (7987, counted=7984).
Fix? yes
Free blocks count wrong (11602, counted=11599).
Fix? yes
Inode bitmap differences: -1505 -1506 -1507 -1508 -1509 -1510 -1511 -1512 -1513 -1514 -1515 -1516
Fix? yes
Free inodes count wrong for group #0 (1493, counted=1489).
Fix? yes
Directories count wrong for group #0 (2, counted=3).
Fix? yes
Free inodes count wrong (2997, counted=2993).
Fix? yes
Block bitmap differences: -8385 -8386 -8387 -8388 -8389 -8390 -8391 -8392 -8393 -8394 -8395 -8396 -8397 -8398 -8399 -8400 -8401 -8402 -8403 -8404 -8405. FIXED
Free blocks count wrong for group 0 (7987, counted=7984). FIXED
Free blocks count wrong (11602, counted=11599). FIXED
Inode bitmap differences: -1505 -1506 -1507 -1508 -1509 -1510 -1511 -1512 -1513 -1514 -1515 -1516. FIXED
Free inodes count wrong for group #0 (1493, counted=1489). FIXED
Directories count wrong for group #0 (2, counted=3). FIXED
Free inodes count wrong (2997, counted=2993). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 15/3008 files (0.0% non-contiguous), 401/12000 blocks

View File

@ -27,13 +27,21 @@ Inode 12 ref count is 4, should be 3. Fix? yes
Unattached zero-length inode 15. Clear? yes
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (75, counted=74).
Fix? yes
Free blocks count wrong (75, counted=74).
Fix? yes
Free inodes count wrong for group #0 (17, counted=16).
Fix? yes
Directories count wrong for group #0 (4, counted=5).
Fix? yes
Free inodes count wrong (17, counted=16).
Fix? yes
Free blocks count wrong for group 0 (75, counted=74). FIXED
Free blocks count wrong (75, counted=74). FIXED
Free inodes count wrong for group #0 (17, counted=16). FIXED
Directories count wrong for group #0 (4, counted=5). FIXED
Free inodes count wrong (17, counted=16). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/32 files (0.0% non-contiguous), 26/100 blocks

View File

@ -9,9 +9,9 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
Fix? yes
Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks

View File

@ -3,15 +3,27 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (8042, counted=7614).
Fix? yes
Free blocks count wrong for group #1 (170, counted=169).
Fix? yes
Free blocks count wrong (8212, counted=7783).
Fix? yes
Free inodes count wrong for group #0 (1053, counted=1052).
Fix? yes
Free inodes count wrong for group #1 (1064, counted=1063).
Fix? yes
Directories count wrong for group #1 (0, counted=1).
Fix? yes
Free inodes count wrong (2117, counted=2115).
Fix? yes
Free blocks count wrong for group 0 (8042, counted=7614). FIXED
Free blocks count wrong for group 1 (170, counted=169). FIXED
Free blocks count wrong (8212, counted=7783). FIXED
Free inodes count wrong for group #0 (1053, counted=1052). FIXED
Free inodes count wrong for group #1 (1064, counted=1063). FIXED
Directories count wrong for group #1 (0, counted=1). FIXED
Free inodes count wrong (2117, counted=2115). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 13/2128 files (0.0% non-contiguous), 717/8500 blocks

View File

@ -4,12 +4,18 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (7987, counted=7982).
Fix? yes
Free blocks count wrong (11602, counted=11597).
Fix? yes
Free inodes count wrong for group #0 (1493, counted=1488).
Fix? yes
Free inodes count wrong (2997, counted=2992).
Fix? yes
Free blocks count wrong for group 0 (7987, counted=7982). FIXED
Free blocks count wrong (11602, counted=11597). FIXED
Free inodes count wrong for group #0 (1493, counted=1488). FIXED
Free inodes count wrong (2997, counted=2992). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks

View File

@ -4,12 +4,18 @@ Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
Free blocks count wrong for group #0 (7987, counted=7982).
Fix? yes
Free blocks count wrong (11602, counted=11597).
Fix? yes
Free inodes count wrong for group #0 (1493, counted=1488).
Fix? yes
Free inodes count wrong (2997, counted=2992).
Fix? yes
Free blocks count wrong for group 0 (7987, counted=7982). FIXED
Free blocks count wrong (11602, counted=11597). FIXED
Free inodes count wrong for group #0 (1493, counted=1488). FIXED
Free inodes count wrong (2997, counted=2992). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks