X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=e2fsck%2Funix.c;h=1cb516721a7d4a46cb850c2fbcc6f760013032a3;hb=7b8253ba09e635d328a48c98a184b571b809911b;hp=939862f1a6f3df8967c77096f0a4091539a69fba;hpb=6304d212bea8368dcaeffc40ed120c2e89bae95a;p=tools%2Fe2fsprogs.git diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 939862f..1cb5167 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -50,6 +50,7 @@ extern int optind; #include "e2p/e2p.h" #include "et/com_err.h" #include "e2p/e2p.h" +#include "uuid/uuid.h" #include "support/plausible.h" #include "e2fsck.h" #include "problem.h" @@ -106,7 +107,7 @@ static void show_stats(e2fsck_t ctx) 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; @@ -119,16 +120,18 @@ static void show_stats(e2fsck_t ctx) 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), " @@ -285,7 +288,7 @@ static int is_on_batt(void) { 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; @@ -309,7 +312,8 @@ static int is_on_batt(void) 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) @@ -394,7 +398,12 @@ static void check_if_skip(e2fsck_t ctx) 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); @@ -609,9 +618,10 @@ static void reserve_stdio_fds(void) fprintf(stderr, _("ERROR: Couldn't open " "/dev/null (%s)\n"), strerror(errno)); - break; + return; } } + (void) close(fd); } #ifdef HAVE_SIGNAL_H @@ -727,12 +737,27 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) else ctx->log_fn = string_copy(ctx, arg, 0); continue; + } else if (strcmp(token, "problem_log") == 0) { + if (!arg) + extended_usage++; + else + ctx->problem_log_fn = string_copy(ctx, arg, 0); + continue; } else if (strcmp(token, "bmap2extent") == 0) { ctx->options |= E2F_OPT_CONVERT_BMAP; continue; } 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; +#ifdef CONFIG_DEVELOPER_FEATURES + } else if (strcmp(token, "clear_all_uninit_bits") == 0) { + ctx->options |= E2F_OPT_CLEAR_UNINIT; + continue; +#endif } else { fprintf(stderr, _("Unknown extended option: %s\n"), token); @@ -757,6 +782,8 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) fputs("\tno_inode_count_fullmap\n", stderr); fputs(_("\treadahead_kb=\n"), stderr); fputs("\tbmap2extent\n", stderr); + fputs("\tunshare_blocks\n", stderr); + fputs("\tfixes_only\n", stderr); fputc('\n', stderr); exit(1); } @@ -921,6 +948,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) break; case 'L': replace_bad_blocks++; + /* fall through */ case 'l': if (bad_blocks_file) free(bad_blocks_file); @@ -1214,7 +1242,7 @@ static errcode_t e2fsck_check_mmp(ext2_filsys fs, e2fsck_t ctx) 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"), @@ -1242,7 +1270,8 @@ check_error: 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); @@ -1356,7 +1385,7 @@ int main (int argc, char *argv[]) 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; @@ -1400,6 +1429,7 @@ int main (int argc, char *argv[]) set_up_logging(ctx); if (ctx->logf) { int i; + fputs("E2fsck run: ", ctx->logf); for (i = 0; i < argc; i++) { if (i) @@ -1408,6 +1438,19 @@ int main (int argc, char *argv[]) } fputc('\n', ctx->logf); } + if (ctx->problem_logf) { + int i; + + fputs("\n", + ctx->problem_logf); + fprintf(ctx->problem_logf, "\n", + (unsigned long) ctx->now); + fprintf(ctx->problem_logf, "problem_logf, " arg%d=\"%s\"", i, argv[i]); + fputs("/>\n", ctx->problem_logf); + } init_resource_track(&ctx->global_rtrack, NULL); if (!(ctx->options & E2F_OPT_PREEN) || show_version_only) @@ -1563,6 +1606,27 @@ failure: "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 ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) && + !(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, @@ -1633,17 +1697,33 @@ failure: * 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)) { + if (ctx->device_name == 0 && sb->s_volume_name[0]) ctx->device_name = string_copy(ctx, sb->s_volume_name, sizeof(sb->s_volume_name)); - } + if (ctx->device_name == 0) ctx->device_name = string_copy(ctx, ctx->filesystem_name, 0); for (cp = ctx->device_name; *cp; cp++) if (isspace(*cp) || *cp == ':') *cp = '_'; + if (ctx->problem_logf) { + + fprintf(ctx->problem_logf, "filesystem_name); + if (!uuid_is_null(sb->s_uuid)) { + char buf[48]; + + uuid_unparse(sb->s_uuid, buf); + fprintf(ctx->problem_logf, " uuid=\"%s\"", buf); + } + if (sb->s_volume_name[0]) + fprintf(ctx->problem_logf, " label=\"%.*s\"", + EXT2_LEN_STR(sb->s_volume_name)); + + fputs("/>\n", ctx->problem_logf); + } + ehandler_init(fs->io); if (ext2fs_has_feature_mmp(fs->super) && @@ -1746,6 +1826,12 @@ print_unsupp_features: goto get_newer; } + if (ext2fs_has_feature_casefold(sb) && !fs->encoding) { + log_err(ctx, _("%s has unsupported encoding: %0x\n"), + ctx->filesystem_name, sb->s_encoding); + goto get_newer; + } + /* * If the user specified a specific superblock, presumably the * master superblock has been trashed. So we mark the @@ -1916,6 +2002,14 @@ no_journal: ext2fs_mark_super_dirty(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) { @@ -1952,6 +2046,8 @@ no_journal: exit_value |= FSCK_REBOOT; } } + +skip_write: if (!ext2fs_test_valid(fs) || ((exit_value & FSCK_CANCELED) && (sb->s_state & EXT2_ERROR_FS))) {