diff options
-rw-r--r-- | ubifs-utils/fsck.ubifs/check_files.c | 25 | ||||
-rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.c | 7 | ||||
-rw-r--r-- | ubifs-utils/fsck.ubifs/fsck.ubifs.h | 4 | ||||
-rw-r--r-- | ubifs-utils/fsck.ubifs/problem.c | 1 |
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, |