Whamcloud - gitweb
LU-1540 e2fsck: add missing symlink NUL terminator
[tools/e2fsprogs.git] / e2fsck / problem.c
index f8882a5..16c858e 100644 (file)
@@ -526,6 +526,14 @@ static struct e2fsck_problem problem_table[] = {
             "not compatible. Resize @i should be disabled.  "),
          PROMPT_FIX, 0, 0, 0, 0 },
 
+       { PR_0_MIN_EXTRA_ISIZE_INVALID,
+         N_("@S has invalid s_min_extra_isize.  "),
+         PROMPT_FIX, PR_PREEN_OK },
+
+       { PR_0_WANT_EXTRA_ISIZE_INVALID,
+         N_("@S has invalid s_want_extra_isize.  "),
+         PROMPT_FIX, PR_PREEN_OK },
+
        /* Pass 1 errors */
 
        /* Pass 1: Checking inodes, blocks, and sizes */
@@ -1199,9 +1207,9 @@ static struct e2fsck_problem problem_table[] = {
          N_("@i %i has a duplicate @x mapping\n\t(logical @b %c, @n physical @b %b, len %N)\n"),
          PROMPT_CLEAR, 0, 0, 0, 0 },
 
-       /* Error allocating memory for encrypted directory list */
-       { PR_1_ALLOCATE_ENCRYPTED_DIRLIST,
-         N_("@A memory for encrypted @d list\n"),
+       /* Error allocating memory for encrypted inode list */
+       { PR_1_ALLOCATE_ENCRYPTED_INODE_LIST,
+         N_("@A %N bytes of memory for encrypted @i list\n"),
          PROMPT_NONE, PR_FATAL, 0, 0, 0 },
 
        /* Inode extent tree could be more shallow */
@@ -1243,6 +1251,12 @@ static struct e2fsck_problem problem_table[] = {
          N_("EA @i %N for parent @i %i missing EA_INODE flag.\n "),
          PROMPT_FIX, PR_PREEN_OK, 0, 0, 0 },
 
+       /* Offer to clear uninitialized flag on an extent */
+       { PR_1_CLEAR_UNINIT_EXTENT,
+         /* xgettext:no-c-format */
+         N_("@i %i has @x marked uninitialized at @b %c (len %N).  "),
+         PROMPT_CLEAR, PR_PREEN_OK, 0, 0, 0 },
+
        /* Casefold flag set on a non-directory */
        { PR_1_CASEFOLD_NONDIR,
          N_("@i %i has the casefold flag set but is not a directory.  "),
@@ -1253,6 +1267,72 @@ static struct e2fsck_problem problem_table[] = {
          N_("@d %p has the casefold flag, but the\ncasefold feature is not enabled.  "),
          PROMPT_CLEAR_FLAG, 0, 0, 0, 0 },
 
+       /* Inode has encrypt flag but no encryption extended attribute */
+       { PR_1_MISSING_ENCRYPTION_XATTR,
+         N_("@i %i has encrypt flag but no encryption @a.\n"),
+         PROMPT_CLEAR_FLAG, 0, 0, 0, 0 },
+
+       /* Encrypted inode has corrupt encryption extended attribute */
+       { PR_1_CORRUPT_ENCRYPTION_XATTR,
+         N_("Encrypted @i %i has corrupt encryption @a.\n"),
+         PROMPT_CLEAR_INODE, 0, 0, 0, 0 },
+
+       /* Htree directory should use SipHash but does not */
+       { PR_1_HTREE_NEEDS_SIPHASH,
+         N_("@h %i uses hash version (%N), but should use SipHash (6) \n"),
+         PROMPT_CLEAR_HTREE, PR_PREEN_OK, 0, 0, 0 },
+
+       /* Htree directory uses SipHash but should not */
+       { PR_1_HTREE_CANNOT_SIPHASH,
+         N_("@h %i uses SipHash, but should not.  "),
+         PROMPT_CLEAR_HTREE, PR_PREEN_OK, 0, 0, 0 },
+
+       /* expand inode */
+       { PR_1_EXPAND_EISIZE_WARNING,
+         N_("\ne2fsck is being run with \"expand_extra_isize\" option or\n"
+            "s_min_extra_isize of %d bytes has been set in the superblock.\n"
+            "Inode %i does not have enough free space.  Either some EAs\n"
+            "need to be deleted from this inode or the RO_COMPAT_EXTRA_ISIZE\n"
+            "flag must be cleared.\n\n"), PROMPT_NONE, PR_PREEN_OK | PR_NO_OK |
+            PR_PREEN_NOMSG },
+
+       /* expand inode */
+       { PR_1_EXPAND_EISIZE,
+         N_("Expanding @i %i.\n"),
+         PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG },
+
+       /* delete an EA so that EXTRA_ISIZE feature may be enabled */
+       { PR_1_EISIZE_DELETE_EA,
+         N_("Delete EA %s of @i %i so that EXTRA_ISIZE feature may be "
+            "enabled?\n"), PROMPT_FIX, PR_NO_OK | PR_PREEN_NO },
+
+       /* an EA needs to be deleted by e2fsck is being run with -p or -y */
+       { PR_1_EA_BLK_NOSPC,
+         N_("An EA needs to be deleted for @i %i but e2fsck is being run\n"
+            "with -p or -y mode.\n"),
+         PROMPT_ABORT, 0 },
+
+       /* disable EXTRA_ISIZE feature since inode cannot be expanded */
+       { PR_1_CLEAR_EXTRA_ISIZE,
+         N_("Disable EXTRA_ISIZE feature since @i %i cannot be expanded\n"
+            "without deletion of an EA.\n"),
+         PROMPT_FIX, 0 },
+
+       /* invalid inode creation time */
+       { PR_1_CRTIME_BAD,
+         N_("@i %i creation time (%t) invalid.\n"),
+         PROMPT_CLEAR, PR_PREEN_OK | PR_NO_OK },
+
+       /* Bad extended attribute value in inode */
+       { PR_1_SYMLINK_NUL,
+         N_("@i %i symlink missing NUL terminator.  "),
+         PROMPT_FIX, 0},
+
+       /* Failed to goto block group */
+       { PR_1_SCAN_GOTO,
+         N_("failed to goto block group"),
+          PROMPT_NONE, PR_FATAL, 0, 0, 0 },
+
        /* Pass 1b errors */
 
        /* Pass 1B: Rescan for duplicate/bad blocks */
@@ -1305,6 +1385,11 @@ static struct e2fsck_problem problem_table[] = {
          " %b--%c",
          PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR, 0, 0, 0 },
 
+       /* Inode is badly corrupt (badness value = ) */
+       { PR_1B_INODE_TOOBAD,
+         N_("@i %i is badly corrupt (badness value = %N).  "),
+         PROMPT_CLEAR, PR_PREEN_OK },
+
        /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
        { PR_1C_PASS_HEADER,
          N_("Pass 1C: Scanning directories for @is with @m @bs\n"),
@@ -1355,6 +1440,14 @@ static struct e2fsck_problem problem_table[] = {
          /* xgettext:no-c-format */
          N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0, 0, 0, 0 },
 
+       /* File with shared blocks found */
+       { PR_1D_DISCONNECT_QUESTION,
+         N_("File with shared blocks found\n"), PROMPT_CONNECT, 0 },
+
+       /* Couldn't unlink file (error) */
+       { PR_1D_DISCONNECT_ERROR,
+         N_("Couldn't unlink file: %m\n"), PROMPT_NONE, 0 },
+
        /* Pass 1E Extent tree optimization     */
 
        /* Pass 1E: Optimizing extent trees */
@@ -1639,7 +1732,7 @@ static struct e2fsck_problem problem_table[] = {
        /* Filesystem contains large files, but has no such flag in sb */
        { PR_2_FEATURE_LARGE_FILES,
          N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
-         PROMPT_FIX, 0, 0, 0, 0 },
+         PROMPT_FIX, PR_PREEN_OK, 0, 0, 0 },
 
        /* Node in HTREE directory not referenced */
        { PR_2_HTREE_NOTREF,
@@ -1665,6 +1758,11 @@ static struct e2fsck_problem problem_table[] = {
        { PR_2_HTREE_CLEAR,
          N_("@n @h %d (%q).  "), PROMPT_CLEAR_HTREE, 0, 0, 0, 0 },
 
+       /* Filesystem has large directories, but has no such flag in sb */
+       { PR_2_FEATURE_LARGE_DIRS,
+         N_("@f has large directories, but lacks LARGE_DIR flag in @S.\n"),
+         PROMPT_FIX, PR_PREEN_OK, 0, 0, 0 },
+
        /* Bad block in htree interior node */
        { PR_2_HTREE_BADBLK,
          N_("@p @h %d (%q): bad @b number %b.\n"),
@@ -1675,7 +1773,7 @@ static struct e2fsck_problem problem_table[] = {
          N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
          PROMPT_NONE, PR_FATAL, 0, 0, 0 },
 
-       /* Invalid HTREE root node */
+       /* Problem in HTREE directory inode: root node is invalid */
        { PR_2_HTREE_BAD_ROOT,
          /* xgettext:no-c-format */
          N_("@p @h %d: root node is @n\n"),
@@ -1779,11 +1877,36 @@ static struct e2fsck_problem problem_table[] = {
          N_("Encrypted @E is too short.\n"),
          PROMPT_CLEAR, 0, 0, 0, 0 },
 
+       /* Encrypted directory contains unencrypted file */
+       { PR_2_UNENCRYPTED_FILE,
+         N_("Encrypted @E references unencrypted @i %Di.\n"),
+         PROMPT_CLEAR, 0, 0, 0, 0 },
+
+       /* Encrypted directory contains file with different encryption policy */
+       { PR_2_INCONSISTENT_ENCRYPTION_POLICY,
+         N_("Encrypted @E references @i %Di, which has a different encryption policy.\n"),
+         PROMPT_CLEAR, 0, 0, 0, 0 },
+
+       /* Casefolded directory entry has illegal characters in its name */
+       { PR_2_BAD_ENCODED_NAME,
+         N_("@E has illegal UTF-8 characters in its name.\n"),
+         PROMPT_FIX, 0, 0, 0, 0 },
+
         /* Non-unique filename found, but can't rename */
         { PR_2_NON_UNIQUE_FILE_NO_RENAME,
           N_("Duplicate filename @E found.  "),
           PROMPT_CLEAR, 0, 0, 0, 0 },
 
+       /* Inode is badly corrupt (badness value = ) */
+       { PR_2_INODE_TOOBAD,
+         N_("@i %i is badly corrupt (badness value = %N).  "),
+         PROMPT_CLEAR, PR_PREEN_OK },
+
+       /* Directory entry dirdata length set incorrectly */
+       { PR_2_CLEAR_DIRDATA,
+         N_("@E dirdata length set incorrectly.\n"),
+         PROMPT_CLEAR, PR_PREEN_OK },
+
        /* Pass 3 errors */
 
        /* Pass 3: Checking directory connectivity */
@@ -2176,6 +2299,11 @@ static struct e2fsck_problem problem_table[] = {
          N_("@g %g @b @B does not match checksum.\n"),
          PROMPT_FIX, PR_LATCH_BBITMAP | PR_PREEN_OK, 0, 0, 0 },
 
+       /* Expand inode */
+       { PR_5_EXPAND_EISIZE,
+         N_("Expanding @i %i.\n"),
+         PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_PREEN_NOMSG },
+
        /* Post-Pass 5 errors */
 
        /* Recreate journal if E2F_FLAG_JOURNAL_INODE flag is set */
@@ -2338,11 +2466,11 @@ static void print_problem(FILE *f, problem_t code, int answer, int fixed,
        if (pctx->dir)
                fprintf(f, " dir=\"%u\"", pctx->dir);
        if (pctx->blk)
-               fprintf(f, " blk=\"%llu\"", pctx->blk);
+               fprintf(f, " blk=\"%llu\"", (unsigned long long) pctx->blk);
        if (pctx->blk2)
-               fprintf(f, " blk2=\"%llu\"", pctx->blk2);
+               fprintf(f, " blk2=\"%llu\"", (unsigned long long) pctx->blk2);
        if (pctx->blkcount != (e2_blkcnt_t) -1)
-               fprintf(f, " blkcount=\"%lld\"", pctx->blkcount);
+               fprintf(f, " blkcount=\"%lld\"", (unsigned long long) pctx->blkcount);
        if (pctx->group != (dgrp_t) -1)
                fprintf(f, " group=\"%u\"", pctx->group);
        if (pctx->csum1)
@@ -2350,15 +2478,16 @@ static void print_problem(FILE *f, problem_t code, int answer, int fixed,
        if (pctx->csum2)
                fprintf(f, " csum2=\"%u\"", pctx->csum2);
        if (pctx->num)
-               fprintf(f, " num=\"%llu\"", pctx->num);
+               fprintf(f, " num=\"%llu\"", (unsigned long long) pctx->num);
        if (pctx->num2)
-               fprintf(f, " num2=\"%llu\"", pctx->num2);
+               fprintf(f, " num2=\"%llu\"", (unsigned long long) pctx->num2);
        if (pctx->str)
                fprintf(f, " str=\"%s\"", pctx->str);
        fputs("/>\n", f);
 }
 
-int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
+int fix_problem_loc(e2fsck_t ctx, problem_t code, struct problem_context *pctx,
+                   int badness, const char *func, const int line)
 {
        ext2_filsys fs = ctx->fs;
        struct e2fsck_problem *ptr;
@@ -2369,6 +2498,10 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        int             suppress = 0;
        int             fixed = 0;
 
+       /* ino is always set in pass1, where we will hit most badness */
+       if (pctx && pctx->ino != 0 && badness && code < PR_3_PASS_HEADER)
+               e2fsck_mark_inode_bad_loc(ctx, pctx, code, badness, func, line);
+
        ptr = find_problem(code);
        if (!ptr) {
                printf(_("Unhandled error code (0x%x)!\n"), code);
@@ -2416,7 +2549,8 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        if (ptr->flags & PR_LATCH_MASK) {
                ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
                if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
-                       ans = fix_problem(ctx, ldesc->question, pctx);
+                       ans = fix_problem_loc(ctx, ldesc->question, pctx,
+                                             0, func, line);
                        if (ans == 1)
                                ldesc->flags |= PRL_YES;
                        if (ans == 0)
@@ -2455,6 +2589,12 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        if (*message)
                message = _(message);
        if (!suppress) {
+#ifdef HAVE_PTHREAD
+               if ((ctx->options & E2F_OPT_MULTITHREAD) && ctx->global_ctx)
+                       printf("[Thread %d] ",
+                              ctx->thread_info.et_thread_index);
+#endif
+
                if ((ctx->options & E2F_OPT_PREEN) &&
                    !(ptr->flags & PR_PREEN_NOHDR)) {
                        printf("%s: ", ctx->device_name ?
@@ -2513,7 +2653,8 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
                fatal_error(ctx, 0);
 
        if (ptr->flags & PR_AFTER_CODE)
-               answer = fix_problem(ctx, ptr->second_code, pctx);
+               answer = fix_problem_loc(ctx, ptr->second_code, pctx,
+                                        0, func, line);
 
        if (answer && (ptr->prompt != PROMPT_NONE) &&
            !(ptr->flags & PR_NOT_A_FIX)) {
@@ -2564,6 +2705,13 @@ void preenhalt(e2fsck_t ctx)
        return;
 }
 
+void e2fsck_mark_inode_bad_loc(e2fsck_t ctx,
+                              struct problem_context *pctx, __u32 code,
+                              int count, const char *func, const int line)
+{
+       return;
+}
+
 errcode_t
 profile_get_string(profile_t profile, const char *name, const char *subname,
                   const char *subsubname, const char *def_val,