Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (C) 2024, Huawei Technologies Co, Ltd.
4 : *
5 : * Authors: Zhihao Cheng <chengzhihao1@huawei.com>
6 : */
7 :
8 : #ifndef __FSCK_UBIFS_H__
9 : #define __FSCK_UBIFS_H__
10 :
11 : /* Exit codes used by fsck-type programs */
12 : #define FSCK_OK 0 /* No errors */
13 : #define FSCK_NONDESTRUCT 1 /* File system errors corrected */
14 : #define FSCK_REBOOT 2 /* System should be rebooted */
15 : #define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
16 : #define FSCK_ERROR 8 /* Operational error */
17 : #define FSCK_USAGE 16 /* Usage or syntax error */
18 : #define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
19 : #define FSCK_LIBRARY 128 /* Shared library error */
20 :
21 : /*
22 : * There are 6 working modes for fsck:
23 : * NORMAL_MODE: Check the filesystem, ask user whether or not to fix the
24 : * problem as long as inconsistent data is found during checking.
25 : * SAFE_MODE: Check and safely repair the filesystem, if there are any
26 : * data dropping operations needed by fixing, fsck will fail.
27 : * DANGER_MODE0:Check and repair the filesystem according to TNC, data dropping
28 : * will be reported. If TNC/master/log is corrupted, fsck will fail.
29 : * DANGER_MODE1:Check and forcedly repair the filesystem according to TNC,
30 : * turns to @REBUILD_MODE mode automatically if TNC/master/log is
31 : * corrupted.
32 : * REBUILD_MODE:Scan entire UBI volume to find all nodes, and rebuild the
33 : * filesystem, always make fsck success.
34 : * CHECK_MODE: Make no changes to the filesystem, only check the filesystem.
35 : */
36 : enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,
37 : DANGER_MODE1, REBUILD_MODE, CHECK_MODE };
38 :
39 : /* Types of inconsistent problems */
40 : enum { SB_CORRUPTED = 0, MST_CORRUPTED, LOG_CORRUPTED, BUD_CORRUPTED,
41 : TNC_CORRUPTED, TNC_DATA_CORRUPTED, ORPHAN_CORRUPTED, INVALID_INO_NODE,
42 : INVALID_DENT_NODE, INVALID_DATA_NODE, SCAN_CORRUPTED, FILE_HAS_NO_INODE,
43 : FILE_HAS_0_NLINK_INODE, FILE_HAS_INCONSIST_TYPE, FILE_HAS_TOO_MANY_DENT,
44 : FILE_SHOULDNT_HAVE_DATA, FILE_HAS_NO_DENT, XATTR_HAS_NO_HOST,
45 : XATTR_HAS_WRONG_HOST, FILE_HAS_NO_ENCRYPT, FILE_IS_DISCONNECTED,
46 : FILE_ROOT_HAS_DENT, DENTRY_IS_UNREACHABLE, FILE_IS_INCONSISTENT,
47 : EMPTY_TNC, LPT_CORRUPTED, NNODE_INCORRECT, PNODE_INCORRECT,
48 : LP_INCORRECT, SPACE_STAT_INCORRECT, LTAB_INCORRECT, INCORRECT_IDX_SZ,
49 : ROOT_DIR_NOT_FOUND, DISCONNECTED_FILE_CANNOT_BE_RECOVERED };
50 :
51 : enum { HAS_DATA_CORRUPTED = 1, HAS_TNC_CORRUPTED = 2 };
52 :
53 : typedef int (*calculate_lp_callback)(struct ubifs_info *c,
54 : int index, int *free, int *dirty,
55 : int *is_idx);
56 :
57 : struct scanned_file;
58 :
59 : /**
60 : * scanned_node - common header node.
61 : * @exist: whether the node is found by scanning
62 : * @lnum: LEB number of the scanned node
63 : * @offs: scanned node's offset within @lnum
64 : * @len: length of scanned node
65 : * @sqnum: sequence number
66 : */
67 : struct scanned_node {
68 : bool exist;
69 : int lnum;
70 : int offs;
71 : int len;
72 : unsigned long long sqnum;
73 : };
74 :
75 : /**
76 : * scanned_ino_node - scanned inode node.
77 : * @header: common header of scanned node
78 : * @key: the key of inode node
79 : * @is_xattr: %1 for xattr inode, otherwise %0
80 : * @is_encrypted: %1 for encrypted inode, otherwise %0
81 : * @mode: file mode
82 : * @nlink: number of hard links
83 : * @xcnt: count of extended attributes this inode has
84 : * @xsz: summarized size of all extended attributes in bytes
85 : * @xnms: sum of lengths of all extended attribute names
86 : * @size: inode size in bytes
87 : * @rb: link in the tree of valid inode nodes or deleted inode nodes
88 : */
89 : struct scanned_ino_node {
90 : struct scanned_node header;
91 : union ubifs_key key;
92 : unsigned int is_xattr:1;
93 : unsigned int is_encrypted:1;
94 : unsigned int mode;
95 : unsigned int nlink;
96 : unsigned int xcnt;
97 : unsigned int xsz;
98 : unsigned int xnms;
99 : unsigned long long size;
100 : struct rb_node rb;
101 : };
102 :
103 : /**
104 : * scanned_dent_node - scanned dentry node.
105 : * @header: common header of scanned node
106 : * @key: the key of dentry node
107 : * @can_be_found: whether this dentry can be found from '/'
108 : * @type: file type, reg/dir/symlink/block/char/fifo/sock
109 : * @nlen: name length
110 : * @name: dentry name
111 : * @inum: target inode number
112 : * @file: corresponding file
113 : * @rb: link in the trees of:
114 : * 1) valid dentry nodes or deleted dentry node
115 : * 2) all scanned dentry nodes from same file
116 : * @list: link in the list dentries for looking up/deleting
117 : */
118 : struct scanned_dent_node {
119 : struct scanned_node header;
120 : union ubifs_key key;
121 : bool can_be_found;
122 : unsigned int type;
123 : unsigned int nlen;
124 : char name[UBIFS_MAX_NLEN + 1];
125 : ino_t inum;
126 : struct scanned_file *file;
127 : struct rb_node rb;
128 : struct list_head list;
129 : };
130 :
131 : /**
132 : * scanned_data_node - scanned data node.
133 : * @header: common header of scanned node
134 : * @key: the key of data node
135 : * @size: uncompressed data size in bytes
136 : * @rb: link in the tree of all scanned data nodes from same file
137 : * @list: link in the list for deleting
138 : */
139 : struct scanned_data_node {
140 : struct scanned_node header;
141 : union ubifs_key key;
142 : unsigned int size;
143 : struct rb_node rb;
144 : struct list_head list;
145 : };
146 :
147 : /**
148 : * scanned_trun_node - scanned truncation node.
149 : * @header: common header of scanned node
150 : * @new_size: size after truncation
151 : */
152 : struct scanned_trun_node {
153 : struct scanned_node header;
154 : unsigned long long new_size;
155 : };
156 :
157 : /**
158 : * scanned_file - file info scanned from UBIFS volume.
159 : *
160 : * @calc_nlink: calculated count of directory entries refer this inode
161 : * @calc_xcnt: calculated count of extended attributes
162 : * @calc_xsz: calculated summary size of all extended attributes
163 : * @calc_xnms: calculated sum of lengths of all extended attribute names
164 : * @calc_size: calculated file size
165 : * @has_encrypted_info: whether the file has encryption related xattrs
166 : *
167 : * @inum: inode number
168 : * @ino: inode node
169 : * @trun: truncation node
170 : *
171 : * @rb: link in the tree of all scanned files
172 : * @list: link in the list files for kinds of processing
173 : * @dent_nodes: tree of all scanned dentry nodes
174 : * @data_nodes: tree of all scanned data nodes
175 : * @xattr_files: tree of all scanned xattr files
176 : */
177 : struct scanned_file {
178 : unsigned int calc_nlink;
179 : unsigned int calc_xcnt;
180 : unsigned int calc_xsz;
181 : unsigned int calc_xnms;
182 : unsigned long long calc_size;
183 : bool has_encrypted_info;
184 :
185 : ino_t inum;
186 : struct scanned_ino_node ino;
187 : struct scanned_trun_node trun;
188 :
189 : struct rb_node rb;
190 : struct list_head list;
191 : struct rb_root dent_nodes;
192 : struct rb_root data_nodes;
193 : struct rb_root xattr_files;
194 : };
195 :
196 : /**
197 : * invalid_file_problem - problem instance for invalid file.
198 : * @file: invalid file instance
199 : * @priv: invalid instance in @file, could be a dent_node or data_node
200 : */
201 : struct invalid_file_problem {
202 : struct scanned_file *file;
203 : void *priv;
204 : };
205 :
206 : /**
207 : * nnode_problem - problem instance for incorrect nnode
208 : * @nnode: incorrect nnode
209 : * @parent_nnode: the parent nnode of @nnode, could be NULL if @nnode is root
210 : * @num: calculated num
211 : */
212 : struct nnode_problem {
213 : struct ubifs_nnode *nnode;
214 : struct ubifs_nnode *parent_nnode;
215 : int num;
216 : };
217 :
218 : /**
219 : * pnode_problem - problem instance for incorrect pnode
220 : * @pnode: incorrect pnode
221 : * @num: calculated num
222 : */
223 : struct pnode_problem {
224 : struct ubifs_pnode *pnode;
225 : int num;
226 : };
227 :
228 : /**
229 : * lp_problem - problem instance for incorrect LEB proerties
230 : * @lp: incorrect LEB properties
231 : * @lnum: LEB number
232 : * @free: calculated free space in LEB
233 : * @dirty: calculated dirty bytes in LEB
234 : * @is_idx: %true means that the LEB is an index LEB
235 : */
236 : struct lp_problem {
237 : struct ubifs_lprops *lp;
238 : int lnum;
239 : int free;
240 : int dirty;
241 : int is_idx;
242 : };
243 :
244 : /**
245 : * space_stat_problem - problem instance for incorrect space statistics
246 : * @lst: current space statistics
247 : * @calc_lst: calculated space statistics
248 : */
249 : struct space_stat_problem {
250 : struct ubifs_lp_stats *lst;
251 : struct ubifs_lp_stats *calc_lst;
252 : };
253 :
254 : /**
255 : * ubifs_rebuild_info - UBIFS rebuilding information.
256 : * @write_buf: write buffer for LEB @head_lnum
257 : * @head_lnum: current writing LEB number
258 : * @head_offs: current writing position in LEB @head_lnum
259 : * @need_update_lpt: whether to update lpt while writing index nodes
260 : */
261 : struct ubifs_rebuild_info {
262 : void *write_buf;
263 : int head_lnum;
264 : int head_offs;
265 : bool need_update_lpt;
266 : };
267 :
268 : /**
269 : * struct ubifs_fsck_info - UBIFS fsck information.
270 : * @mode: working mode
271 : * @failure_reason: reasons for failed operations
272 : * @lpt_status: the status of lpt, could be: %0(OK), %FR_LPT_CORRUPTED or
273 : * %FR_LPT_INCORRECT
274 : * @scanned_files: tree of all scanned files
275 : * @used_lebs: a bitmap used for recording used lebs
276 : * @disconnected_files: regular files without dentries
277 : * @lpts: lprops table
278 : * @try_rebuild: %true means that try to rebuild fs when fsck failed
279 : * @rebuild: rebuilding-related information
280 : * @lost_and_found: inode number of the lost+found directory, %0 means invalid
281 : */
282 : struct ubifs_fsck_info {
283 : int mode;
284 : unsigned int failure_reason;
285 : unsigned int lpt_status;
286 : struct rb_root scanned_files;
287 : unsigned long *used_lebs;
288 : struct list_head disconnected_files;
289 : struct ubifs_lprops *lpts;
290 : bool try_rebuild;
291 : struct ubifs_rebuild_info *rebuild;
292 : ino_t lost_and_found;
293 : };
294 :
295 : #define FSCK(c) ((struct ubifs_fsck_info*)c->private)
296 :
297 : static inline const char *mode_name(const struct ubifs_info *c)
298 : {
299 359782 : if (!c->private)
300 : return "";
301 :
302 357659 : switch (FSCK(c)->mode) {
303 : case NORMAL_MODE:
304 : return ",normal mode";
305 : case SAFE_MODE:
306 : return ",safe mode";
307 : case DANGER_MODE0:
308 : return ",danger mode";
309 : case DANGER_MODE1:
310 : return ",danger + rebuild mode";
311 : case REBUILD_MODE:
312 : return ",rebuild mode";
313 : case CHECK_MODE:
314 : return ",check mode";
315 : default:
316 : return "";
317 : }
318 : }
319 :
320 : #define log_out(c, fmt, ...) do { \
321 : printf("%s[%d] (%s%s): " fmt "\n", c->program_name ? : "noprog",\
322 : getpid(), c->dev_name ? : "-", mode_name(c), \
323 : ##__VA_ARGS__); \
324 : } while (0)
325 :
326 : #define log_err(c, err, fmt, ...) do { \
327 : printf("%s[%d][ERROR] (%s%s): %s: " fmt, \
328 : c->program_name ? : "noprog", getpid(), \
329 : c->dev_name ? : "-", mode_name(c), \
330 : __FUNCTION__, ##__VA_ARGS__); \
331 : if (err) \
332 : printf(" - %s", strerror(err)); \
333 : printf("\n"); \
334 : } while (0)
335 :
336 : /* Exit code for fsck program. */
337 : extern int exit_code;
338 :
339 : /* fsck.ubifs.c */
340 : void handle_error(const struct ubifs_info *c, int reason_set);
341 :
342 : /* problem.c */
343 : bool fix_problem(const struct ubifs_info *c, int problem_type, const void *priv);
344 :
345 : /* load_fs.c */
346 : int ubifs_load_filesystem(struct ubifs_info *c);
347 : void ubifs_destroy_filesystem(struct ubifs_info *c);
348 :
349 : /* extract_files.c */
350 : bool parse_ino_node(struct ubifs_info *c, int lnum, int offs, void *node,
351 : union ubifs_key *key, struct scanned_ino_node *ino_node);
352 : bool parse_dent_node(struct ubifs_info *c, int lnum, int offs, void *node,
353 : union ubifs_key *key, struct scanned_dent_node *dent_node);
354 : bool parse_data_node(struct ubifs_info *c, int lnum, int offs, void *node,
355 : union ubifs_key *key, struct scanned_data_node *data_node);
356 : bool parse_trun_node(struct ubifs_info *c, int lnum, int offs, void *node,
357 : union ubifs_key *key, struct scanned_trun_node *trun_node);
358 : int insert_or_update_file(struct ubifs_info *c, struct rb_root *file_tree,
359 : struct scanned_node *sn, int key_type, ino_t inum);
360 : void destroy_file_content(struct ubifs_info *c, struct scanned_file *file);
361 : void destroy_file_tree(struct ubifs_info *c, struct rb_root *file_tree);
362 : void destroy_file_list(struct ubifs_info *c, struct list_head *file_list);
363 : struct scanned_file *lookup_file(struct rb_root *file_tree, ino_t inum);
364 : int delete_file(struct ubifs_info *c, struct scanned_file *file);
365 : int file_is_valid(struct ubifs_info *c, struct scanned_file *file,
366 : struct rb_root *file_tree, int *is_diconnected);
367 : bool file_is_reachable(struct ubifs_info *c, struct scanned_file *file,
368 : struct rb_root *file_tree);
369 : int check_and_correct_files(struct ubifs_info *c);
370 :
371 : /* rebuild_fs.c */
372 : int ubifs_rebuild_filesystem(struct ubifs_info *c);
373 :
374 : /* check_files.c */
375 : int traverse_tnc_and_construct_files(struct ubifs_info *c);
376 : void update_files_size(struct ubifs_info *c);
377 : int handle_invalid_files(struct ubifs_info *c);
378 : int handle_dentry_tree(struct ubifs_info *c);
379 : bool tnc_is_empty(struct ubifs_info *c);
380 : int check_and_create_root(struct ubifs_info *c);
381 :
382 : /* check_space.c */
383 : int get_free_leb(struct ubifs_info *c);
384 : int build_lpt(struct ubifs_info *c, calculate_lp_callback calculate_lp_cb,
385 : bool free_ltab);
386 : int check_and_correct_space(struct ubifs_info *c);
387 : int check_and_correct_index_size(struct ubifs_info *c);
388 :
389 : /* handle_disconnected.c */
390 : int check_and_create_lost_found(struct ubifs_info *c);
391 : int handle_disonnected_files(struct ubifs_info *c);
392 :
393 : #endif
|