* to fix a problem.
*/
static const char *prompt[] = {
- N_("(no prompt)"), /* 0 */
- N_("Fix"), /* 1 */
- N_("Clear"), /* 2 */
- N_("Relocate"), /* 3 */
- N_("Allocate"), /* 4 */
- N_("Expand"), /* 5 */
- N_("Connect to /lost+found"), /* 6 */
- N_("Create"), /* 7 */
- N_("Salvage"), /* 8 */
- N_("Truncate"), /* 9 */
- N_("Clear inode"), /* 10 */
- N_("Abort"), /* 11 */
- N_("Split"), /* 12 */
- N_("Continue"), /* 13 */
- N_("Clone multiply-claimed blocks"), /* 14 */
- N_("Delete file"), /* 15 */
- N_("Suppress messages"),/* 16 */
- N_("Unlink"), /* 17 */
- N_("Clear HTree index"),/* 18 */
- N_("Recreate"), /* 19 */
- N_("Optimize"), /* 20 */
- N_("Clear flag"), /* 21 */
- "", /* 22 */
+ N_("(no prompt)"), /* PROMPT_NONE = 0 */
+ N_("Fix"), /* PROMPT_FIX = 1 */
+ N_("Clear"), /* PROMPT_CLEAR = 2 */
+ N_("Relocate"), /* PROMPT_RELOCATE = 3 */
+ N_("Allocate"), /* PROMPT_CREATE = 4 */
+ N_("Expand"), /* PROMPT_EXPAND = 5 */
+ N_("Connect to /lost+found"), /* PROMPT_CONNECT = 6 */
+ N_("Create"), /* PROMPT_CREATE = 7 */
+ N_("Salvage"), /* PROMPT_SALVAGE = 8 */
+ N_("Truncate"), /* PROMPT_TRUNCATE = 9 */
+ N_("Clear inode"), /* PROMPT_CLEAR_INODE = 10 */
+ N_("Abort"), /* PROMPT_ABORT = 11 */
+ N_("Split"), /* PROMPT_SPLIT = 12 */
+ N_("Continue"), /* PROMPT_CONTINUE = 13 */
+ N_("Clone multiply-claimed blocks"), /* PROMPT_CLONE = 14 */
+ N_("Delete file"), /* PROMPT_DELETE = 15 */
+ N_("Suppress messages"), /* PROMPT_SUPPRESS = 16 */
+ N_("Unlink"), /* PROMPT_UNLINK = 17 */
+ N_("Clear HTree index"), /* PROMPT_CLEAR_HTREE = 18 */
+ N_("Recreate"), /* PROMPT_RECREATE = 19 */
+ N_("Optimize"), /* PROMPT_OPTIMIZE = 20 */
+ N_("Clear flag"), /* PROMPT_CLEAR_FLAG = 21 */
+ "", /* PROMPT_NULL = 22 */
};
/*
/* group descriptor N checksum is invalid, should be yyyy. */
{ PR_0_GDT_CSUM,
N_("@g descriptor %g checksum is %04x, should be %04y. "),
- PROMPT_FIX, PR_LATCH_BG_CHECKSUM, 0, 0, 0 },
+ PROMPT_FIX, PR_PREEN_OK | PR_LATCH_BG_CHECKSUM, 0, 0, 0 },
/* group descriptor N marked uninitialized without feature set. */
{ PR_0_GDT_UNINIT,
"not compatible. Resize @i should be disabled. "),
PROMPT_FIX, 0, 0, 0, 0 },
+ /* Orphan file contains holes */
+ { PR_0_ORPHAN_FILE_HOLE,
+ N_("Orphan file (@i %i) contains hole at @b %b. Terminating orphan file recovery.\n"),
+ PROMPT_NONE, 0 },
+
+ /* Orphan file block has wrong magic */
+ { PR_0_ORPHAN_FILE_BAD_MAGIC,
+ N_("Orphan file (@i %i) @b %b contains wrong magic. Terminating orphan file recovery.\n"),
+ PROMPT_NONE, 0 },
+
+ /* Orphan file block has wrong checksum */
+ { PR_0_ORPHAN_FILE_BAD_CHECKSUM,
+ N_("Orphan file (@i %i) @b %b contains wrong checksum. Terminating orphan file recovery.\n"),
+ PROMPT_NONE, 0 },
+
+ /* Orphan file size isn't multiple of blocks size */
+ { PR_0_ORPHAN_FILE_WRONG_SIZE,
+ N_("Orphan file (@i %i) size is not multiple of block size. Terminating orphan file recovery.\n"),
+ PROMPT_NONE, 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 */
N_("@h %i uses SipHash, but should not. "),
PROMPT_CLEAR_HTREE, PR_PREEN_OK, 0, 0, 0 },
+ /* Orphan file has bad mode */
+ { PR_1_ORPHAN_FILE_BAD_MODE,
+ N_("Orphan file @i %i is not regular file. "),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Orphan file inode is not in use, but contains data */
+ { PR_1_ORPHAN_FILE_NOT_CLEAR,
+ N_("Orphan file @i %i is not in use, but contains data. "),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* 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 */
" %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"),
/* 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 */
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 */
/* Unconnected directory inode */
{ PR_3_UNCONNECTED_DIR,
/* xgettext:no-c-format */
- N_("Unconnected @d @i %i (%p)\n"),
+ N_("Unconnected @d @i %i (was in %q)\n"),
PROMPT_CONNECT, 0, 0, 0, 0 },
/* /lost+found not found */
N_("/@l is encrypted\n"),
PROMPT_CLEAR, 0, 0, 0, 0 },
+ /* Recursively looped directory inode */
+ { PR_3_LOOPED_DIR,
+ /* xgettext:no-c-format */
+ N_("Recursively looped @d @i %i (%p)\n"),
+ PROMPT_CONNECT, 0, 0, 0, 0 },
+
/* Pass 3A Directory Optimization */
/* Pass 3A: Optimizing directories */
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 */
N_("Error writing quota info for quota type %N: %m\n"),
PROMPT_NULL, 0, 0, 0, 0 },
+ /* Orphan file without a journal */
+ { PR_6_ORPHAN_FILE_WITHOUT_JOURNAL,
+ N_("@S has orphan file without @j.\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Orphan file truncation failed */
+ { PR_6_ORPHAN_FILE_TRUNC_FAILED,
+ N_("Failed to truncate orphan file.\n"),
+ PROMPT_NONE, 0 },
+
+ /* Failed to initialize orphan file */
+ { PR_6_ORPHAN_FILE_CORRUPTED,
+ N_("Failed to initialize orphan file.\n"),
+ PROMPT_RECREATE, PR_PREEN_OK },
+
+ /* Cannot fix corrupted orphan file with invalid bitmaps */
+ { PR_6_ORPHAN_FILE_BITMAP_INVALID,
+ N_("Cannot fix corrupted orphan file with invalid bitmaps.\n"),
+ PROMPT_NONE, 0 },
+
+ /* Orphan file creation failed */
+ { PR_6_ORPHAN_FILE_CREATE_FAILED,
+ N_("Failed to truncate orphan file (@i %i).\n"),
+ PROMPT_NONE, 0 },
+
+ /* Orphan file block contains data */
+ { PR_6_ORPHAN_BLOCK_DIRTY,
+ N_("Orphan file (@i %i) @b %b is not clean.\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* orphan_present set but orphan file is empty */
+ { PR_6_ORPHAN_PRESENT_CLEAN_FILE,
+ N_("Feature orphan_present is set but orphan file is clean.\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* orphan_present set but orphan_file is not */
+ { PR_6_ORPHAN_PRESENT_NO_FILE,
+ N_("Feature orphan_present is set but feature orphan_file is not.\n"),
+ PROMPT_CLEAR, PR_PREEN_OK },
+
+ /* Orphan file size isn't multiple of blocks size */
+ { PR_6_ORPHAN_FILE_WRONG_SIZE,
+ N_("Orphan file (@i %i) size is not multiple of block size.\n"),
+ PROMPT_NONE, 0 },
+
+ /* Orphan file contains holes */
+ { PR_6_ORPHAN_FILE_HOLE,
+ N_("Orphan file (@i %i) contains hole at @b %b.\n"),
+ PROMPT_NONE, 0 },
+
{ 0 }
};
int answer = -1;
ldesc = find_latch(mask);
+ if (!ldesc)
+ return answer;
if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
clear_problem_context(&pctx);
answer = fix_problem(ctx, ldesc->end_message, &pctx);
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;
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);
* Do special latch processing. This is where we ask the
* latch question, if it exists
*/
- if (ptr->flags & PR_LATCH_MASK) {
- ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
+ if (ptr->flags & PR_LATCH_MASK &&
+ (ldesc = find_latch(ptr->flags & PR_LATCH_MASK)) != NULL) {
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)
if ((ctx->options & E2F_OPT_PREEN) &&
(ptr->flags & PR_PREEN_OK))
suppress++;
- if ((ptr->flags & PR_LATCH_MASK) &&
- (ldesc->flags & (PRL_YES | PRL_NO)))
+ if (ldesc && (ldesc->flags & (PRL_YES | PRL_NO)))
suppress++;
if (ptr->count == ptr->max_count + 1) {
if (ctx->problem_logf)
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 ?
answer = def_yn;
if (!(ptr->flags & PR_PREEN_NOMSG))
print_answer = 1;
- } else if ((ptr->flags & PR_LATCH_MASK) &&
- (ldesc->flags & (PRL_YES | PRL_NO))) {
+ } else if (ldesc && (ldesc->flags & (PRL_YES | PRL_NO))) {
print_answer = 1;
if (ldesc->flags & PRL_YES)
answer = 1;
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)) {
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,