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/check_files.c25
-rw-r--r--ubifs-utils/fsck.ubifs/fsck.ubifs.c7
-rw-r--r--ubifs-utils/fsck.ubifs/fsck.ubifs.h4
-rw-r--r--ubifs-utils/fsck.ubifs/problem.c1
4 files changed, 36 insertions, 1 deletions
diff --git a/ubifs-utils/fsck.ubifs/check_files.c b/ubifs-utils/fsck.ubifs/check_files.c
index 2be9619..b9f31a7 100644
--- a/ubifs-utils/fsck.ubifs/check_files.c
+++ b/ubifs-utils/fsck.ubifs/check_files.c
@@ -499,3 +499,28 @@ int handle_dentry_tree(struct ubifs_info *c)
return 0;
}
+
+/**
+ * tnc_is_empty - Check whether the TNC is empty.
+ * @c: UBIFS file-system description object
+ *
+ * Returns %true if the TNC is empty, otherwise %false is returned.
+ */
+bool tnc_is_empty(struct ubifs_info *c)
+{
+ /*
+ * Check whether the TNC is empty, turn to rebuild_fs if it is empty.
+ * Can we recreate a new root dir to avoid empty TNC? The answer is no,
+ * lpt fixing should be done before creating new entry, but lpt fixing
+ * needs a committing before new dirty data generated to ensure that
+ * bud data won't be overwritten(bud LEB could become freeable after
+ * replaying journal, corrected lpt may treat it as a free one to hold
+ * new data, see details in space checking & correcting step). Then we
+ * have to create the new root dir after fixing lpt and a committing,
+ * znode without children(empty TNC) maybe written on disk at the
+ * moment of committing, which corrupts the UBIFS image. So we choose
+ * to rebuild the filesystem if the TNC is empty, this case is
+ * equivalent to corrupted TNC.
+ */
+ return c->zroot.znode->child_cnt == 0;
+}
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
index 3f61668..cd498f5 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
@@ -467,6 +467,12 @@ static int do_fsck(void)
goto free_disconnected_files;
}
+ log_out(c, "Check whether the TNC is empty");
+ if (tnc_is_empty(c) && fix_problem(c, EMPTY_TNC, NULL)) {
+ err = -EINVAL;
+ FSCK(c)->try_rebuild = true;
+ }
+
free_disconnected_files:
destroy_file_list(c, &FSCK(c)->disconnected_files);
free_used_lebs:
@@ -512,6 +518,7 @@ int main(int argc, char *argv[])
* Step 8: Check and handle invalid files
* Step 9: Check and handle unreachable files
* Step 10: Check and correct files
+ * Step 11: Check whether the TNC is empty
*/
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 32a991d..3c0f2af 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -43,7 +43,8 @@ enum { SB_CORRUPTED = 0, MST_CORRUPTED, LOG_CORRUPTED, BUD_CORRUPTED,
FILE_HAS_0_NLINK_INODE, FILE_HAS_INCONSIST_TYPE, FILE_HAS_TOO_MANY_DENT,
FILE_SHOULDNT_HAVE_DATA, FILE_HAS_NO_DENT, XATTR_HAS_NO_HOST,
XATTR_HAS_WRONG_HOST, FILE_HAS_NO_ENCRYPT, FILE_IS_DISCONNECTED,
- FILE_ROOT_HAS_DENT, DENTRY_IS_UNREACHABLE, FILE_IS_INCONSISTENT };
+ FILE_ROOT_HAS_DENT, DENTRY_IS_UNREACHABLE, FILE_IS_INCONSISTENT,
+ EMPTY_TNC };
enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 };
@@ -318,5 +319,6 @@ int traverse_tnc_and_construct_files(struct ubifs_info *c);
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);
#endif
diff --git a/ubifs-utils/fsck.ubifs/problem.c b/ubifs-utils/fsck.ubifs/problem.c
index e8f0860..795f05f 100644
--- a/ubifs-utils/fsck.ubifs/problem.c
+++ b/ubifs-utils/fsck.ubifs/problem.c
@@ -60,6 +60,7 @@ static const struct fsck_problem problem_table[] = {
{PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA, "Root dir should not have a dentry"}, // FILE_ROOT_HAS_DENT
{PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA, "Dentry is unreachable"}, // DENTRY_IS_UNREACHABLE
{PROBLEM_FIXABLE | PROBLEM_MUST_FIX, "File is inconsistent"}, // FILE_IS_INCONSISTENT
+ {PROBLEM_FIXABLE | PROBLEM_MUST_FIX | PROBLEM_DROP_DATA | PROBLEM_NEED_REBUILD, "TNC is empty"}, // EMPTY_TNC
};
static const char *get_question(const struct fsck_problem *problem,