diff options
author | Zhihao Cheng <chengzhihao1@huawei.com> | 2024-11-11 17:08:04 +0800 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2024-11-11 10:32:46 +0100 |
commit | c5ca3893ea854e8d8b5916bc492db8523db70122 (patch) | |
tree | 5817c717593cfb28fc54eb8991f541ea88429bcc /ubifs-utils/fsck.ubifs/check_files.c | |
parent | e708c6f33e51d9cd5565e16c76af2c4180341499 (diff) |
fsck.ubifs: Check and handle invalid files
This is the 8/18 step of fsck. Check and handle invalid files, the
checking rule is same as rebuild mode which has been implemented in
file_is_valid, but the methods of handling are different:
1. Move unattached(file has no dentries) regular file into disconnected
list, let subsequent steps to handle them with lost+found.
2. Make file type be consistent between inode, detries and data nodes by
deleting dentries or data blocks.
3. Delete file for other invalid cases(eg. file has no inode).
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/check_files.c')
-rw-r--r-- | ubifs-utils/fsck.ubifs/check_files.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/ubifs-utils/fsck.ubifs/check_files.c b/ubifs-utils/fsck.ubifs/check_files.c index 0fd6b32..c5c606e 100644 --- a/ubifs-utils/fsck.ubifs/check_files.c +++ b/ubifs-utils/fsck.ubifs/check_files.c @@ -354,3 +354,91 @@ void update_files_size(struct ubifs_info *c) kfree(e); } } + +/** + * handle_invalid_files - Handle invalid files. + * @c: UBIFS file-system description object + * + * This function checks and handles invalid files, there are three situations: + * 1. Move unattached(file has no dentries, or file's parent file has invalid + * type) regular file into disconnected list, let subsequent steps to handle + * them with lost+found. + * 2. Make file type be consistent between inode, detries and data nodes by + * deleting dentries or data blocks. + * 3. Delete file for other invalid cases(eg. file has no inode). + * + * Returns zero in case of success, a negative error code in case of failure. + */ +int handle_invalid_files(struct ubifs_info *c) +{ + int err; + struct rb_node *node; + struct scanned_file *file; + struct rb_root *tree = &FSCK(c)->scanned_files; + LIST_HEAD(tmp_list); + + /* Add all xattr files into a list. */ + for (node = rb_first(tree); node; node = rb_next(node)) { + file = rb_entry(node, struct scanned_file, rb); + + if (file->ino.is_xattr) + list_add(&file->list, &tmp_list); + } + + /* + * Round 1: Traverse xattr files, check whether the xattr file is + * valid, move valid xattr file into corresponding host file's subtree. + */ + while (!list_empty(&tmp_list)) { + file = list_entry(tmp_list.next, struct scanned_file, list); + + list_del(&file->list); + rb_erase(&file->rb, tree); + err = file_is_valid(c, file, tree, NULL); + if (err < 0) { + destroy_file_content(c, file); + kfree(file); + return err; + } else if (!err) { + err = delete_file(c, file); + kfree(file); + if (err) + return err; + } + } + + /* Round 2: Traverse non-xattr files. */ + for (node = rb_first(tree); node; node = rb_next(node)) { + int is_diconnected = 0; + + file = rb_entry(node, struct scanned_file, rb); + err = file_is_valid(c, file, tree, &is_diconnected); + if (err < 0) { + return err; + } else if (!err) { + if (is_diconnected) + list_add(&file->list, &FSCK(c)->disconnected_files); + else + list_add(&file->list, &tmp_list); + } + } + + /* Delete & remove invalid files. */ + while (!list_empty(&tmp_list)) { + file = list_entry(tmp_list.next, struct scanned_file, list); + + list_del(&file->list); + err = delete_file(c, file); + if (err) + return err; + rb_erase(&file->rb, tree); + kfree(file); + } + + /* Remove disconnected file from the file tree. */ + list_for_each_entry(file, &FSCK(c)->disconnected_files, list) { + rb_erase(&file->rb, tree); + } + + return 0; +} |