summaryrefslogtreecommitdiff
path: root/ubifs-utils/fsck.ubifs
diff options
context:
space:
mode:
authorZhihao Cheng <chengzhihao1@huawei.com>2024-11-11 17:01:22 +0800
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2024-11-11 10:32:46 +0100
commitcf844f788d34e1facf142910b955554c69eb8f9b (patch)
tree1da22bb52854b759515661b41ea1fb4b53524a91 /ubifs-utils/fsck.ubifs
parent3f8ee068870a046b0dcf2921ed7ee375f405e49f (diff)
fsck.ubifs: Replay journal
This is the 2/18 step of fsck. Replay journal, update TNC & LPT. There could be following steps and possible errors: Step 1. scan log LEB, get all bud LEBs a. corrupted scanning data in log area: danger mode with rebuild_fs and normal mode with 'yes' answer will turn to rebuild filesystem, other modes will exit. Step 2. scan bud LEBs, get all nodes a. corrupted scanning data in bud LEB: danger mode and normal mode with 'yes' answer will drop bud LEB and set %FR_LPT_INCORRECT for lpt status, other modes will exit. Step 3. apply nodes, record latest isize into size_tree Step 4. apply nodes, update TNC & LPT a. corrupted data searched from TNC: skip node and set %FR_LPT_INCORRECT lpt status for danger mode and normal mode with 'yes' answer, other modes will exit. b. corrupted index node read from TNC: danger mode with rebuild_fs and normal mode with 'yes' answer will turn to rebuild filesystem, other modes will exit. c. corrupted lpt: Set %FR_LPT_CORRUPTED for lpt status. Ignore the error. d. incorrect lpt: Set %FR_LPT_INCORRECT for lpt status. Ignore the error. e. If lpt status is not empty, skip updating lpt. Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
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(),