Line data Source code
1 : #ifndef _FSCK_H
2 : #define _FSCK_H
3 :
4 : #include "libgfs2.h"
5 : #include "osi_tree.h"
6 :
7 : #define FSCK_MAX_FORMAT (1802)
8 :
9 : #define FSCK_HASH_SHIFT (13)
10 : #define FSCK_HASH_SIZE (1 << FSCK_HASH_SHIFT)
11 : #define FSCK_HASH_MASK (FSCK_HASH_SIZE - 1)
12 :
13 : #define query(cx, fmt, args...) fsck_query(cx, fmt, ##args)
14 :
15 : /*
16 : * Exit codes used by fsck-type programs
17 : * Copied from e2fsck's e2fsck.h
18 : */
19 : #define FSCK_OK 0 /* No errors */
20 : #define FSCK_NONDESTRUCT 1 /* File system errors corrected */
21 : #define FSCK_REBOOT 2 /* System should be rebooted */
22 : #define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
23 : #define FSCK_ERROR 8 /* Operational error */
24 : #define FSCK_USAGE 16 /* Usage or syntax error */
25 : #define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
26 : #define FSCK_LIBRARY 128 /* Shared library error */
27 :
28 : #define BAD_POINTER_TOLERANCE 10 /* How many bad pointers is too many? */
29 :
30 : struct bmap {
31 : uint64_t size;
32 : uint64_t mapsize;
33 : unsigned char *map;
34 : };
35 :
36 : struct inode_info
37 : {
38 : struct osi_node node;
39 : struct lgfs2_inum num;
40 : uint32_t di_nlink; /* the number of links the inode
41 : * thinks it has */
42 : uint32_t counted_links; /* the number of links we've found */
43 : };
44 :
45 : struct dir_info
46 : {
47 : struct osi_node node;
48 : struct lgfs2_inum dinode;
49 : uint64_t treewalk_parent;
50 : struct lgfs2_inum dotdot_parent;
51 : uint32_t di_nlink;
52 : uint32_t counted_links;
53 : uint8_t checked:1;
54 : };
55 :
56 : struct dir_status {
57 : uint8_t dotdir:1;
58 : uint8_t dotdotdir:1;
59 : int q;
60 : uint32_t entry_count;
61 : };
62 :
63 : #define DUPFLAG_REF1_FOUND 1 /* Has the original reference been found? */
64 : #define DUPFLAG_REF1_IS_DUPL 2 /* The original reference is also where we
65 : determined there was a duplicate. */
66 :
67 : struct duptree {
68 : struct osi_node node;
69 : int dup_flags;
70 : int refs;
71 : uint64_t block;
72 : osi_list_t ref_inode_list; /* list of inodes referencing a dup block */
73 : osi_list_t ref_invinode_list; /* list of invalid inodes referencing */
74 : };
75 :
76 : enum dup_ref_type {
77 : REF_AS_DATA = 0, /* dinode references this block as a data block */
78 : REF_AS_META = 1, /* dinode references this block as a metadata block */
79 : REF_AS_EA = 2, /* dinode references this block as an extended attr */
80 : REF_IS_INODE= 3, /* The reference is itself a dinode. In other words,
81 : it's a dinode, not pointed to as data or
82 : metadata */
83 : REF_TYPES = 4,
84 : };
85 :
86 : struct inode_with_dups {
87 : osi_list_t list;
88 : uint64_t block_no;
89 : int dup_count;
90 : int reftypecount[REF_TYPES];
91 : uint64_t parent;
92 : char *name;
93 : };
94 :
95 : enum rgindex_trust_level { /* how far can we trust our RG index? */
96 : BLIND_FAITH = 0, /* We'd like to trust the rgindex. We always used to
97 : before bz 179069. This should cover most cases. */
98 : YE_OF_LITTLE_FAITH = 1, /* The rindex seems trustworthy but there's
99 : rg damage that need to be fixed. */
100 : OPEN_MINDED = 2, /* At least 1 RG is corrupt. Try to calculate what it
101 : should be, in a perfect world where our RGs are all
102 : on even boundaries. Blue sky. Chirping birds. */
103 : DISTRUST = 3, /* The world isn't perfect, our RGs are not on nice neat
104 : boundaries. The fs must have been messed with by
105 : gfs2_grow or something. Count the RGs by hand. */
106 : INDIGNATION = 4 /* Not only do we have corruption, but the rgrps
107 : aren't on even boundaries, so this file system
108 : must have been converted from gfs2_convert. */
109 : };
110 :
111 : struct fsck_options {
112 : char *device;
113 : unsigned int yes:1;
114 : unsigned int no:1;
115 : unsigned int preen:1;
116 : unsigned int force:1;
117 : };
118 :
119 : struct fsck_cx {
120 : struct lgfs2_sbd *sdp;
121 : struct osi_root dup_blocks;
122 : struct osi_root dirtree;
123 : struct osi_root inodetree;
124 : const struct fsck_options * const opts;
125 : };
126 :
127 : extern struct lgfs2_inode *fsck_load_inode(struct lgfs2_sbd *sdp, uint64_t block);
128 : extern struct lgfs2_inode *fsck_inode_get(struct lgfs2_sbd *sdp,
129 : struct lgfs2_rgrp_tree *rgd,
130 : struct lgfs2_buffer_head *bh);
131 : extern void fsck_inode_put(struct lgfs2_inode **ip);
132 :
133 : extern int initialize(struct fsck_cx *cx, int *all_clean);
134 : extern void destroy(struct fsck_cx *cx);
135 : extern int pass1(struct fsck_cx *cx);
136 : extern int pass1b(struct fsck_cx *cx);
137 : extern int pass1c(struct fsck_cx *cx);
138 : extern int pass2(struct fsck_cx *cx);
139 : extern int pass3(struct fsck_cx *cx);
140 : extern int pass4(struct fsck_cx *cx);
141 : extern int pass5(struct fsck_cx *cx, struct bmap *bl);
142 : extern int rindex_repair(struct fsck_cx *cx, int trust_lvl, int *ok);
143 : extern int fsck_query(struct fsck_cx *cx, const char *format, ...)
144 : __attribute__((format(printf,2,3)));
145 : extern struct dir_info *dirtree_find(struct fsck_cx *cx, uint64_t block);
146 : extern void dup_delete(struct fsck_cx *cx, struct duptree *dt);
147 : extern void dirtree_delete(struct fsck_cx *cx, struct dir_info *b);
148 :
149 : /* FIXME: Hack to get this going for pass2 - this should be pulled out
150 : * of pass1 and put somewhere else... */
151 : struct dir_info *dirtree_insert(struct fsck_cx *cx, struct lgfs2_inum inum);
152 :
153 : extern struct lgfs2_inode *lf_dip; /* Lost and found directory inode */
154 : extern int lf_was_created;
155 : extern uint64_t last_fs_block, last_reported_block;
156 : extern int64_t last_reported_fblock;
157 : extern int skip_this_pass, fsck_abort;
158 : extern int errors_found, errors_corrected;
159 : extern uint64_t last_data_block;
160 : extern uint64_t first_data_block;
161 : extern int dups_found; /* How many duplicate references have we found? */
162 : extern int dups_found_first; /* How many duplicates have we found the original
163 : reference for? */
164 :
165 0 : static inline int valid_block(struct lgfs2_sbd *sdp, uint64_t blkno)
166 : {
167 0 : return !((blkno > sdp->fssize) || (blkno <= LGFS2_SB_ADDR(sdp)) ||
168 0 : (lgfs2_get_bitmap(sdp, blkno, NULL) < 0));
169 : }
170 :
171 6163822 : static inline int rgrp_contains_block(struct lgfs2_rgrp_tree *rgd, uint64_t blk)
172 : {
173 6163822 : if (blk < rgd->rt_addr)
174 229 : return 0;
175 6163593 : if (blk >= rgd->rt_data0 + rgd->rt_data)
176 48095 : return 0;
177 6115498 : return 1;
178 : }
179 :
180 4035560 : static inline int valid_block_ip(struct lgfs2_inode *ip, uint64_t blk)
181 : {
182 4035560 : struct lgfs2_sbd *sdp = ip->i_sbd;
183 4035560 : struct lgfs2_rgrp_tree *rgd = ip->i_rgd;
184 :
185 4035560 : if (blk > sdp->fssize)
186 0 : return 0;
187 4035560 : if (blk <= LGFS2_SB_ADDR(sdp))
188 0 : return 0;
189 4035560 : if (rgd == NULL || !rgrp_contains_block(rgd, blk)) {
190 3938000 : rgd = lgfs2_blk2rgrpd(sdp, blk);
191 3938000 : if (rgd == NULL)
192 0 : return 0;
193 : }
194 :
195 4035560 : return rgrp_contains_block(rgd, blk);
196 : }
197 :
198 : struct special_blocks {
199 : osi_list_t list;
200 : uint64_t block;
201 : };
202 :
203 : extern struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num);
204 : extern void special_set(struct special_blocks *blocklist, uint64_t block);
205 : extern void special_free(struct special_blocks *blist);
206 : extern int sb_fixed;
207 : extern int build_per_node(struct lgfs2_sbd *sdp);
208 :
209 : #endif /* _FSCK_H */
|