aboutsummaryrefslogtreecommitdiff
path: root/ubifs-utils/fsck.ubifs
diff options
context:
space:
mode:
Diffstat (limited to 'ubifs-utils/fsck.ubifs')
-rw-r--r--ubifs-utils/fsck.ubifs/fsck.ubifs.c11
-rw-r--r--ubifs-utils/fsck.ubifs/fsck.ubifs.h5
-rw-r--r--ubifs-utils/fsck.ubifs/load_fs.c29
-rw-r--r--ubifs-utils/fsck.ubifs/problem.c39
4 files changed, 71 insertions, 13 deletions
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
index 2fd68df..85175cf 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
@@ -325,13 +325,17 @@ static bool fsck_can_ignore_failure(const struct ubifs_info *c,
return false;
}
-static const unsigned int reason_mapping_table[] = {};
+static const unsigned int reason_mapping_table[] = {
+ BUD_CORRUPTED, /* FR_H_BUD_CORRUPTED */
+ TNC_DATA_CORRUPTED, /* FR_H_TNC_DATA_CORRUPTED */
+};
-static bool fsck_handle_failure(const struct ubifs_info *c, unsigned int reason)
+static bool fsck_handle_failure(const struct ubifs_info *c, unsigned int reason,
+ void *priv)
{
ubifs_assert(c, FSCK(c)->mode != REBUILD_MODE);
- return fix_problem(c, reason_mapping_table[reason]);
+ return fix_problem(c, reason_mapping_table[reason], priv);
}
static void signal_cancel(int sig)
@@ -426,6 +430,7 @@ int main(int argc, char *argv[])
/*
* Init: Read superblock
* Step 1: Read master & init lpt
+ * Step 2: Replay journal
*/
err = ubifs_load_filesystem(c);
if (err) {
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
index 7f82615..f1da974 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -37,7 +37,8 @@ enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,
DANGER_MODE1, REBUILD_MODE, CHECK_MODE };
/* Types of inconsistent problems */
-enum { SB_CORRUPTED = 0, MST_CORRUPTED };
+enum { SB_CORRUPTED = 0, MST_CORRUPTED, LOG_CORRUPTED, BUD_CORRUPTED,
+ TNC_CORRUPTED, TNC_DATA_CORRUPTED };
struct scanned_file;
@@ -259,7 +260,7 @@ static inline const char *mode_name(const struct ubifs_info *c)
extern int exit_code;
/* problem.c */
-bool fix_problem(const struct ubifs_info *c, int problem_type);
+bool fix_problem(const struct ubifs_info *c, int problem_type, const void *priv);
/* load_fs.c */
int ubifs_load_filesystem(struct ubifs_info *c);
diff --git a/ubifs-utils/fsck.ubifs/load_fs.c b/ubifs-utils/fsck.ubifs/load_fs.c
index 036e307..f45c411 100644
--- a/ubifs-utils/fsck.ubifs/load_fs.c
+++ b/ubifs-utils/fsck.ubifs/load_fs.c
@@ -72,7 +72,7 @@ int ubifs_load_filesystem(struct ubifs_info *c)
err = ubifs_read_superblock(c);
if (err) {
if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED))
- fix_problem(c, SB_CORRUPTED);
+ fix_problem(c, SB_CORRUPTED, NULL);
exit_code |= FSCK_ERROR;
goto out_mounting;
}
@@ -103,7 +103,7 @@ int ubifs_load_filesystem(struct ubifs_info *c)
err = ubifs_read_master(c);
if (err) {
if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED)) {
- if (fix_problem(c, MST_CORRUPTED))
+ if (fix_problem(c, MST_CORRUPTED, NULL))
FSCK(c)->try_rebuild = true;
} else
exit_code |= FSCK_ERROR;
@@ -161,10 +161,34 @@ int ubifs_load_filesystem(struct ubifs_info *c)
c->superblock_need_write = 0;
}
+ log_out(c, "Replay journal");
+ err = ubifs_replay_journal(c);
+ if (err) {
+ unsigned int reason = get_failure_reason_callback(c);
+
+ clear_failure_reason_callback(c);
+ if (reason & FR_DATA_CORRUPTED) {
+ if (fix_problem(c, LOG_CORRUPTED, NULL))
+ FSCK(c)->try_rebuild = true;
+ } else if (reason & FR_TNC_CORRUPTED) {
+ if (fix_problem(c, TNC_CORRUPTED, NULL))
+ FSCK(c)->try_rebuild = true;
+ } else {
+ ubifs_assert(c, reason == 0);
+ exit_code |= FSCK_ERROR;
+ }
+ goto out_journal;
+ }
+
+ /* Calculate 'min_idx_lebs' after journal replay */
+ c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c);
+
c->mounting = 0;
return 0;
+out_journal:
+ destroy_journal(c);
out_lpt:
ubifs_lpt_free(c, 0);
out_master:
@@ -188,6 +212,7 @@ out_free:
void ubifs_destroy_filesystem(struct ubifs_info *c)
{
+ destroy_journal(c);
free_wbufs(c);
ubifs_lpt_free(c, 0);
diff --git a/ubifs-utils/fsck.ubifs/problem.c b/ubifs-utils/fsck.ubifs/problem.c
index 1af6663..9df2c2a 100644
--- a/ubifs-utils/fsck.ubifs/problem.c
+++ b/ubifs-utils/fsck.ubifs/problem.c
@@ -37,12 +37,39 @@ struct fsck_problem {
static const struct fsck_problem problem_table[] = {
{0, "Corrupted superblock"}, // SB_CORRUPTED
{PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA | PROBLEM_NEED_REBUILD, "Corrupted master node"}, // MST_CORRUPTED
+ {PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA | PROBLEM_NEED_REBUILD, "Corrupted log area"}, // LOG_CORRUPTED
+ {PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA, "Corrupted bud LEB"}, // BUD_CORRUPTED
+ {PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA | PROBLEM_NEED_REBUILD, "Corrupted index node"}, // TNC_CORRUPTED
+ {PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA, "Corrupted data searched from TNC"}, // TNC_DATA_CORRUPTED
};
+static const char *get_question(const struct fsck_problem *problem,
+ int problem_type)
+{
+ if (problem->flags & PROBLEM_NEED_REBUILD)
+ return "Rebuild filesystem?";
+
+ switch (problem_type) {
+ case BUD_CORRUPTED:
+ return "Drop bud?";
+ case TNC_DATA_CORRUPTED:
+ return "Drop it?";
+ }
+
+ return "Fix it?";
+}
+
static void print_problem(const struct ubifs_info *c,
- const struct fsck_problem *problem)
+ const struct fsck_problem *problem, int problem_type,
+ const void *priv)
{
- log_out(c, "problem: %s", problem->desc);
+ if (problem_type == BUD_CORRUPTED) {
+ const struct ubifs_bud *bud = (const struct ubifs_bud *)priv;
+
+ log_out(c, "problem: %s %d:%d %s", problem->desc, bud->lnum,
+ bud->start, dbg_jhead(bud->jhead));
+ } else
+ log_out(c, "problem: %s", problem->desc);
}
static void fatal_error(const struct ubifs_info *c,
@@ -59,17 +86,17 @@ static void fatal_error(const struct ubifs_info *c,
* fix_problem - whether fixing the inconsistent problem
* @c: UBIFS file-system description object
* @problem_type: the type of inconsistent problem
+ * @priv: private data for problem instance
*
* This function decides to fix/skip the inconsistent problem or abort the
* program according to @problem_type, returns %true if the problem should
* be fixed, returns %false if the problem will be skipped.
*/
-bool fix_problem(const struct ubifs_info *c, int problem_type)
+bool fix_problem(const struct ubifs_info *c, int problem_type, const void *priv)
{
bool ans, ask = true, def_y = true;
const struct fsck_problem *problem = &problem_table[problem_type];
- const char *question = (problem->flags & PROBLEM_NEED_REBUILD) ?
- "Rebuild filesystem?" : "Fix it?";
+ const char *question = get_question(problem, problem_type);
ubifs_assert(c, FSCK(c)->mode != REBUILD_MODE);
@@ -88,7 +115,7 @@ bool fix_problem(const struct ubifs_info *c, int problem_type)
(FSCK(c)->mode == DANGER_MODE0 || FSCK(c)->mode == DANGER_MODE1))
ask = false;
- print_problem(c, problem);
+ print_problem(c, problem, problem_type, priv);
ans = def_y;
if (FSCK(c)->mode == NORMAL_MODE) {
printf("%s[%d] (%s%s)", c->program_name, getpid(),