[RFC PATCH mtd-utils 094/110] fsck.ubifs: Check and create the root dir

From: Zhihao Cheng
Date: Fri Jun 07 2024 - 00:51:17 EST


This is the 15/18 step of fsck. Check whether the root dir is existed,
create a new one if it is not found. This step makes sure that filesystem
can be mounted successful.

Signed-off-by: Zhihao Cheng <chengzhihao1@xxxxxxxxxx>
---
ubifs-utils/fsck.ubifs/check_files.c | 29 +++++++++++++++++++++++++++++
ubifs-utils/fsck.ubifs/fsck.ubifs.c | 8 ++++++++
ubifs-utils/fsck.ubifs/fsck.ubifs.h | 4 +++-
ubifs-utils/fsck.ubifs/problem.c | 3 +++
4 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/ubifs-utils/fsck.ubifs/check_files.c b/ubifs-utils/fsck.ubifs/check_files.c
index 4190bf91..d52a5660 100644
--- a/ubifs-utils/fsck.ubifs/check_files.c
+++ b/ubifs-utils/fsck.ubifs/check_files.c
@@ -524,3 +524,32 @@ bool tnc_is_empty(struct ubifs_info *c)
*/
return c->zroot.znode->child_cnt == 0;
}
+
+/**
+ * check_and_create_root - Check and create root dir.
+ * @c: UBIFS file-system description object
+ *
+ * This function checks whether the root dir is existed, create a new root
+ * dir if it doesn't exist. Returns zero in case of success, a negative error
+ * code in case of failure.
+ */
+int check_and_create_root(struct ubifs_info *c)
+{
+ int err;
+ struct ubifs_inode *ui = ubifs_lookup_by_inum(c, UBIFS_ROOT_INO);
+
+ if (!IS_ERR(ui)) {
+ /* The root dir is found. */
+ dbg_fsck("root dir is found, in %s", c->dev_name);
+ kfree(ui);
+ return 0;
+ }
+
+ err = PTR_ERR(ui);
+ if (err != -ENOENT)
+ return err;
+
+ fix_problem(c, ROOT_DIR_NOT_FOUND, NULL);
+ dbg_fsck("root dir is lost, create a new one, in %s", c->dev_name);
+ return ubifs_create_root(c);
+}
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
index d3525e30..584965fc 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
@@ -519,6 +519,13 @@ static int do_fsck(void)

log_out(c, "Check and correct the index size");
err = check_and_correct_index_size(c);
+ if (err) {
+ exit_code |= FSCK_ERROR;
+ goto free_disconnected_files_2;
+ }
+
+ log_out(c, "Check and create root dir");
+ err = check_and_create_root(c);
if (err)
exit_code |= FSCK_ERROR;

@@ -575,6 +582,7 @@ int main(int argc, char *argv[])
* Step 12: Check and correct the space statistics
* Step 13: Commit problem fixing modifications
* Step 14: Check and correct the index size
+ * Step 15: Check and create root dir
*/
err = do_fsck();
if (err && FSCK(c)->try_rebuild) {
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
index 2d17b205..5c305ba0 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -45,7 +45,8 @@ 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, INCORRECT_IDX_SZ };
+ LP_INCORRECT, SPACE_STAT_INCORRECT, LTAB_INCORRECT, INCORRECT_IDX_SZ,
+ ROOT_DIR_NOT_FOUND };

enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 };

@@ -374,6 +375,7 @@ void update_files_size(struct ubifs_info *c);
int handle_invalid_files(struct ubifs_info *c);
int handle_dentry_tree(struct ubifs_info *c);
bool tnc_is_empty(struct ubifs_info *c);
+int check_and_create_root(struct ubifs_info *c);

/* check_space.c */
int get_free_leb(struct ubifs_info *c);
diff --git a/ubifs-utils/fsck.ubifs/problem.c b/ubifs-utils/fsck.ubifs/problem.c
index 32182c91..8e7e1e15 100644
--- a/ubifs-utils/fsck.ubifs/problem.c
+++ b/ubifs-utils/fsck.ubifs/problem.c
@@ -68,6 +68,7 @@ static const struct fsck_problem problem_table[] = {
{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
+ {PROBLEM_FIXABLE | PROBLEM_MUST_FIX, "Root dir is lost"}, // ROOT_DIR_NOT_FOUND
};

static const char *get_question(const struct fsck_problem *problem,
@@ -105,6 +106,8 @@ static const char *get_question(const struct fsck_problem *problem,
return "Put it into disconnected list?";
case LPT_CORRUPTED:
return "Rebuild LPT?";
+ case ROOT_DIR_NOT_FOUND:
+ return "Create a new one?";
}

return "Fix it?";
--
2.13.6