Beispiel #1
0
void print_e2fsck_message(e2fsck_t ctx, const char *msg,
			  struct problem_context *pctx, int first,
			  int recurse)
{
	ext2_filsys fs = ctx->fs;
	const char *	cp;
	int		i;

	e2fsck_clear_progbar(ctx);
	for (cp = msg; *cp; cp++) {
		if (cp[0] == '@') {
			cp++;
			expand_at_expression(ctx, *cp, pctx, &first, recurse);
		} else if (cp[0] == '%' && cp[1] == 'I') {
			cp += 2;
			expand_inode_expression(*cp, pctx);
		} else if (cp[0] == '%' && cp[1] == 'D') {
			cp += 2;
			expand_dirent_expression(*cp, pctx);
		} else if ((cp[0] == '%')) {
			cp++;
			expand_percent_expression(fs, *cp, pctx);
		} else {
			for (i=0; cp[i]; i++)
				if ((cp[i] == '@') || cp[i] == '%')
					break;
			printf("%.*s", i, cp);
			cp += i-1;
		}
		first = 0;
	}
}
static void signal_progress_off(int sig EXT2FS_ATTR((unused)))
{
	e2fsck_t ctx = e2fsck_global_ctx;

	if (!ctx)
		return;

	e2fsck_clear_progbar(ctx);
	ctx->progress = 0;
}
Beispiel #3
0
void e2fsck_pass5(e2fsck_t ctx)
{
#ifdef RESOURCE_TRACK
	struct resource_track	rtrack;
#endif
	struct problem_context	pctx;
	
#ifdef MTRACE
	mtrace_print("Pass 5");
#endif

#ifdef RESOURCE_TRACK
	init_resource_track(&rtrack);
#endif
	
	clear_problem_context(&pctx);

	if (!(ctx->options & E2F_OPT_PREEN))
		fix_problem(ctx, PR_5_PASS_HEADER, &pctx);

	if (ctx->progress)
		if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
			return;

	e2fsck_read_bitmaps(ctx);

	check_block_bitmaps(ctx);
	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
		return;
	check_inode_bitmaps(ctx);
	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
		return;
	check_inode_end(ctx);
	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
		return;
	check_block_end(ctx);
	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
		return;

	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;

#ifdef RESOURCE_TRACK
	if (ctx->options & E2F_OPT_TIME2) {
		e2fsck_clear_progbar(ctx);
		print_resource_track(_("Pass 5"), &rtrack);
	}
#endif
}
Beispiel #4
0
void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg,
			  struct problem_context *pctx, int first,
			  int recurse)
{
	ext2_filsys fs = ctx->fs;
	const char *	cp;
	int		i, width;

	e2fsck_clear_progbar(ctx);
	for (cp = msg; *cp; cp++) {
		if (cp[0] == '@') {
			cp++;
			expand_at_expression(f, ctx, *cp, pctx, &first,
					     recurse);
		} else if (cp[0] == '%') {
			cp++;
			width = 0;
			while (isdigit(cp[0])) {
				width = (width * 10) + cp[0] - '0';
				cp++;
			}
			if (cp[0] == 'I') {
				cp++;
				expand_inode_expression(f, fs, *cp, pctx);
			} else if (cp[0] == 'D') {
				cp++;
				expand_dirent_expression(f, fs, *cp, pctx);
			} else {
				expand_percent_expression(f, fs, *cp, width,
							  &first, pctx);
			}
		} else {
			for (i=0; cp[i]; i++)
				if ((cp[i] == '@') || cp[i] == '%')
					break;
			fprintf(f, "%.*s", i, cp);
			cp += i-1;
		}
		first = 0;
	}
}
int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
			   unsigned int dpynum)
{
	static const char spinner[] = "\\|/-";
	int	i;
	unsigned int	tick;
	struct timeval	tv;
	int dpywidth;
	int fixed_percent;

	if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
		return 0;

	/*
	 * Calculate the new progress position.  If the
	 * percentage hasn't changed, then we skip out right
	 * away.
	 */
	fixed_percent = (int) ((10 * percent) + 0.5);
	if (ctx->progress_last_percent == fixed_percent)
		return 0;
	ctx->progress_last_percent = fixed_percent;

	/*
	 * If we've already updated the spinner once within
	 * the last 1/8th of a second, no point doing it
	 * again.
	 */
	gettimeofday(&tv, NULL);
	tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
	if ((tick == ctx->progress_last_time) &&
	    (fixed_percent != 0) && (fixed_percent != 1000))
		return 0;
	ctx->progress_last_time = tick;

	/*
	 * Advance the spinner, and note that the progress bar
	 * will be on the screen
	 */
	ctx->progress_pos = (ctx->progress_pos+1) & 3;
	ctx->flags |= E2F_FLAG_PROG_BAR;

	dpywidth = 66 - strlen(label);
	dpywidth = 8 * (dpywidth / 8);
	if (dpynum)
		dpywidth -= 8;

	i = ((percent * dpywidth) + 50) / 100;
	printf("%s%s: |%s%s", ctx->start_meta, label,
	       bar + (sizeof(bar) - (i+1)),
	       spaces + (sizeof(spaces) - (dpywidth - i + 1)));
	if (fixed_percent == 1000)
		fputc('|', stdout);
	else
		fputc(spinner[ctx->progress_pos & 3], stdout);
	printf(" %4.1f%%  ", percent);
	if (dpynum)
		printf("%u\r", dpynum);
	else
		fputs(" \r", stdout);
	fputs(ctx->stop_meta, stdout);

	if (fixed_percent == 1000)
		e2fsck_clear_progbar(ctx);
	fflush(stdout);

	return 0;
}
Beispiel #6
0
void print_resource_track(e2fsck_t ctx, const char *desc,
			  struct resource_track *track, io_channel channel)
{
#ifdef HAVE_GETRUSAGE
	struct rusage r;
#endif
#ifdef HAVE_MALLINFO
	struct mallinfo	malloc_info;
#endif
	struct timeval time_end;

	if ((desc && !(ctx->options & E2F_OPT_TIME2)) ||
	    (!desc && !(ctx->options & E2F_OPT_TIME)))
		return;

	e2fsck_clear_progbar(ctx);
	gettimeofday(&time_end, 0);

	if (desc)
		log_out(ctx, "%s: ", desc);

#ifdef HAVE_MALLINFO
#define kbytes(x)	(((unsigned long)(x) + 1023) / 1024)

	malloc_info = mallinfo();
	log_out(ctx, _("Memory used: %luk/%luk (%luk/%luk), "),
		kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
		kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
#else
	log_out(ctx, _("Memory used: %lu, "),
		(unsigned long) (((char *) sbrk(0)) -
				 ((char *) track->brk_start)));
#endif
#ifdef HAVE_GETRUSAGE
	getrusage(RUSAGE_SELF, &r);

	log_out(ctx, _("time: %5.2f/%5.2f/%5.2f\n"),
		timeval_subtract(&time_end, &track->time_start),
		timeval_subtract(&r.ru_utime, &track->user_start),
		timeval_subtract(&r.ru_stime, &track->system_start));
#else
	log_out(ctx, _("elapsed time: %6.3f\n"),
		timeval_subtract(&time_end, &track->time_start));
#endif
#define mbytes(x)	(((x) + 1048575) / 1048576)
	if (channel && channel->manager && channel->manager->get_stats) {
		io_stats delta = 0;
		unsigned long long bytes_read = 0;
		unsigned long long bytes_written = 0;

		if (desc)
			log_out(ctx, "%s: ", desc);

		channel->manager->get_stats(channel, &delta);
		if (delta) {
			bytes_read = delta->bytes_read - track->bytes_read;
			bytes_written = delta->bytes_written -
				track->bytes_written;
		}
		log_out(ctx, "I/O read: %lluMB, write: %lluMB, "
			"rate: %.2fMB/s\n",
			mbytes(bytes_read), mbytes(bytes_written),
			(double)mbytes(bytes_read + bytes_written) /
			timeval_subtract(&time_end, &track->time_start));
	}
}
Beispiel #7
0
void e2fsck_rehash_directories(e2fsck_t ctx)
{
	struct problem_context	pctx;
#ifdef RESOURCE_TRACK
	struct resource_track	rtrack;
#endif
	struct dir_info		*dir;
	ext2_u32_iterate 	iter;
	ext2_ino_t		ino;
	errcode_t		retval;
	int			i, cur, max, all_dirs, dir_index, first = 1;

#ifdef RESOURCE_TRACK
	init_resource_track(&rtrack);
#endif

	all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;

	if (!ctx->dirs_to_hash && !all_dirs)
		return;

	e2fsck_get_lost_and_found(ctx, 0);
		
	clear_problem_context(&pctx);

	dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
	cur = 0;
	if (all_dirs) {
		i = 0;
		max = e2fsck_get_num_dirinfo(ctx);
	} else {
		retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash, 
						       &iter);
		if (retval) {
			pctx.errcode = retval;
			fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
			return;
		}
		max = ext2fs_u32_list_count(ctx->dirs_to_hash);
	}
	while (1) {
		if (all_dirs) {
			if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
				break;
			ino = dir->ino;
		} else {
			if (!ext2fs_u32_list_iterate(iter, &ino))
				break;
		}
		if (ino == ctx->lost_and_found)
			continue;
		pctx.dir = ino;
		if (first) {
			fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
			first = 0;
		}
#if 0
		fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
#endif
		pctx.errcode = e2fsck_rehash_dir(ctx, ino);
		if (pctx.errcode) {
			end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
			fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
		}
		if (ctx->progress && !ctx->progress_fd)
			e2fsck_simple_progress(ctx, "Rebuilding directory",
			       100.0 * (float) (++cur) / (float) max, ino);
	}
	end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
	if (!all_dirs)
		ext2fs_u32_list_iterate_end(iter);
	
	if (ctx->dirs_to_hash)
		ext2fs_u32_list_free(ctx->dirs_to_hash);
	ctx->dirs_to_hash = 0;

#ifdef RESOURCE_TRACK
	if (ctx->options & E2F_OPT_TIME2) {
		e2fsck_clear_progbar(ctx);
		print_resource_track("Pass 3A", &rtrack);
	}
#endif
}
Beispiel #8
0
int main (int argc, char *argv[])
{
	errcode_t	retval = 0;
	int		exit_value = FSCK_OK;
	ext2_filsys	fs = 0;
	io_manager	io_ptr;
	struct ext2_super_block *sb;
	const char	*lib_ver_date;
	int		my_ver, lib_ver;
	e2fsck_t	ctx;
	struct problem_context pctx;
	int flags, run_result;
	
	clear_problem_context(&pctx);
#ifdef MTRACE
	mtrace();
#endif
#ifdef MCHECK
	mcheck(0);
#endif
#ifdef ENABLE_NLS
	setlocale(LC_MESSAGES, "");
	setlocale(LC_CTYPE, "");
	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
	textdomain(NLS_CAT_NAME);
#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(FSCK_ERROR);
	}
	reserve_stdio_fds();
	
#ifdef RESOURCE_TRACK
	init_resource_track(&ctx->global_rtrack);
#endif

	if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
		fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
			 my_ver_date);

	if (show_version_only) {
		fprintf(stderr, _("\tUsing %s, %s\n"),
			error_message(EXT2_ET_BASE), lib_ver_date);
		exit(FSCK_OK);
	}
	
	check_mount(ctx);
	
	if (!(ctx->options & E2F_OPT_PREEN) &&
	    !(ctx->options & E2F_OPT_NO) &&
	    !(ctx->options & E2F_OPT_YES)) {
		if (!ctx->interactive)
			fatal_error(ctx,
				    _("need terminal for interactive repairs"));
	}
	ctx->superblock = ctx->use_superblock;
restart:
#ifdef CONFIG_TESTIO_DEBUG
	io_ptr = test_io_manager;
	test_io_backing_manager = unix_io_manager;
#else
	io_ptr = unix_io_manager;
#endif
	flags = 0;
	if ((ctx->options & E2F_OPT_READONLY) == 0)
		flags |= EXT2_FLAG_RW;
	if ((ctx->mount_flags & EXT2_MF_MOUNTED) == 0)
		flags |= EXT2_FLAG_EXCLUSIVE;

	if (ctx->superblock && ctx->blocksize) {
		retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, 
				      flags, ctx->superblock, ctx->blocksize,
				      io_ptr, &fs);
	} else if (ctx->superblock) {
		int blocksize;
		for (blocksize = EXT2_MIN_BLOCK_SIZE;
		     blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
			retval = ext2fs_open2(ctx->filesystem_name, 
					      ctx->io_options, flags,
					      ctx->superblock, blocksize,
					      io_ptr, &fs);
			if (!retval)
				break;
		}
	} else 
		retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, 
				      flags, 0, 0, io_ptr, &fs);
	if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
	    !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
	    ((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..."));
			get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
			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(_("The filesystem revision is apparently "
			       "too high for this version of e2fsck.\n"
			       "(Or the filesystem superblock "
			       "is corrupt)\n\n"));
			fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
		} 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 if (retval == EBUSY)
			printf(_("Filesystem mounted or opened exclusively "
				 "by another program?\n"));
#ifdef EROFS
		else if (retval == EROFS)
			printf(_("Disk write-protected; use the -n option "
			       "to do a read-only\n"
			       "check of the device.\n"));
#endif
		else
			fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
		fatal_error(ctx, 0);
	}
	ctx->fs = fs;
	fs->priv_data = ctx;
	fs->now = ctx->now;
	sb = fs->super;
	if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
		com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
			_("while trying to open %s"),
			ctx->filesystem_name);
	get_newer:
		fatal_error(ctx, _("Get a newer version of e2fsck!"));
	}

	/*
	 * Set the device name, which is used whenever we print error
	 * or informational messages to the user.
	 */
	if (ctx->device_name == 0 &&
	    (sb->s_volume_name[0] != 0)) {
		ctx->device_name = string_copy(ctx, sb->s_volume_name,
					       sizeof(sb->s_volume_name));
	}
	if (ctx->device_name == 0)
		ctx->device_name = ctx->filesystem_name;

	/*
	 * Make sure the ext3 superblock fields are consistent.
	 */
	retval = e2fsck_check_ext3_journal(ctx);
	if (retval) {
		com_err(ctx->program_name, retval,
			_("while checking ext3 journal for %s"),
			ctx->device_name);
		fatal_error(ctx, 0);
	}

	/*
	 * Check to see if we need to do ext3-style recovery.  If so,
	 * do it, and then restart the fsck.
	 */
	if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
		if (ctx->options & E2F_OPT_READONLY) {
			printf(_("Warning: skipping journal recovery "
				 "because doing a read-only filesystem "
				 "check.\n"));
			io_channel_flush(ctx->fs->io);
		} else {
			if (ctx->flags & E2F_FLAG_RESTARTED) {
				/*
				 * Whoops, we attempted to run the
				 * journal twice.  This should never
				 * happen, unless the hardware or
				 * device driver is being bogus.
				 */
				com_err(ctx->program_name, 0,
					_("unable to set superblock flags on %s\n"), ctx->device_name);
				fatal_error(ctx, 0);
			}
			retval = e2fsck_run_ext3_journal(ctx);
			if (retval) {
				com_err(ctx->program_name, retval,
				_("while recovering ext3 journal of %s"),
					ctx->device_name);
				fatal_error(ctx, 0);
			}
			ext2fs_close(ctx->fs);
			ctx->fs = 0;
			ctx->flags |= E2F_FLAG_RESTARTED;
			goto restart;
		}
	}

	/*
	 * Check for compatibility with the feature sets.  We need to
	 * be more stringent than ext2fs_open().
	 */
	if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
	    (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
		com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
			"(%s)", ctx->device_name);
		goto get_newer;
	}
	if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
		com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
			"(%s)", ctx->device_name);
		goto get_newer;
	}
#ifdef ENABLE_COMPRESSION
	if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
		com_err(ctx->program_name, 0,
			_("Warning: compression support is experimental.\n"));
#endif
#ifndef ENABLE_HTREE
	if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
		com_err(ctx->program_name, 0,
			_("E2fsck not compiled with HTREE support,\n\t"
			  "but filesystem %s has HTREE directories.\n"),
			ctx->device_name);
		goto get_newer;
	}
#endif

	/*
	 * 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);

	/*
	 * We only update the master superblock because (a) paranoia;
	 * we don't want to corrupt the backup superblocks, and (b) we
	 * don't need to update the mount count and last checked
	 * fields in the backup superblock (the kernel doesn't
	 * update the backup superblocks anyway).
	 */
	fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;

	ehandler_init(fs->io);

	if (ctx->superblock)
		set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
	ext2fs_mark_valid(fs);
	check_super_block(ctx);
	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
		fatal_error(ctx, 0);
	check_if_skip(ctx);
	if (bad_blocks_file)
		read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
	else if (cflag)
		read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
		fatal_error(ctx, 0);
#ifdef ENABLE_SWAPFS
	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(ctx, 0);
		}
	}
	if (swapfs) {
		swap_filesys(ctx);
		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
			fatal_error(ctx, 0);
	}
#endif

	/*
	 * 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"));
	}

	run_result = e2fsck_run(ctx);
	e2fsck_clear_progbar(ctx);
	if (run_result == E2F_FLAG_RESTART) {
		printf(_("Restarting e2fsck from the beginning...\n"));
		retval = e2fsck_reset_context(ctx);
		if (retval) {
			com_err(ctx->program_name, retval,
				_("while resetting context"));
			fatal_error(ctx, 0);
		}
		ext2fs_close(fs);
		goto restart;
	}
	if (run_result & E2F_FLAG_CANCEL) {
		printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
		       ctx->device_name : ctx->filesystem_name);
		exit_value |= FSCK_CANCELED;
	}
	if (run_result & E2F_FLAG_ABORT)
		fatal_error(ctx, _("aborted"));

#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 (ctx->mount_flags & EXT2_MF_ISROOT) {
			printf(_("%s: ***** REBOOT LINUX *****\n"),
			       ctx->device_name);
			exit_value |= FSCK_REBOOT;
		}
	}
	if (!ext2fs_test_valid(fs) ||
	    ((exit_value & FSCK_CANCELED) && 
	     (sb->s_state & EXT2_ERROR_FS))) {
		printf(_("\n%s: ********** WARNING: Filesystem still has "
			 "errors **********\n\n"), ctx->device_name);
		exit_value |= FSCK_UNCORRECTED;
		exit_value &= ~FSCK_NONDESTRUCT;
	}
	if (exit_value & FSCK_CANCELED) {
		int	allow_cancellation;

		profile_get_boolean(ctx->profile, "options",
				    "allow_cancellation", 0, 0, 
				    &allow_cancellation);
		exit_value &= ~FSCK_NONDESTRUCT;
		if (allow_cancellation && ext2fs_test_valid(fs) &&
		    (sb->s_state & EXT2_VALID_FS) && 
		    !(sb->s_state & EXT2_ERROR_FS))
			exit_value = 0;
	} else {
		show_stats(ctx);
		if (!(ctx->options & E2F_OPT_READONLY)) {
			if (ext2fs_test_valid(fs)) {
				if (!(sb->s_state & EXT2_VALID_FS))
					exit_value |= FSCK_NONDESTRUCT;
				sb->s_state = EXT2_VALID_FS;
			} else
				sb->s_state &= ~EXT2_VALID_FS;
			sb->s_mnt_count = 0;
			sb->s_lastcheck = ctx->now;
			ext2fs_mark_super_dirty(fs);
		}
	}

	e2fsck_write_bitmaps(ctx);
	
	ext2fs_close(fs);
	ctx->fs = NULL;
	free(ctx->filesystem_name);
	free(ctx->journal_name);

#ifdef RESOURCE_TRACK
	if (ctx->options & E2F_OPT_TIME)
		print_resource_track(NULL, &ctx->global_rtrack);
#endif
	e2fsck_free_context(ctx);
	return exit_value;
}
Beispiel #9
0
void e2fsck_pass4(e2fsck_t ctx)
{
	ext2_filsys fs = ctx->fs;
	ext2_ino_t	i;
	struct ext2_inode	inode;
#ifdef RESOURCE_TRACK
	struct resource_track	rtrack;
#endif
	struct problem_context	pctx;
	__u16	link_count, link_counted;
	char	*buf = 0;
	int	group, maxgroup;
	
#ifdef RESOURCE_TRACK
	init_resource_track(&rtrack);
#endif

#ifdef MTRACE
	mtrace_print("Pass 4");
#endif

	clear_problem_context(&pctx);

	if (!(ctx->options & E2F_OPT_PREEN))
		fix_problem(ctx, PR_4_PASS_HEADER, &pctx);

	group = 0;
	maxgroup = fs->group_desc_count;
	if (ctx->progress)
		if ((ctx->progress)(ctx, 4, 0, maxgroup))
			return;

	/* Protect loop from wrap-around if s_inodes_count maxed */
	for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) {
		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
			goto errout;
		if ((i % fs->super->s_inodes_per_group) == 0) {
			group++;
			if (ctx->progress)
				if ((ctx->progress)(ctx, 4, group, maxgroup))
					goto errout;
		}
		if (i == EXT2_BAD_INO ||
		    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
			continue;
		if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
		    (ctx->inode_imagic_map &&
		     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
		    (ctx->inode_bb_map &&
		     ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
			continue;
		ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
		ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
		if (link_counted == 0) {
			if (!buf)
				buf = e2fsck_allocate_memory(ctx,
				     fs->blocksize, "bad_inode buffer");
			if (e2fsck_process_bad_inode(ctx, 0, i, buf))
				continue;
			if (disconnect_inode(ctx, i))
				continue;
			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(ctx, i, &inode, "pass4");
			pctx.ino = i;
			pctx.inode = &inode;
			if (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(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
				inode.i_links_count = link_counted;
				e2fsck_write_inode(ctx, i, &inode, "pass4");
			}
		}
	}
	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;
	ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
	ctx->inode_imagic_map = 0;
errout:
	if (buf)
		ext2fs_free_mem(&buf);
#ifdef RESOURCE_TRACK
	if (ctx->options & E2F_OPT_TIME2) {
		e2fsck_clear_progbar(ctx);
		print_resource_track(_("Pass 4"), &rtrack);
	}
#endif
}
Beispiel #10
0
void e2fsck_pass2(e2fsck_t ctx)
{
    struct ext2_super_block *sb = ctx->fs->super;
    struct problem_context	pctx;
    ext2_filsys 		fs = ctx->fs;
    char			*buf;
#ifdef RESOURCE_TRACK
    struct resource_track	rtrack;
#endif
    struct dir_info 	*dir;
    struct check_dir_struct cd;

#ifdef RESOURCE_TRACK
    init_resource_track(&rtrack);
#endif

    clear_problem_context(&cd.pctx);

#ifdef MTRACE
    mtrace_print("Pass 2");
#endif

    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);
        ctx->flags |= E2F_FLAG_ABORT;
        return;
    }
    buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
                                          "directory scan buffer");

    /*
     * Set up the parent pointer for the root directory, if
     * present.  (If the root directory is not present, we will
     * create it in pass 3.)
     */
    dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
    if (dir)
        dir->parent = EXT2_ROOT_INO;

    cd.buf = buf;
    cd.ctx = ctx;
    cd.count = 1;
    cd.max = ext2fs_dblist_count(fs->dblist);

    if (ctx->progress)
        (void) (ctx->progress)(ctx, 2, 0, cd.max);

    cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
                                            &cd);
    if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
        return;
    if (cd.pctx.errcode) {
        fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
        ctx->flags |= E2F_FLAG_ABORT;
        return;
    }

    ext2fs_free_mem((void **) &buf);
    ext2fs_free_dblist(fs->dblist);

    if (ctx->inode_bad_map) {
        ext2fs_free_inode_bitmap(ctx->inode_bad_map);
        ctx->inode_bad_map = 0;
    }
    if (ctx->inode_reg_map) {
        ext2fs_free_inode_bitmap(ctx->inode_reg_map);
        ctx->inode_reg_map = 0;
    }

    clear_problem_context(&pctx);
    if (ctx->large_files) {
        if (!(sb->s_feature_ro_compat &
                EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
                fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
            sb->s_feature_ro_compat |=
                EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
            ext2fs_mark_super_dirty(fs);
        }
        if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
                fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
            ext2fs_update_dynamic_rev(fs);
            ext2fs_mark_super_dirty(fs);
        }
    } else if (!ctx->large_files &&
               (sb->s_feature_ro_compat &
                EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
        if (fs->flags & EXT2_FLAG_RW) {
            sb->s_feature_ro_compat &=
                ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
            ext2fs_mark_super_dirty(fs);
        }
    }

#ifdef RESOURCE_TRACK
    if (ctx->options & E2F_OPT_TIME2) {
        e2fsck_clear_progbar(ctx);
        print_resource_track("Pass 2", &rtrack);
    }
#endif
}