]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blobdiff - e2fsck/unix.c
e2fsck: remove get_filename_hash() prototype
[thirdparty/e2fsprogs.git] / e2fsck / unix.c
index 9ef4b1e782c0662951476770b41de04ef9950dea..faf5af9a82242513cedce89f1fe7324cbf451fc0 100644 (file)
@@ -50,10 +50,11 @@ extern int optind;
 #include "e2p/e2p.h"
 #include "et/com_err.h"
 #include "e2p/e2p.h"
+#include "support/plausible.h"
 #include "e2fsck.h"
 #include "problem.h"
+#include "jfs_user.h"
 #include "../version.h"
-#include "../misc/plausible.h"
 
 /* Command line options */
 static int cflag;              /* check disk */
@@ -66,15 +67,14 @@ static char *bad_blocks_file;
 
 e2fsck_t e2fsck_global_ctx;    /* Try your very best not to use this! */
 
-#ifdef CONFIG_JBD_DEBUG                /* Enabled by configure --enable-jfs-debug */
+#ifdef CONFIG_JBD_DEBUG                /* Enabled by configure --enable-jbd-debug */
 int journal_enable_debug = -1;
 #endif
 
 static void usage(e2fsck_t ctx)
 {
        fprintf(stderr,
-               _("Usage: %s [-panyrcdfvtDFV] [-b superblock] [-B blocksize]\n"
-               "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
+               _("Usage: %s [-panyrcdfktvDFV] [-b superblock] [-B blocksize]\n"
                "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
                "\t\t[-E extended-options] [-z undo_file] device\n"),
                ctx->program_name);
@@ -106,7 +106,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 +119,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), "
@@ -709,6 +711,18 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
                } 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++;
@@ -730,17 +744,22 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
        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("\tfixes_only\n", stderr);
                fputc('\n', stderr);
                exit(1);
        }
@@ -1007,6 +1026,16 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
        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);
@@ -1188,7 +1217,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"),
@@ -1338,7 +1367,7 @@ int main (int argc, char *argv[])
        int old_bitmaps;
        __u32 features[3];
        char *cp;
-       int qtype = -99;  /* quota type */
+       enum quota_type qtype;
 
        clear_problem_context(&pctx);
        sigcatcher_setup();
@@ -1620,7 +1649,7 @@ failure:
 
        ehandler_init(fs->io);
 
-       if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
+       if (ext2fs_has_feature_mmp(fs->super) &&
            (flags & EXT2_FLAG_SKIP_MMP)) {
                if (e2fsck_check_mmp(fs, ctx))
                        fatal_error(ctx, 0);
@@ -1640,19 +1669,22 @@ failure:
        /*
         * 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);
+       if ((ctx->mount_flags & (EXT2_MF_MOUNTED | EXT2_MF_BUSY)) == 0) {
+               retval = e2fsck_check_ext3_journal(ctx);
+               if (retval) {
+                       com_err(ctx->program_name, retval,
+                               _("while checking journal for %s"),
+                               ctx->device_name);
+                       fatal_error(ctx,
+                               _("Cannot proceed with file system check"));
+               }
        }
 
        /*
         * 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 (ext2fs_has_feature_journal_needs_recovery(sb)) {
                if (ctx->options & E2F_OPT_READONLY) {
                        log_out(ctx, "%s",
                                _("Warning: skipping journal recovery because "
@@ -1672,11 +1704,17 @@ failure:
                                fatal_error(ctx, 0);
                        }
                        retval = e2fsck_run_ext3_journal(ctx);
-                       if (retval) {
+                       if (retval == EFSBADCRC) {
+                               log_out(ctx, _("Journal checksum error "
+                                              "found in %s\n"),
+                                       ctx->device_name);
+                       } else if (retval == EFSCORRUPTED) {
+                               log_out(ctx, _("Journal corrupted in %s\n"),
+                                       ctx->device_name);
+                       } else if (retval) {
                                com_err(ctx->program_name, retval,
-                               _("while recovering ext3 journal of %s"),
+                               _("while recovering journal of %s"),
                                        ctx->device_name);
-                               fatal_error(ctx, 0);
                        }
                        ext2fs_close_free(&ctx->fs);
                        ctx->flags |= E2F_FLAG_RESTARTED;
@@ -1710,14 +1748,6 @@ print_unsupp_features:
                log_err(ctx, "\n");
                goto get_newer;
        }
-#ifndef ENABLE_HTREE
-       if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
-               log_err(ctx, _("%s: e2fsck not compiled with HTREE support,\n\t"
-                         "but filesystem %s has HTREE directories.\n"),
-                       ctx->program_name, ctx->device_name);
-               goto get_newer;
-       }
-#endif
 
        /*
         * If the user specified a specific superblock, presumably the
@@ -1782,15 +1812,14 @@ print_unsupp_features:
        else
                journal_size = -1;
 
-       if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_QUOTA) {
+       if (ext2fs_has_feature_quota(sb)) {
                /* Quotas were enabled. Do quota accounting during fsck. */
-               if ((sb->s_usr_quota_inum && sb->s_grp_quota_inum) ||
-                   (!sb->s_usr_quota_inum && !sb->s_grp_quota_inum))
-                       qtype = -1;
-               else
-                       qtype = sb->s_usr_quota_inum ? USRQUOTA : GRPQUOTA;
-
-               quota_init_context(&ctx->qctx, ctx->fs, qtype);
+               clear_problem_context(&pctx);
+               pctx.errcode = quota_init_context(&ctx->qctx, ctx->fs, 0);
+               if (pctx.errcode) {
+                       fix_problem(ctx, PR_0_QUOTA_INIT_CTX, &pctx);
+                       fatal_error(ctx, 0);
+               }
        }
 
        run_result = e2fsck_run(ctx);
@@ -1802,8 +1831,7 @@ print_unsupp_features:
                        if (journal_size < 1024)
                                journal_size = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super));
                        if (journal_size < 0) {
-                               fs->super->s_feature_compat &=
-                                       ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+                               ext2fs_clear_feature_journal(fs->super);
                                fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
                                log_out(ctx, "%s: Couldn't determine "
                                        "journal size\n", ctx->program_name);
@@ -1826,18 +1854,30 @@ print_unsupp_features:
        }
 no_journal:
 
-       if (ctx->qctx) {
-               int i, needs_writeout;
-               for (i = 0; i < MAXQUOTAS; i++) {
-                       if (qtype != -1 && qtype != i)
+       if (run_result & E2F_FLAG_ABORT) {
+               fatal_error(ctx, _("aborted"));
+       } else if (run_result & E2F_FLAG_CANCEL) {
+               log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ?
+                       ctx->device_name : ctx->filesystem_name);
+               exit_value |= FSCK_CANCELED;
+       } else if (ctx->qctx && !ctx->invalid_bitmaps) {
+               int needs_writeout;
+
+               for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
+                       if (*quota_sb_inump(sb, qtype) == 0)
                                continue;
                        needs_writeout = 0;
-                       pctx.num = i;
-                       retval = quota_compare_and_update(ctx->qctx, i,
+                       pctx.num = qtype;
+                       retval = quota_compare_and_update(ctx->qctx, qtype,
                                                          &needs_writeout);
                        if ((retval || needs_writeout) &&
-                           fix_problem(ctx, PR_6_UPDATE_QUOTAS, &pctx))
-                               quota_write_inode(ctx->qctx, i);
+                           fix_problem(ctx, PR_6_UPDATE_QUOTAS, &pctx)) {
+                               pctx.errcode = quota_write_inode(ctx->qctx,
+                                                                1 << qtype);
+                               if (pctx.errcode)
+                                       (void) fix_problem(ctx,
+                                               PR_6_WRITE_QUOTAS, &pctx);
+                       }
                }
                quota_release_context(&ctx->qctx);
        }
@@ -1854,18 +1894,13 @@ no_journal:
                ext2fs_close_free(&ctx->fs);
                goto restart;
        }
-       if (run_result & E2F_FLAG_ABORT)
-               fatal_error(ctx, _("aborted"));
 
 #ifdef MTRACE
        mtrace_print("Cleanup");
 #endif
        was_changed = ext2fs_test_changed(fs);
-       if (run_result & E2F_FLAG_CANCEL) {
-               log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ?
-                       ctx->device_name : ctx->filesystem_name);
-               exit_value |= FSCK_CANCELED;
-       } else if (!(ctx->options & E2F_OPT_READONLY)) {
+       if (!(ctx->flags & E2F_FLAG_RUN_RETURN) &&
+           !(ctx->options & E2F_OPT_READONLY)) {
                if (ext2fs_test_valid(fs)) {
                        if (!(sb->s_state & EXT2_VALID_FS))
                                exit_value |= FSCK_NONDESTRUCT;
@@ -1884,24 +1919,38 @@ no_journal:
                ext2fs_mark_super_dirty(fs);
        }
 
-       e2fsck_write_bitmaps(ctx);
-       if (fs->flags & EXT2_FLAG_DIRTY) {
-               pctx.errcode = ext2fs_flush(ctx->fs);
+       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) {
-               exit_value |= FSCK_NONDESTRUCT;
-               if (!(ctx->options & E2F_OPT_PREEN))
-                       log_out(ctx, _("\n%s: ***** FILE SYSTEM WAS "
-                                      "MODIFIED *****\n"),
+               int fs_fixed = (ctx->flags & E2F_FLAG_PROBLEMS_FIXED);
+
+               if (fs_fixed)
+                       exit_value |= FSCK_NONDESTRUCT;
+               if (!(ctx->options & E2F_OPT_PREEN)) {
+#if 0  /* Do this later; it breaks too many tests' golden outputs */
+                       log_out(ctx, fs_fixed ?
+                               _("\n%s: ***** FILE SYSTEM ERRORS "
+                                 "CORRECTED *****\n") :
+                               _("%s: File system was modified.\n"),
                                ctx->device_name);
+#else
+                       log_out(ctx,
+                               _("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
+                               ctx->device_name);
+#endif
+               }
                if (ctx->mount_flags & EXT2_MF_ISROOT) {
-                       log_out(ctx, _("%s: ***** REBOOT LINUX *****\n"),
+                       log_out(ctx, _("%s: ***** REBOOT SYSTEM *****\n"),
                                ctx->device_name);
                        exit_value |= FSCK_REBOOT;
                }
@@ -1933,6 +1982,8 @@ no_journal:
        ext2fs_close_free(&ctx->fs);
        free(ctx->journal_name);
 
+       if (ctx->logf)
+               fprintf(ctx->logf, "Exit status: %d\n", exit_value);
        e2fsck_free_context(ctx);
        remove_error_table(&et_ext2_error_table);
        remove_error_table(&et_prof_error_table);