]> www.infradead.org Git - mtd-utils.git/commitdiff
fsck.ubifs: Check and correct the index size
authorZhihao Cheng <chengzhihao1@huawei.com>
Mon, 11 Nov 2024 09:08:11 +0000 (17:08 +0800)
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Mon, 11 Nov 2024 09:32:46 +0000 (10:32 +0100)
This is the 14/18 step of fsck. Check and correct the index size by
traversing TNC just like dbg_check_idx_size does. This step should
be executed after first committing, because 'c->calc_idx_sz' can be
changed in 'ubifs_tnc_start_commit' and the initial value of
'c->calc_idx_sz' read from disk is untrusted.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
ubifs-utils/fsck.ubifs/check_space.c
ubifs-utils/fsck.ubifs/fsck.ubifs.c
ubifs-utils/fsck.ubifs/fsck.ubifs.h
ubifs-utils/fsck.ubifs/problem.c

index afe6ba0be13bf6186482271125dfa7b3d3fe4b94..cff8a7c2b355c11d2a464aa7bcc47639b47ba82a 100644 (file)
@@ -660,3 +660,31 @@ rebuild:
 
        return err;
 }
+
+/**
+ * check_and_correct_index_size - check & correct the index size.
+ * @c: UBIFS file-system description object
+ *
+ * This function checks and corrects the index size by traversing TNC: Returns
+ * zero in case of success, a negative error code in case of failure.
+ */
+int check_and_correct_index_size(struct ubifs_info *c)
+{
+       int err;
+       unsigned long long index_size = 0;
+
+       ubifs_assert(c, c->bi.old_idx_sz == c->calc_idx_sz);
+       err = dbg_walk_index(c, NULL, add_size, &index_size);
+       if (err) {
+               /* All TNC nodes must be accessible. */
+               ubifs_assert(c, !get_failure_reason_callback(c));
+               return err;
+       }
+
+       dbg_fsck("total index size %llu, in %s", index_size, c->dev_name);
+       if (index_size != c->calc_idx_sz &&
+           fix_problem(c, INCORRECT_IDX_SZ, &index_size))
+               c->bi.old_idx_sz = c->calc_idx_sz = index_size;
+
+       return 0;
+}
index 07ed81718321954e2ff4ceaa2543e12cd36de261..80205aac5e5848a0bda05702d5d7a95d75c8d665 100644 (file)
@@ -512,6 +512,13 @@ static int do_fsck(void)
        }
 
        err = commit_fix_modifications(c);
+       if (err) {
+               exit_code |= FSCK_ERROR;
+               goto free_disconnected_files_2;
+       }
+
+       log_out(c, "Check and correct the index size");
+       err = check_and_correct_index_size(c);
        if (err)
                exit_code |= FSCK_ERROR;
 
@@ -567,6 +574,7 @@ int main(int argc, char *argv[])
         * Step 11: Check whether the TNC is empty
         * Step 12: Check and correct the space statistics
         * Step 13: Commit problem fixing modifications
+        * Step 14: Check and correct the index size
         */
        err = do_fsck();
        if (err && FSCK(c)->try_rebuild) {
index 00c157a4368d8ec1b87fa5580735433187cf2a78..ab498ad13a0e3002e0835618d844c8c93a1d6493 100644 (file)
@@ -45,7 +45,7 @@ enum { SB_CORRUPTED = 0, MST_CORRUPTED, LOG_CORRUPTED, BUD_CORRUPTED,
        XATTR_HAS_WRONG_HOST, FILE_HAS_NO_ENCRYPT, FILE_IS_DISCONNECTED,
        FILE_ROOT_HAS_DENT, DENTRY_IS_UNREACHABLE, FILE_IS_INCONSISTENT,
        EMPTY_TNC, LPT_CORRUPTED, NNODE_INCORRECT, PNODE_INCORRECT,
-       LP_INCORRECT, SPACE_STAT_INCORRECT, LTAB_INCORRECT };
+       LP_INCORRECT, SPACE_STAT_INCORRECT, LTAB_INCORRECT, INCORRECT_IDX_SZ };
 
 enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 };
 
@@ -379,5 +379,6 @@ int get_free_leb(struct ubifs_info *c);
 int build_lpt(struct ubifs_info *c, calculate_lp_callback calculate_lp_cb,
              bool free_ltab);
 int check_and_correct_space(struct ubifs_info *c);
+int check_and_correct_index_size(struct ubifs_info *c);
 
 #endif
index f987e480c9a83a29d459149c7ecb5a603984b7e2..32182c91e75474442e14a0cfe6386f485e803e23 100644 (file)
@@ -67,6 +67,7 @@ static const struct fsck_problem problem_table[] = {
        {PROBLEM_FIXABLE | PROBLEM_MUST_FIX, "Inconsistent properties for LEB"},        // LP_INCORRECT
        {PROBLEM_FIXABLE | PROBLEM_MUST_FIX, "Incorrect space statistics"},     // SPACE_STAT_INCORRECT
        {PROBLEM_FIXABLE | PROBLEM_MUST_FIX, "Inconsistent properties for lprops table"},       // LTAB_INCORRECT
+       {PROBLEM_FIXABLE | PROBLEM_MUST_FIX, "Incorrect index size"},   // INCORRECT_IDX_SZ
 };
 
 static const char *get_question(const struct fsck_problem *problem,
@@ -280,6 +281,14 @@ static void print_problem(const struct ubifs_info *c,
                        ssp->calc_lst->total_dead, ssp->calc_lst->total_dark);
                break;
        }
+       case INCORRECT_IDX_SZ:
+       {
+               const unsigned long long *calc_sz = (const unsigned long long *)priv;
+
+               log_out(c, "problem: %s, index size is %llu, should be %llu",
+                       problem->desc, c->calc_idx_sz, *calc_sz);
+               break;
+       }
        default:
                log_out(c, "problem: %s", problem->desc);
                break;