aboutsummaryrefslogtreecommitdiff
path: root/ubifs-utils/fsck.ubifs/fsck.ubifs.h
diff options
context:
space:
mode:
Diffstat (limited to 'ubifs-utils/fsck.ubifs/fsck.ubifs.h')
-rw-r--r--ubifs-utils/fsck.ubifs/fsck.ubifs.h392
1 files changed, 392 insertions, 0 deletions
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
new file mode 100644
index 0000000..6529932
--- /dev/null
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024, Huawei Technologies Co, Ltd.
+ *
+ * Authors: Zhihao Cheng <chengzhihao1@huawei.com>
+ */
+
+#ifndef __FSCK_UBIFS_H__
+#define __FSCK_UBIFS_H__
+
+/* Exit codes used by fsck-type programs */
+#define FSCK_OK 0 /* No errors */
+#define FSCK_NONDESTRUCT 1 /* File system errors corrected */
+#define FSCK_REBOOT 2 /* System should be rebooted */
+#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
+#define FSCK_ERROR 8 /* Operational error */
+#define FSCK_USAGE 16 /* Usage or syntax error */
+#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
+#define FSCK_LIBRARY 128 /* Shared library error */
+
+/*
+ * There are 6 working modes for fsck:
+ * NORMAL_MODE: Check the filesystem, ask user whether or not to fix the
+ * problem as long as inconsistent data is found during checking.
+ * SAFE_MODE: Check and safely repair the filesystem, if there are any
+ * data dropping operations needed by fixing, fsck will fail.
+ * DANGER_MODE0:Check and repair the filesystem according to TNC, data dropping
+ * will be reported. If TNC/master/log is corrupted, fsck will fail.
+ * DANGER_MODE1:Check and forcedly repair the filesystem according to TNC,
+ * turns to @REBUILD_MODE mode automatically if TNC/master/log is
+ * corrupted.
+ * REBUILD_MODE:Scan entire UBI volume to find all nodes, and rebuild the
+ * filesystem, always make fsck success.
+ * CHECK_MODE: Make no changes to the filesystem, only check the filesystem.
+ */
+enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,
+ DANGER_MODE1, REBUILD_MODE, CHECK_MODE };
+
+/* Types of inconsistent problems */
+enum { SB_CORRUPTED = 0, MST_CORRUPTED, LOG_CORRUPTED, BUD_CORRUPTED,
+ TNC_CORRUPTED, TNC_DATA_CORRUPTED, ORPHAN_CORRUPTED, INVALID_INO_NODE,
+ INVALID_DENT_NODE, INVALID_DATA_NODE, SCAN_CORRUPTED, FILE_HAS_NO_INODE,
+ 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,
+ EMPTY_TNC, LPT_CORRUPTED, NNODE_INCORRECT, PNODE_INCORRECT,
+ LP_INCORRECT, SPACE_STAT_INCORRECT, LTAB_INCORRECT, INCORRECT_IDX_SZ,
+ ROOT_DIR_NOT_FOUND, DISCONNECTED_FILE_CANNOT_BE_RECOVERED };
+
+enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 };
+
+typedef int (*calculate_lp_callback)(struct ubifs_info *c,
+ int index, int *free, int *dirty,
+ int *is_idx);
+
+struct scanned_file;
+
+/**
+ * scanned_node - common header node.
+ * @exist: whether the node is found by scanning
+ * @lnum: LEB number of the scanned node
+ * @offs: scanned node's offset within @lnum
+ * @len: length of scanned node
+ * @sqnum: sequence number
+ */
+struct scanned_node {
+ bool exist;
+ int lnum;
+ int offs;
+ int len;
+ unsigned long long sqnum;
+};
+
+/**
+ * scanned_ino_node - scanned inode node.
+ * @header: common header of scanned node
+ * @key: the key of inode node
+ * @is_xattr: %1 for xattr inode, otherwise %0
+ * @is_encrypted: %1 for encrypted inode, otherwise %0
+ * @mode: file mode
+ * @nlink: number of hard links
+ * @xcnt: count of extended attributes this inode has
+ * @xsz: summarized size of all extended attributes in bytes
+ * @xnms: sum of lengths of all extended attribute names
+ * @size: inode size in bytes
+ * @rb: link in the tree of valid inode nodes or deleted inode nodes
+ */
+struct scanned_ino_node {
+ struct scanned_node header;
+ union ubifs_key key;
+ unsigned int is_xattr:1;
+ unsigned int is_encrypted:1;
+ unsigned int mode;
+ unsigned int nlink;
+ unsigned int xcnt;
+ unsigned int xsz;
+ unsigned int xnms;
+ unsigned long long size;
+ struct rb_node rb;
+};
+
+/**
+ * scanned_dent_node - scanned dentry node.
+ * @header: common header of scanned node
+ * @key: the key of dentry node
+ * @can_be_found: whether this dentry can be found from '/'
+ * @type: file type, reg/dir/symlink/block/char/fifo/sock
+ * @nlen: name length
+ * @name: dentry name
+ * @inum: target inode number
+ * @file: corresponding file
+ * @rb: link in the trees of:
+ * 1) valid dentry nodes or deleted dentry node
+ * 2) all scanned dentry nodes from same file
+ * @list: link in the list dentries for looking up/deleting
+ */
+struct scanned_dent_node {
+ struct scanned_node header;
+ union ubifs_key key;
+ bool can_be_found;
+ unsigned int type;
+ unsigned int nlen;
+ char name[UBIFS_MAX_NLEN + 1];
+ ino_t inum;
+ struct scanned_file *file;
+ struct rb_node rb;
+ struct list_head list;
+};
+
+/**
+ * scanned_data_node - scanned data node.
+ * @header: common header of scanned node
+ * @key: the key of data node
+ * @size: uncompressed data size in bytes
+ * @rb: link in the tree of all scanned data nodes from same file
+ * @list: link in the list for deleting
+ */
+struct scanned_data_node {
+ struct scanned_node header;
+ union ubifs_key key;
+ unsigned int size;
+ struct rb_node rb;
+ struct list_head list;
+};
+
+/**
+ * scanned_trun_node - scanned truncation node.
+ * @header: common header of scanned node
+ * @new_size: size after truncation
+ */
+struct scanned_trun_node {
+ struct scanned_node header;
+ unsigned long long new_size;
+};
+
+/**
+ * scanned_file - file info scanned from UBIFS volume.
+ *
+ * @calc_nlink: calculated count of directory entries refer this inode
+ * @calc_xcnt: calculated count of extended attributes
+ * @calc_xsz: calculated summary size of all extended attributes
+ * @calc_xnms: calculated sum of lengths of all extended attribute names
+ * @calc_size: calculated file size
+ * @has_encrypted_info: whether the file has encryption related xattrs
+ *
+ * @inum: inode number
+ * @ino: inode node
+ * @trun: truncation node
+ *
+ * @rb: link in the tree of all scanned files
+ * @list: link in the list files for kinds of processing
+ * @dent_nodes: tree of all scanned dentry nodes
+ * @data_nodes: tree of all scanned data nodes
+ * @xattr_files: tree of all scanned xattr files
+ */
+struct scanned_file {
+ unsigned int calc_nlink;
+ unsigned int calc_xcnt;
+ unsigned int calc_xsz;
+ unsigned int calc_xnms;
+ unsigned long long calc_size;
+ bool has_encrypted_info;
+
+ ino_t inum;
+ struct scanned_ino_node ino;
+ struct scanned_trun_node trun;
+
+ struct rb_node rb;
+ struct list_head list;
+ struct rb_root dent_nodes;
+ struct rb_root data_nodes;
+ struct rb_root xattr_files;
+};
+
+/**
+ * invalid_file_problem - problem instance for invalid file.
+ * @file: invalid file instance
+ * @priv: invalid instance in @file, could be a dent_node or data_node
+ */
+struct invalid_file_problem {
+ struct scanned_file *file;
+ void *priv;
+};
+
+/**
+ * nnode_problem - problem instance for incorrect nnode
+ * @nnode: incorrect nnode
+ * @parent_nnode: the parent nnode of @nnode, could be NULL if @nnode is root
+ * @num: calculated num
+ */
+struct nnode_problem {
+ struct ubifs_nnode *nnode;
+ struct ubifs_nnode *parent_nnode;
+ int num;
+};
+
+/**
+ * pnode_problem - problem instance for incorrect pnode
+ * @pnode: incorrect pnode
+ * @num: calculated num
+ */
+struct pnode_problem {
+ struct ubifs_pnode *pnode;
+ int num;
+};
+
+/**
+ * lp_problem - problem instance for incorrect LEB proerties
+ * @lp: incorrect LEB properties
+ * @lnum: LEB number
+ * @free: calculated free space in LEB
+ * @dirty: calculated dirty bytes in LEB
+ * @is_idx: %true means that the LEB is an index LEB
+ */
+struct lp_problem {
+ struct ubifs_lprops *lp;
+ int lnum;
+ int free;
+ int dirty;
+ int is_idx;
+};
+
+/**
+ * space_stat_problem - problem instance for incorrect space statistics
+ * @lst: current space statistics
+ * @calc_lst: calculated space statistics
+ */
+struct space_stat_problem {
+ struct ubifs_lp_stats *lst;
+ struct ubifs_lp_stats *calc_lst;
+};
+
+/**
+ * ubifs_rebuild_info - UBIFS rebuilding information.
+ * @write_buf: write buffer for LEB @head_lnum
+ * @head_lnum: current writing LEB number
+ * @head_offs: current writing position in LEB @head_lnum
+ * @need_update_lpt: whether to update lpt while writing index nodes
+ */
+struct ubifs_rebuild_info {
+ void *write_buf;
+ int head_lnum;
+ int head_offs;
+ bool need_update_lpt;
+};
+
+/**
+ * struct ubifs_fsck_info - UBIFS fsck information.
+ * @mode: working mode
+ * @failure_reason: reasons for failed operations
+ * @lpt_status: the status of lpt, could be: %0(OK), %FR_LPT_CORRUPTED or
+ * %FR_LPT_INCORRECT
+ * @scanned_files: tree of all scanned files
+ * @used_lebs: a bitmap used for recording used lebs
+ * @disconnected_files: regular files without dentries
+ * @lpts: lprops table
+ * @try_rebuild: %true means that try to rebuild fs when fsck failed
+ * @rebuild: rebuilding-related information
+ * @lost_and_found: inode number of the lost+found directory, %0 means invalid
+ */
+struct ubifs_fsck_info {
+ int mode;
+ unsigned int failure_reason;
+ unsigned int lpt_status;
+ struct rb_root scanned_files;
+ unsigned long *used_lebs;
+ struct list_head disconnected_files;
+ struct ubifs_lprops *lpts;
+ bool try_rebuild;
+ struct ubifs_rebuild_info *rebuild;
+ ino_t lost_and_found;
+};
+
+#define FSCK(c) ((struct ubifs_fsck_info*)c->private)
+
+static inline const char *mode_name(const struct ubifs_info *c)
+{
+ if (!c->private)
+ return "";
+
+ switch (FSCK(c)->mode) {
+ case NORMAL_MODE:
+ return ",normal mode";
+ case SAFE_MODE:
+ return ",safe mode";
+ case DANGER_MODE0:
+ return ",danger mode";
+ case DANGER_MODE1:
+ return ",danger + rebuild mode";
+ case REBUILD_MODE:
+ return ",rebuild mode";
+ case CHECK_MODE:
+ return ",check mode";
+ default:
+ return "";
+ }
+}
+
+#define log_out(c, fmt, ...) \
+ printf("%s[%d] (%s%s): " fmt "\n", c->program_name ? : "noprog",\
+ getpid(), c->dev_name ? : "-", mode_name(c), \
+ ##__VA_ARGS__)
+
+#define log_err(c, err, fmt, ...) do { \
+ printf("%s[%d][ERROR] (%s%s): %s: " fmt, \
+ c->program_name ? : "noprog", getpid(), \
+ c->dev_name ? : "-", mode_name(c), \
+ __FUNCTION__, ##__VA_ARGS__); \
+ if (err) \
+ printf(" - %s", strerror(err)); \
+ printf("\n"); \
+} while (0)
+
+/* Exit code for fsck program. */
+extern int exit_code;
+
+/* fsck.ubifs.c */
+void handle_error(const struct ubifs_info *c, int reason_set);
+
+/* problem.c */
+bool fix_problem(const struct ubifs_info *c, int problem_type, const void *priv);
+
+/* load_fs.c */
+int ubifs_load_filesystem(struct ubifs_info *c);
+void ubifs_destroy_filesystem(struct ubifs_info *c);
+
+/* extract_files.c */
+bool parse_ino_node(struct ubifs_info *c, int lnum, int offs, void *node,
+ union ubifs_key *key, struct scanned_ino_node *ino_node);
+bool parse_dent_node(struct ubifs_info *c, int lnum, int offs, void *node,
+ union ubifs_key *key, struct scanned_dent_node *dent_node);
+bool parse_data_node(struct ubifs_info *c, int lnum, int offs, void *node,
+ union ubifs_key *key, struct scanned_data_node *data_node);
+bool parse_trun_node(struct ubifs_info *c, int lnum, int offs, void *node,
+ union ubifs_key *key, struct scanned_trun_node *trun_node);
+int insert_or_update_file(struct ubifs_info *c, struct rb_root *file_tree,
+ struct scanned_node *sn, int key_type, ino_t inum);
+void destroy_file_content(struct ubifs_info *c, struct scanned_file *file);
+void destroy_file_tree(struct ubifs_info *c, struct rb_root *file_tree);
+void destroy_file_list(struct ubifs_info *c, struct list_head *file_list);
+struct scanned_file *lookup_file(struct rb_root *file_tree, ino_t inum);
+int delete_file(struct ubifs_info *c, struct scanned_file *file);
+int file_is_valid(struct ubifs_info *c, struct scanned_file *file,
+ struct rb_root *file_tree, int *is_diconnected);
+bool file_is_reachable(struct ubifs_info *c, struct scanned_file *file,
+ struct rb_root *file_tree);
+int check_and_correct_files(struct ubifs_info *c);
+
+/* rebuild_fs.c */
+int ubifs_rebuild_filesystem(struct ubifs_info *c);
+
+/* check_files.c */
+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);
+int check_and_create_root(struct ubifs_info *c);
+
+/* check_space.c */
+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);
+
+/* handle_disconnected.c */
+int check_and_create_lost_found(struct ubifs_info *c);
+int handle_disonnected_files(struct ubifs_info *c);
+
+#endif