unsigned int dir_links;
unsigned int num_files, num_links;
__u32 *mask, m;
- int frag_percent_file, frag_percent_dir, frag_percent_total;
+ int frag_percent_file = 0, frag_percent_dir = 0, frag_percent_total = 0;
int i, j, printed = 0;
dir_links = 2 * ctx->fs_directory_count - 1;
blocks_used = (ext2fs_blocks_count(fs->super) -
ext2fs_free_blocks_count(fs->super));
- frag_percent_file = (10000 * ctx->fs_fragmented) / inodes_used;
- frag_percent_file = (frag_percent_file + 5) / 10;
+ if (inodes_used > 0) {
+ frag_percent_file = (10000 * ctx->fs_fragmented) / inodes_used;
+ frag_percent_file = (frag_percent_file + 5) / 10;
- frag_percent_dir = (10000 * ctx->fs_fragmented_dir) / inodes_used;
- frag_percent_dir = (frag_percent_dir + 5) / 10;
+ frag_percent_dir = (10000 * ctx->fs_fragmented_dir) / inodes_used;
+ frag_percent_dir = (frag_percent_dir + 5) / 10;
- frag_percent_total = ((10000 * (ctx->fs_fragmented +
- ctx->fs_fragmented_dir))
- / inodes_used);
- frag_percent_total = (frag_percent_total + 5) / 10;
+ frag_percent_total = ((10000 * (ctx->fs_fragmented +
+ ctx->fs_fragmented_dir))
+ / inodes_used);
+ frag_percent_total = (frag_percent_total + 5) / 10;
+ }
if (!verbose) {
log_out(ctx, _("%s: %u/%u files (%0d.%d%% non-contiguous), "
{
FILE *f;
DIR *d;
- char tmp[80], tmp2[80], fname[80];
+ char tmp[80], tmp2[80], fname[NAME_MAX+30];
unsigned int acflag;
struct dirent* de;
while ((de=readdir(d)) != NULL) {
if (!strncmp(".", de->d_name, 1))
continue;
- snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
+ snprintf(fname, sizeof(fname),
+ "/proc/acpi/ac_adapter/%s/state",
de->d_name);
f = fopen(fname, "r");
if (!f)
if (batt && ((ctx->now - fs->super->s_lastcheck) <
fs->super->s_checkinterval*2))
reason = 0;
+ } else if (broken_system_clock && fs->super->s_checkinterval) {
+ log_out(ctx, "%s: ", ctx->device_name);
+ log_out(ctx, "%s",
+ _("ignoring check interval, broken_system_clock set\n"));
}
+
if (reason) {
log_out(ctx, "%s", ctx->device_name);
log_out(ctx, reason, reason_arg);
} else if (strcmp(token, "nodiscard") == 0) {
ctx->options &= ~E2F_OPT_DISCARD;
continue;
+ } else if (strcmp(token, "optimize_extents") == 0) {
+ ctx->options &= ~E2F_OPT_NOOPT_EXTENTS;
+ continue;
+ } else if (strcmp(token, "no_optimize_extents") == 0) {
+ ctx->options |= E2F_OPT_NOOPT_EXTENTS;
+ continue;
+ } else if (strcmp(token, "inode_count_fullmap") == 0) {
+ ctx->options |= E2F_OPT_ICOUNT_FULLMAP;
+ continue;
+ } else if (strcmp(token, "no_inode_count_fullmap") == 0) {
+ ctx->options &= ~E2F_OPT_ICOUNT_FULLMAP;
+ continue;
} else if (strcmp(token, "log_filename") == 0) {
if (!arg)
extended_usage++;
} else if (strcmp(token, "fixes_only") == 0) {
ctx->options |= E2F_OPT_FIXES_ONLY;
continue;
+ } else if (strcmp(token, "unshare_blocks") == 0) {
+ ctx->options |= E2F_OPT_UNSHARE_BLOCKS;
+ ctx->options |= E2F_OPT_FORCE;
+ continue;
} else {
fprintf(stderr, _("Unknown extended option: %s\n"),
token);
free(buf);
if (extended_usage) {
- fputs(("\nExtended options are separated by commas, "
+ fputs(_("\nExtended options are separated by commas, "
"and may take an argument which\n"
"is set off by an equals ('=') sign. "
- "Valid extended options are:\n"), stderr);
- fputs(("\tea_ver=<ea_version (1 or 2)>\n"), stderr);
- fputs(("\tfragcheck\n"), stderr);
- fputs(("\tjournal_only\n"), stderr);
- fputs(("\tdiscard\n"), stderr);
- fputs(("\tnodiscard\n"), stderr);
- fputs(("\treadahead_kb=<buffer size>\n"), stderr);
- fputs(("\tbmap2extent\n"), stderr);
+ "Valid extended options are:\n\n"), stderr);
+ fputs(_("\tea_ver=<ea_version (1 or 2)>\n"), stderr);
+ fputs("\tfragcheck\n", stderr);
+ fputs("\tjournal_only\n", stderr);
+ fputs("\tdiscard\n", stderr);
+ fputs("\tnodiscard\n", stderr);
+ fputs("\toptimize_extents\n", stderr);
+ fputs("\tno_optimize_extents\n", stderr);
+ fputs("\tinode_count_fullmap\n", stderr);
+ fputs("\tno_inode_count_fullmap\n", stderr);
+ fputs(_("\treadahead_kb=<buffer size>\n"), stderr);
+ fputs("\tbmap2extent\n", stderr);
+ fputs("\tunshare_blocks\n", stderr);
+ fputs("\tfixes_only\n", stderr);
fputc('\n', stderr);
exit(1);
}
break;
case 'L':
replace_bad_blocks++;
+ /* fall through */
case 'l':
if (bad_blocks_file)
free(bad_blocks_file);
if (c)
verbose = 1;
+ profile_get_boolean(ctx->profile, "options", "no_optimize_extents",
+ 0, 0, &c);
+ if (c)
+ ctx->options |= E2F_OPT_NOOPT_EXTENTS;
+
+ profile_get_boolean(ctx->profile, "options", "inode_count_fullmap",
+ 0, 0, &c);
+ if (c)
+ ctx->options |= E2F_OPT_ICOUNT_FULLMAP;
+
if (ctx->readahead_kb == ~0ULL) {
profile_get_integer(ctx->profile, "options",
"readahead_mem_pct", 0, -1, &c);
if (retval)
goto check_error;
- /* Print warning if e2fck will wait for more than 20 secs. */
+ /* Print warning if e2fsck will wait for more than 20 secs. */
if (verbose || wait_time > EXT4_MMP_MIN_CHECK_INTERVAL * 4) {
log_out(ctx, _("MMP interval is %u seconds and total wait "
"time is %u seconds. Please wait...\n"),
dump_mmp_msg(fs->mmp_buf,
_("If you are sure the filesystem is not "
"in use on any node, run:\n"
- "'tune2fs -f -E clear_mmp {device}'\n"));
+ "'tune2fs -f -E clear_mmp %s'\n"),
+ ctx->device_name);
} else if (retval == EXT2_ET_MMP_MAGIC_INVALID) {
if (fix_problem(ctx, PR_0_MMP_INVALID_MAGIC, &pctx)) {
ext2fs_mmp_clear(fs);
const char *lib_ver_date;
int my_ver, lib_ver;
e2fsck_t ctx;
- blk64_t orig_superblock;
+ blk64_t orig_superblock = ~(blk64_t)0;
struct problem_context pctx;
int flags, run_result, was_changed;
int journal_size;
"check of the device.\n"));
#endif
else {
+ /*
+ * Let's try once more will less consistency checking
+ * so that we are able to recover from more errors
+ * (e.g. some tool messing up some value in the sb).
+ */
+ if (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS)) {
+ if (fs)
+ ext2fs_close_free(&fs);
+ log_out(ctx, _("%s: Trying to load superblock "
+ "despite errors...\n"),
+ ctx->program_name);
+ flags |= EXT2_FLAG_IGNORE_SB_ERRORS;
+ /*
+ * If we tried backup sb, revert to the
+ * original one now.
+ */
+ if (orig_superblock != ~(blk64_t)0)
+ ctx->superblock = orig_superblock;
+ goto restart;
+ }
fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
if (retval == EXT2_ET_BAD_MAGIC)
check_plausibility(ctx->filesystem_name,
ext2fs_mark_super_dirty(fs);
}
- e2fsck_write_bitmaps(ctx);
- if (fs->flags & EXT2_FLAG_DIRTY) {
- pctx.errcode = ext2fs_flush(ctx->fs);
+ if (ext2fs_has_feature_shared_blocks(ctx->fs->super) &&
+ (ctx->options & E2F_OPT_UNSHARE_BLOCKS) &&
+ (ctx->options & E2F_OPT_NO))
+ /* Don't try to write or flush I/O, we just wanted to know whether or
+ * not there were enough free blocks to undo deduplication.
+ */
+ goto skip_write;
+
+ if (!(ctx->options & E2F_OPT_READONLY)) {
+ e2fsck_write_bitmaps(ctx);
+ if (fs->flags & EXT2_FLAG_DIRTY) {
+ pctx.errcode = ext2fs_flush(ctx->fs);
+ if (pctx.errcode)
+ fix_problem(ctx, PR_6_FLUSH_FILESYSTEM, &pctx);
+ }
+ pctx.errcode = io_channel_flush(ctx->fs->io);
if (pctx.errcode)
- fix_problem(ctx, PR_6_FLUSH_FILESYSTEM, &pctx);
+ fix_problem(ctx, PR_6_IO_FLUSH, &pctx);
}
- pctx.errcode = io_channel_flush(ctx->fs->io);
- if (pctx.errcode)
- fix_problem(ctx, PR_6_IO_FLUSH, &pctx);
if (was_changed) {
int fs_fixed = (ctx->flags & E2F_FLAG_PROBLEMS_FIXED);
exit_value |= FSCK_REBOOT;
}
}
+
+skip_write:
if (!ext2fs_test_valid(fs) ||
((exit_value & FSCK_CANCELED) &&
(sb->s_state & EXT2_ERROR_FS))) {