Line data Source code
1 : /* pass1 checks inodes for format & type, duplicate blocks, & incorrect
2 : * block count.
3 : *
4 : * It builds up tables that contains the state of each block (free,
5 : * block in use, metadata type, etc), as well as bad blocks and
6 : * duplicate blocks. (See block_list.[ch] for more info)
7 : *
8 : */
9 :
10 : #include <stdio.h>
11 : #include <stdlib.h>
12 : #include <sys/time.h>
13 : #include <sys/stat.h>
14 : #include <unistd.h>
15 : #include <string.h>
16 : #include <time.h>
17 : #include <fcntl.h>
18 : #include <sys/ioctl.h>
19 : #include <inttypes.h>
20 : #include <libintl.h>
21 : #define _(String) gettext(String)
22 :
23 : #include <logging.h>
24 : #include "libgfs2.h"
25 : #include "fsck.h"
26 : #include "inode_hash.h"
27 : #include "util.h"
28 : #include "link.h"
29 : #include "metawalk.h"
30 : #include "fs_recovery.h"
31 :
32 : static struct bmap *bl = NULL;
33 : static struct metawalk_fxns pass1_fxns;
34 :
35 : struct block_count {
36 : uint64_t indir_count;
37 : uint64_t data_count;
38 : uint64_t ea_count;
39 : };
40 :
41 2115168 : static int blockmap_set(struct bmap *bmap, uint64_t bblock, int mark)
42 : {
43 : static unsigned char *byte;
44 : static uint64_t b;
45 :
46 2115168 : if (!bmap)
47 0 : return 0;
48 2115168 : if (bblock > bmap->size)
49 0 : return -1;
50 :
51 2115168 : byte = bmap->map + BLOCKMAP_SIZE2(bblock);
52 2115168 : b = BLOCKMAP_BYTE_OFFSET2(bblock);
53 2115168 : *byte &= ~(BLOCKMAP_MASK2 << b);
54 2115168 : *byte |= (mark & BLOCKMAP_MASK2) << b;
55 2115168 : return 0;
56 : }
57 :
58 : /*
59 : * _fsck_blockmap_set - Mark a block in the 4-bit blockmap and the 2-bit
60 : * bitmap, and adjust free space accordingly.
61 : */
62 1982705 : static int _fsck_blockmap_set(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t bblock,
63 : const char *btype, int mark, int error_on_dinode,
64 : const char *caller, int fline)
65 : {
66 1982705 : int error = _fsck_bitmap_set(cx, ip, bblock, btype, mark, error_on_dinode,
67 : caller, fline);
68 1982705 : if (error)
69 0 : return error;
70 :
71 1982705 : return blockmap_set(bl, bblock, mark);
72 : }
73 :
74 : #define fsck_blockmap_set(cx, ip, b, bt, m) \
75 : _fsck_blockmap_set(cx, ip, b, bt, m, 0, __FUNCTION__, __LINE__)
76 : #define fsck_blkmap_set_noino(cx, ip, b, bt, m) \
77 : _fsck_blockmap_set(cx, ip, b, bt, m, 1, __FUNCTION__, __LINE__)
78 :
79 : /**
80 : * p1_delete_block - delete a block associated with an inode
81 : */
82 0 : static int p1_delete_block(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
83 : struct lgfs2_buffer_head **bh, const char *btype,
84 : void *private)
85 : {
86 0 : if (valid_block_ip(ip, block)) {
87 0 : fsck_blockmap_set(cx, ip, block, btype, GFS2_BLKST_FREE);
88 0 : return 0;
89 : }
90 0 : return -1;
91 : }
92 :
93 : /* This is a pass1-specific leaf repair. Since we are not allowed to do
94 : * block allocations, we do what we can. */
95 0 : static int p1_repair_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t *leaf_no,
96 : int lindex, int ref_count, const char *msg)
97 : {
98 : uint64_t *cpyptr;
99 : char *padbuf;
100 : int pad_size, i;
101 :
102 0 : log_err(_("Directory Inode %"PRIu64" (0x%"PRIx64") points to leaf %"PRIu64" (0x%"PRIx64") %s.\n"),
103 : ip->i_num.in_addr, ip->i_num.in_addr, *leaf_no, *leaf_no, msg);
104 0 : if (!query(cx, _("Attempt to patch around it? (y/n) "))) {
105 0 : log_err( _("Bad leaf left in place.\n"));
106 0 : goto out;
107 : }
108 :
109 0 : padbuf = malloc(ref_count * sizeof(uint64_t));
110 0 : cpyptr = (uint64_t *)padbuf;
111 0 : for (i = 0; i < ref_count; i++) {
112 0 : *cpyptr = 0;
113 0 : cpyptr++;
114 : }
115 0 : pad_size = ref_count * sizeof(uint64_t);
116 0 : log_err(_("Writing zeros to the hash table of directory %"PRIu64
117 : " (0x%"PRIx64") at index: 0x%x for 0x%x pointers.\n"),
118 : ip->i_num.in_addr, ip->i_num.in_addr, lindex, ref_count);
119 0 : lgfs2_writei(ip, padbuf, lindex * sizeof(uint64_t), pad_size);
120 0 : free(padbuf);
121 0 : log_err(_("Directory Inode %"PRIu64" (0x%"PRIx64") patched.\n"),
122 : ip->i_num.in_addr, ip->i_num.in_addr);
123 :
124 0 : out:
125 0 : *leaf_no = 0;
126 0 : return 0;
127 : }
128 :
129 : /*
130 : * resuscitate_metalist - make sure a system directory entry's metadata blocks
131 : * are marked "in use" in the bitmap.
132 : *
133 : * This function makes sure metadata blocks for system and root directories are
134 : * marked "in use" by the bitmap. You don't want root's indirect blocks
135 : * deleted, do you? Or worse, reused for lost+found.
136 : */
137 0 : static int resuscitate_metalist(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
138 : int *is_valid, int *was_duplicate, void *private)
139 : {
140 0 : struct block_count *bc = (struct block_count *)private;
141 0 : struct lgfs2_inode *ip = iptr.ipt_ip;
142 0 : uint64_t block = iptr_block(iptr);
143 :
144 0 : *is_valid = 1;
145 0 : *was_duplicate = 0;
146 0 : *bh = NULL;
147 0 : if (!valid_block_ip(ip, block)){ /* blk outside of FS */
148 0 : fsck_blockmap_set(cx, ip, ip->i_num.in_addr, _("itself"), GFS2_BLKST_UNLINKED);
149 0 : log_err(_("Bad indirect block pointer (invalid or out of "
150 : "range) found in system inode %"PRIu64" (0x%"PRIx64").\n"),
151 : ip->i_num.in_addr, ip->i_num.in_addr);
152 0 : *is_valid = 0;
153 0 : return META_IS_GOOD;
154 : }
155 0 : if (fsck_system_inode(ip->i_sbd, block))
156 0 : fsck_blockmap_set(cx, ip, block, _("system file"), GFS2_BLKST_USED);
157 : else
158 0 : check_n_fix_bitmap(cx, ip->i_rgd, block, 0, GFS2_BLKST_USED);
159 0 : bc->indir_count++;
160 0 : return META_IS_GOOD;
161 : }
162 :
163 : /*
164 : * resuscitate_dentry - make sure a system directory entry is alive
165 : *
166 : * This function makes sure directory entries in system directories are
167 : * kept alive. You don't want journal0 deleted from jindex, do you?
168 : */
169 1036 : static int resuscitate_dentry(struct fsck_cx *cx, struct lgfs2_inode *ip, struct gfs2_dirent *dent,
170 : struct gfs2_dirent *prev_de,
171 : struct lgfs2_buffer_head *bh, char *filename,
172 : uint32_t *count, int *lindex, void *priv)
173 : {
174 1036 : struct lgfs2_sbd *sdp = ip->i_sbd;
175 : struct lgfs2_dirent d;
176 : char tmp_name[GFS2_FNAMESIZE];
177 : uint64_t block;
178 :
179 1036 : lgfs2_dirent_in(&d, dent);
180 1036 : block = d.dr_inum.in_addr;
181 : /* Start of checks */
182 1036 : memset(tmp_name, 0, sizeof(tmp_name));
183 1036 : if (d.dr_name_len < sizeof(tmp_name))
184 1036 : strncpy(tmp_name, filename, d.dr_name_len);
185 : else
186 0 : strncpy(tmp_name, filename, sizeof(tmp_name) - 1);
187 1036 : if (!valid_block_ip(ip, block)) {
188 0 : log_err(_("Block # referenced by system directory entry %s in inode "
189 : "%"PRIu64" (0x%"PRIx64") is invalid or out of range; ignored.\n"),
190 : tmp_name, ip->i_num.in_addr, ip->i_num.in_addr);
191 0 : return 0;
192 : }
193 : /* If this is a system dinode, we'll handle it later in
194 : check_system_inodes. If not, it'll be handled by pass1 but
195 : since it's in a system directory we need to make sure it's
196 : represented in the rgrp bitmap. */
197 1036 : if (fsck_system_inode(sdp, block))
198 846 : fsck_blockmap_set(cx, ip, block, _("system file"),
199 : GFS2_BLKST_DINODE);
200 : else
201 190 : check_n_fix_bitmap(cx, ip->i_rgd, block, 0,
202 : GFS2_BLKST_DINODE);
203 : /* Return the number of leaf entries so metawalk doesn't flag this
204 : leaf as having none. */
205 1036 : *count = be16_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_entries);
206 1036 : return 0;
207 : }
208 :
209 : static struct metawalk_fxns sysdir_fxns = {
210 : .private = NULL,
211 : .check_metalist = resuscitate_metalist,
212 : .check_dentry = resuscitate_dentry,
213 : .delete_block = p1_delete_block,
214 : };
215 :
216 9 : static int p1_check_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, void *private)
217 : {
218 9 : struct block_count *bc = (struct block_count *) private;
219 : int q;
220 :
221 : /* Note if we've gotten this far, the block has already passed the
222 : check in metawalk: lgfs2_check_meta(lbh, GFS2_METATYPE_LF).
223 : So we know it's a leaf block. */
224 9 : bc->indir_count++;
225 9 : q = block_type(bl, block);
226 9 : if (q != GFS2_BLKST_FREE) {
227 0 : log_err(_("Found duplicate block #%"PRIu64" (0x%"PRIx64") referenced "
228 : "as a directory leaf in dinode "
229 : "%"PRIu64" (0x%"PRIx64") - was marked %d (%s)\n"),
230 : block, block, ip->i_num.in_addr, ip->i_num.in_addr, q,
231 : block_type_string(q));
232 0 : add_duplicate_ref(cx, ip, block, REF_AS_META, 0, INODE_VALID);
233 0 : if (q == GFS2_BLKST_USED)
234 : /* If the previous reference also saw this as a leaf,
235 : it was already checked, so don't check again. */
236 0 : return EEXIST; /* non-fatal */
237 : }
238 9 : fsck_blockmap_set(cx, ip, block, _("directory leaf"), GFS2_BLKST_USED);
239 9 : return 0;
240 : }
241 :
242 7361 : static int p1_check_metalist(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
243 : int *is_valid, int *was_duplicate, void *private)
244 : {
245 7361 : struct block_count *bc = (struct block_count *)private;
246 7361 : struct lgfs2_inode *ip = iptr.ipt_ip;
247 7361 : uint64_t block = iptr_block(iptr);
248 : struct lgfs2_buffer_head *nbh;
249 : const char *blktypedesc;
250 : int iblk_type;
251 : int q;
252 :
253 7361 : *bh = NULL;
254 :
255 7361 : *was_duplicate = 0;
256 7361 : *is_valid = 0;
257 7361 : if (!valid_block_ip(ip, block)) { /* blk outside of FS */
258 : /* The bad dinode should be invalidated later due to
259 : "unrecoverable" errors. The inode itself should be
260 : set "free" and removed from the inodetree by
261 : undo_check_metalist. */
262 0 : fsck_blockmap_set(cx, ip, ip->i_num.in_addr,
263 : _("bad block referencing"), GFS2_BLKST_UNLINKED);
264 0 : log_debug(_("Bad indirect block (invalid/out of range) "
265 : "found in inode %"PRIu64" (0x%"PRIx64").\n"),
266 : ip->i_num.in_addr, ip->i_num.in_addr);
267 :
268 0 : return META_SKIP_FURTHER;
269 : }
270 7361 : if (is_dir(ip) && h == ip->i_height) {
271 0 : iblk_type = GFS2_METATYPE_JD;
272 0 : blktypedesc = _("a directory hash table block");
273 : } else {
274 7361 : iblk_type = GFS2_METATYPE_IN;
275 7361 : blktypedesc = _("a journaled data block");
276 : }
277 7361 : q = block_type(bl, block);
278 7361 : if (q != GFS2_BLKST_FREE) {
279 0 : log_err(_("Found duplicate block #%"PRIu64" (0x%"PRIx64") referenced "
280 : "as metadata in indirect block for dinode "
281 : "%"PRIu64" (0x%"PRIx64") - was marked %d (%s)\n"),
282 : block, block, ip->i_num.in_addr, ip->i_num.in_addr, q,
283 : block_type_string(q));
284 0 : *was_duplicate = 1;
285 : }
286 7361 : nbh = lgfs2_bread(ip->i_sbd, block);
287 :
288 7361 : *is_valid = (lgfs2_check_meta(nbh->b_data, iblk_type) == 0);
289 :
290 7361 : if (!(*is_valid)) {
291 0 : log_err(_("Inode %"PRIu64" (0x%"PRIx64") has a bad indirect block "
292 : "pointer %"PRIu64" (0x%"PRIx64") (points to something "
293 : "that is not %s).\n"),
294 : ip->i_num.in_addr, ip->i_num.in_addr, block, block, blktypedesc);
295 0 : if (query(cx, _("Zero the indirect block pointer? (y/n) "))){
296 0 : *iptr_ptr(iptr) = 0;
297 0 : lgfs2_bmodified(iptr.ipt_bh);
298 0 : *is_valid = 1;
299 0 : lgfs2_brelse(nbh);
300 0 : return META_SKIP_ONE;
301 : } else {
302 0 : lgfs2_brelse(nbh);
303 0 : return META_SKIP_FURTHER;
304 : }
305 : }
306 :
307 7361 : bc->indir_count++;
308 7361 : if (*was_duplicate) {
309 0 : add_duplicate_ref(cx, ip, block, REF_AS_META, 0,
310 0 : *is_valid ? INODE_VALID : INODE_INVALID);
311 0 : lgfs2_brelse(nbh);
312 : } else {
313 7361 : *bh = nbh;
314 7361 : fsck_blockmap_set(cx, ip, block, _("indirect"), GFS2_BLKST_USED);
315 : }
316 :
317 7361 : if (*is_valid)
318 7361 : return META_IS_GOOD;
319 0 : return META_SKIP_FURTHER;
320 : }
321 :
322 : /* undo_reference - undo previously processed data or metadata
323 : * We've treated the metadata for this dinode as good so far, but not we
324 : * realize it's bad. So we need to undo what we've done.
325 : *
326 : * Returns: 0 - We need to process the block as metadata. In other words,
327 : * we need to undo any blocks it refers to.
328 : * 1 - We can't process the block as metadata.
329 : */
330 :
331 0 : static int undo_reference(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, int meta,
332 : void *private)
333 : {
334 0 : struct block_count *bc = (struct block_count *)private;
335 : struct duptree *dt;
336 : struct inode_with_dups *id;
337 0 : int old_bitmap_state = 0;
338 : struct lgfs2_rgrp_tree *rgd;
339 :
340 0 : if (!valid_block_ip(ip, block)) { /* blk outside of FS */
341 0 : fsck_blockmap_set(cx, ip, ip->i_num.in_addr, _("bad block referencing"), GFS2_BLKST_FREE);
342 0 : return 1;
343 : }
344 :
345 0 : if (meta)
346 0 : bc->indir_count--;
347 0 : dt = dupfind(cx, block);
348 0 : if (dt) {
349 : /* remove all duplicate reference structures from this inode */
350 : do {
351 0 : id = find_dup_ref_inode(dt, ip);
352 0 : if (!id)
353 0 : break;
354 :
355 0 : dup_listent_delete(dt, id);
356 0 : } while (id);
357 :
358 0 : if (dt->refs) {
359 0 : log_err(_("Block %"PRIu64" (0x%"PRIx64") is still referenced "
360 : "from another inode; not freeing.\n"),
361 : block, block);
362 0 : if (dt->refs == 1) {
363 0 : log_err(_("This was the only duplicate "
364 : "reference so far; removing it.\n"));
365 0 : dup_delete(cx, dt);
366 : }
367 0 : return 1;
368 : }
369 : }
370 0 : if (!meta) {
371 0 : rgd = lgfs2_blk2rgrpd(ip->i_sbd, block);
372 0 : old_bitmap_state = lgfs2_get_bitmap(ip->i_sbd, block, rgd);
373 0 : if (old_bitmap_state == GFS2_BLKST_DINODE)
374 0 : return -1;
375 : }
376 0 : fsck_blockmap_set(cx, ip, block,
377 : meta ? _("bad indirect") : _("referenced data"),
378 : GFS2_BLKST_FREE);
379 0 : return 0;
380 : }
381 :
382 0 : static int p1_undo_check_metalist(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
383 : int h, void *private)
384 : {
385 0 : return undo_reference(cx, ip, block, 1, private);
386 : }
387 :
388 0 : static int p1_undo_check_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
389 : void *private)
390 : {
391 0 : return undo_reference(cx, ip, block, 0, private);
392 : }
393 :
394 : /* blockmap_set_as_data - set block as 'data' in the blockmap, if not dinode
395 : *
396 : * This function tries to set a block that's referenced as data as 'data'
397 : * in the fsck blockmap. But if that block is marked as 'dinode' in the
398 : * rgrp bitmap, it does additional checks to see if it looks like a dinode.
399 : * Note that previous checks were done for duplicate references, so this
400 : * is checking for dinodes that we haven't processed yet.
401 : */
402 1973676 : static int blockmap_set_as_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block)
403 : {
404 : int error;
405 : struct lgfs2_buffer_head *bh;
406 : struct gfs2_dinode *di;
407 :
408 1973676 : error = fsck_blkmap_set_noino(cx, ip, block, "data", GFS2_BLKST_USED);
409 1973676 : if (!error)
410 1973676 : return 0;
411 :
412 0 : error = 0;
413 : /* The bitmap says it's a dinode, but a block reference begs to differ.
414 : So which is it? */
415 0 : bh = lgfs2_bread(ip->i_sbd, block);
416 0 : if (lgfs2_check_meta(bh->b_data, GFS2_METATYPE_DI) != 0)
417 0 : goto out;
418 :
419 : /* The meta header agrees it's a dinode. But it might be data in
420 : disguise, so do some extra checks. */
421 0 : di = (struct gfs2_dinode *)bh->b_data;
422 0 : if (be64_to_cpu(di->di_num.no_addr) != block)
423 0 : goto out;
424 :
425 0 : log_err(_("Inode %"PRIu64" (0x%"PRIx64") has a reference to block %"PRIu64" (0x%"PRIx64") "
426 : "as a data block, but it appears to be a dinode we haven't checked yet.\n"),
427 : ip->i_num.in_addr, ip->i_num.in_addr, block, block);
428 0 : error = -1;
429 0 : out:
430 0 : if (!error)
431 0 : fsck_blockmap_set(cx, ip, block, "data", GFS2_BLKST_USED);
432 0 : lgfs2_brelse(bh);
433 0 : return error;
434 : }
435 :
436 1973676 : static int p1_check_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
437 : uint64_t block, void *private,
438 : struct lgfs2_buffer_head *bbh, __be64 *ptr)
439 : {
440 : int q;
441 1973676 : struct block_count *bc = (struct block_count *) private;
442 :
443 1973676 : if (!valid_block_ip(ip, block)) {
444 0 : log_err(_("inode %"PRIu64" (0x%"PRIx64") has a bad data block pointer "
445 : "%"PRIu64" (0x%"PRIx64") (invalid or out of range) "),
446 : ip->i_num.in_addr, ip->i_num.in_addr, block, block);
447 0 : if (metablock == ip->i_num.in_addr)
448 0 : log_err("\n");
449 : else
450 0 : log_err(_("from metadata block %"PRIu64" (0x%"PRIx64")\n"),
451 : metablock, metablock);
452 : /* Mark the owner of this block with the bad_block
453 : * designator so we know to check it for out of range
454 : * blocks later */
455 0 : fsck_blockmap_set(cx, ip, ip->i_num.in_addr, _("bad (out of range) data"), GFS2_BLKST_UNLINKED);
456 0 : return -1;
457 : }
458 1973676 : bc->data_count++; /* keep the count sane anyway */
459 1973676 : q = block_type(bl, block);
460 1973676 : if (q != GFS2_BLKST_FREE) {
461 : struct lgfs2_buffer_head *bh;
462 : struct gfs2_meta_header *mh;
463 : uint32_t mh_type;
464 :
465 0 : log_err(_("Found duplicate %s block %"PRIu64" (0x%"PRIx64") "
466 : "referenced as data by dinode %"PRIu64" (0x%"PRIx64") "),
467 : block_type_string(q),
468 : block, block, ip->i_num.in_addr, ip->i_num.in_addr);
469 0 : if (metablock == ip->i_num.in_addr)
470 0 : log_err("\n");
471 : else
472 0 : log_err(_("from metadata block %"PRIu64" (0x%"PRIx64")\n"),
473 : metablock, metablock);
474 :
475 0 : switch (q) {
476 0 : case GFS2_BLKST_DINODE:
477 0 : log_info(_("The block was processed earlier as an "
478 : "inode, so it can't possibly be data.\n"));
479 : /* We still need to add a duplicate record here because
480 : when check_metatree tries to delete the inode, we
481 : can't have the "undo" functions freeing the block
482 : out from other the original referencing inode. */
483 0 : add_duplicate_ref(cx, ip, block, REF_AS_DATA, 0,
484 : INODE_VALID);
485 0 : return 1;
486 0 : case GFS2_BLKST_USED: /* tough decision: May be data or meta */
487 0 : bh = lgfs2_bread(ip->i_sbd, block);
488 0 : mh = (struct gfs2_meta_header *)bh->b_data;
489 0 : mh_type = be32_to_cpu(mh->mh_type);
490 0 : lgfs2_brelse(bh);
491 0 : if (be32_to_cpu(mh->mh_magic) == GFS2_MAGIC &&
492 0 : mh_type >= GFS2_METATYPE_RG &&
493 0 : mh_type <= GFS2_METATYPE_QC &&
494 0 : mh_type != GFS2_METATYPE_DI &&
495 0 : be32_to_cpu(mh->mh_format) % 100 == 0) {
496 0 : log_info(_("The block was processed earlier "
497 : "as valid metadata, so it can't "
498 : "possibly be data.\n"));
499 : /* We still need to add a duplicate record here
500 : because when check_metatree tries to delete
501 : the inode, we can't have the "undo"
502 : functions freeing the block out from other
503 : the original referencing inode. */
504 0 : add_duplicate_ref(cx, ip, block, REF_AS_DATA, 0,
505 : INODE_VALID);
506 0 : return 1;
507 : }
508 0 : log_info( _("Seems to be a normal duplicate; I'll "
509 : "sort it out in pass1b.\n"));
510 0 : add_duplicate_ref(cx, ip, block, REF_AS_DATA, 0,
511 : INODE_VALID);
512 : /* This inode references the block as data. So if this
513 : all is validated, we want to keep this count. */
514 0 : return 0;
515 0 : case GFS2_BLKST_UNLINKED:
516 0 : log_info( _("The block was invalid as metadata but might be "
517 : "okay as data. I'll sort it out in pass1b.\n"));
518 0 : add_duplicate_ref(cx, ip, block, REF_AS_DATA, 0, INODE_VALID);
519 0 : return 0;
520 : }
521 : }
522 1973676 : return blockmap_set_as_data(cx, ip, block);
523 : }
524 :
525 0 : static int ask_remove_inode_eattr(struct fsck_cx *cx, struct lgfs2_inode *ip,
526 : struct block_count *bc)
527 : {
528 0 : if (ip->i_eattr == 0)
529 0 : return 0; /* eattr was removed prior to this call */
530 0 : log_err(_("Inode %"PRIu64" (0x%"PRIx64") has unrecoverable Extended Attribute errors.\n"),
531 : ip->i_num.in_addr, ip->i_num.in_addr);
532 0 : if (query(cx, _("Clear all Extended Attributes from the inode? (y/n) "))){
533 0 : undo_reference(cx, ip, ip->i_eattr, 0, bc);
534 0 : ip->i_eattr = 0;
535 0 : bc->ea_count = 0;
536 0 : ip->i_blocks = 1 + bc->indir_count + bc->data_count;
537 0 : ip->i_flags &= ~GFS2_DIF_EA_INDIRECT;
538 0 : lgfs2_bmodified(ip->i_bh);
539 0 : log_err( _("Extended attributes were removed.\n"));
540 : } else {
541 0 : log_err( _("Extended attributes were not removed.\n"));
542 : }
543 0 : return 0;
544 : }
545 :
546 0 : static int undo_eattr_indir_or_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
547 : uint64_t parent,
548 : struct lgfs2_buffer_head **bh,
549 : void *private)
550 : {
551 0 : struct lgfs2_sbd *sdp = ip->i_sbd;
552 : int q;
553 : int error;
554 0 : struct block_count *bc = (struct block_count *) private;
555 :
556 0 : if (!valid_block_ip(ip, block))
557 0 : return META_ERROR;
558 :
559 : /* Need to check block_type before undoing the reference, which can
560 : set it to free, which would cause the test below to fail. */
561 0 : q = block_type(bl, block);
562 :
563 0 : error = undo_reference(cx, ip, block, 0, private);
564 0 : if (error)
565 0 : return error;
566 :
567 0 : bc->ea_count--;
568 :
569 0 : if (q != GFS2_BLKST_USED)
570 0 : return 1;
571 :
572 0 : *bh = lgfs2_bread(sdp, block);
573 0 : return 0;
574 : }
575 :
576 : /* complain_eas - complain about extended attribute errors for an inode
577 : *
578 : * @ip - in core inode pointer
579 : * block - the block that had the problem
580 : * duplicate - if this is a duplicate block, don't set it "free"
581 : * emsg - what to tell the user about the eas being checked
582 : * Returns: 1 if the EA is fixed, else 0 if it was not fixed.
583 : */
584 0 : static void complain_eas(struct lgfs2_inode *ip, uint64_t block,
585 : const char *emsg)
586 : {
587 0 : log_err(_("Inode #%"PRIu64" (0x%"PRIx64"): %s"), ip->i_num.in_addr, ip->i_num.in_addr, emsg);
588 0 : log_err(_(" at block #%"PRIu64" (0x%"PRIx64").\n"), block, block);
589 0 : }
590 :
591 0 : static int p1_check_eattr_indir(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t indirect,
592 : uint64_t parent, struct lgfs2_buffer_head **bh,
593 : void *private)
594 : {
595 0 : struct lgfs2_sbd *sdp = ip->i_sbd;
596 0 : int ret = 0;
597 : int q;
598 0 : struct block_count *bc = (struct block_count *) private;
599 :
600 : /* This inode contains an eattr - it may be invalid, but the
601 : * eattr attributes points to a non-zero block */
602 0 : if (!valid_block_ip(ip, indirect)) {
603 : /* Doesn't help to mark this here - this gets checked
604 : * in pass1c */
605 0 : return 1;
606 : }
607 0 : q = block_type(bl, indirect);
608 :
609 : /* Special duplicate processing: If we have an EA block,
610 : check if it really is an EA. If it is, let duplicate
611 : handling sort it out. If it isn't, clear it but don't
612 : count it as a duplicate. */
613 0 : *bh = lgfs2_bread(sdp, indirect);
614 0 : if (lgfs2_check_meta((*bh)->b_data, GFS2_METATYPE_IN)) {
615 0 : bc->ea_count++;
616 0 : if (q != GFS2_BLKST_FREE) { /* Duplicate? */
617 0 : add_duplicate_ref(cx, ip, indirect, REF_AS_EA, 0,
618 : INODE_VALID);
619 0 : complain_eas(ip, indirect,
620 0 : _("Bad indirect Extended Attribute "
621 : "duplicate found"));
622 : /* Return 0 here because if all that's wrong is a
623 : duplicate block reference, we want pass1b to figure
624 : it out. We don't want to delete all the extended
625 : attributes as if they are in error. */
626 0 : return 0;
627 : }
628 0 : complain_eas(ip, indirect,
629 0 : _("Extended Attribute indirect block has "
630 : "incorrect type"));
631 0 : return 1;
632 : }
633 0 : if (q != GFS2_BLKST_FREE) { /* Duplicate? */
634 0 : add_duplicate_ref(cx, ip, indirect, REF_AS_EA, 0, INODE_VALID);
635 0 : complain_eas(ip, indirect,
636 0 : _("Duplicate Extended Attribute indirect block"));
637 0 : bc->ea_count++;
638 0 : ret = 0; /* For the same reason stated above. */
639 : } else {
640 0 : fsck_blockmap_set(cx, ip, indirect,
641 : _("indirect Extended Attribute"), GFS2_BLKST_USED);
642 0 : bc->ea_count++;
643 : }
644 0 : return ret;
645 : }
646 :
647 0 : static int p1_finish_eattr_indir(struct fsck_cx *cx, struct lgfs2_inode *ip, int leaf_pointers,
648 : int leaf_pointer_errors, void *private)
649 : {
650 0 : struct block_count *bc = (struct block_count *) private;
651 :
652 0 : if (leaf_pointer_errors == leaf_pointers) /* All eas were bad */
653 0 : return ask_remove_inode_eattr(cx, ip, bc);
654 0 : log_debug(_("Marking inode #%"PRIu64" (0x%"PRIx64") with extended attribute block\n"),
655 : ip->i_num.in_addr, ip->i_num.in_addr);
656 0 : if (!leaf_pointer_errors)
657 0 : return 0;
658 0 : log_err(_("Inode %"PRIu64" (0x%"PRIx64") has recoverable indirect extended attribute errors.\n"),
659 : ip->i_num.in_addr, ip->i_num.in_addr);
660 0 : if (query(cx, _("Okay to fix the block count for the inode? (y/n) "))) {
661 0 : ip->i_blocks = 1 + bc->indir_count + bc->data_count + bc->ea_count;
662 0 : lgfs2_bmodified(ip->i_bh);
663 0 : log_err(_("Block count fixed: 1+%"PRIu64"+%"PRIu64"+%"PRIu64" = %"PRIu64".\n"),
664 : bc->indir_count, bc->data_count, bc->ea_count, ip->i_blocks);
665 0 : return 1;
666 : }
667 0 : log_err( _("Block count not fixed.\n"));
668 0 : return 1;
669 : }
670 :
671 : /* check_ealeaf_block
672 : * checks an extended attribute (not directory) leaf block
673 : */
674 0 : static int check_ealeaf_block(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, int btype,
675 : struct lgfs2_buffer_head **bh, void *private)
676 : {
677 0 : struct lgfs2_buffer_head *leaf_bh = NULL;
678 0 : struct lgfs2_sbd *sdp = ip->i_sbd;
679 : int q;
680 0 : struct block_count *bc = (struct block_count *) private;
681 :
682 0 : q = block_type(bl, block);
683 : /* Special duplicate processing: If we have an EA block, check if it
684 : really is an EA. If it is, let duplicate handling sort it out.
685 : If it isn't, clear it but don't count it as a duplicate. */
686 0 : leaf_bh = lgfs2_bread(sdp, block);
687 0 : if (lgfs2_check_meta(leaf_bh->b_data, btype)) {
688 0 : bc->ea_count++;
689 0 : if (q != GFS2_BLKST_FREE) { /* Duplicate? */
690 0 : add_duplicate_ref(cx, ip, block, REF_AS_EA, 0,
691 : INODE_VALID);
692 0 : complain_eas(ip, block, _("Extended attribute leaf "
693 : "duplicate found"));
694 0 : lgfs2_bfree(&leaf_bh);
695 : /* Return 0 here because if all that's wrong is a
696 : duplicate block reference, we want pass1b to figure
697 : it out. We don't want to delete all the extended
698 : attributes as if they are in error. */
699 0 : return 0;
700 : }
701 0 : complain_eas(ip, block, _("Extended Attribute leaf block has "
702 : "incorrect type"));
703 0 : lgfs2_brelse(leaf_bh);
704 0 : return 1;
705 : }
706 0 : if (q != GFS2_BLKST_FREE) { /* Duplicate? */
707 0 : complain_eas(ip, block, _("Extended Attribute leaf "
708 : "duplicate found"));
709 0 : add_duplicate_ref(cx, ip, block, REF_AS_DATA, 0, INODE_VALID);
710 0 : bc->ea_count++;
711 0 : lgfs2_brelse(leaf_bh);
712 : /* Return 0 here because if all that's wrong is a duplicate
713 : block reference, we want pass1b to figure it out. We don't
714 : want to delete all the extended attributes as if they are
715 : in error. */
716 0 : return 0;
717 : }
718 : /* Point of confusion: We've got to set the ea block itself to
719 : GFS2_BLKST_USED here. Elsewhere we mark the inode with
720 : gfs2_eattr_block meaning it contains an eattr. */
721 0 : fsck_blockmap_set(cx, ip, block, _("Extended Attribute"), GFS2_BLKST_USED);
722 0 : bc->ea_count++;
723 0 : *bh = leaf_bh;
724 0 : return 0;
725 : }
726 :
727 : /**
728 : * p1_check_extended_leaf_eattr
729 : * @ip
730 : * @el_blk: block number of the extended leaf
731 : *
732 : * An EA leaf block can contain EA's with pointers to blocks
733 : * where the data for that EA is kept. Those blocks still
734 : * have the gfs2 meta header of type GFS2_METATYPE_EA
735 : *
736 : * Returns: 0 if correct[able], -1 if removal is needed
737 : */
738 0 : static int p1_check_extended_leaf_eattr(struct fsck_cx *cx, struct lgfs2_inode *ip, int i,
739 : __be64 *data_ptr,
740 : struct lgfs2_buffer_head *leaf_bh,
741 : uint32_t tot_ealen,
742 : struct gfs2_ea_header *ea_hdr,
743 : struct gfs2_ea_header *ea_hdr_prev,
744 : void *private)
745 : {
746 0 : uint64_t el_blk = be64_to_cpu(*data_ptr);
747 0 : struct lgfs2_buffer_head *bh = NULL;
748 0 : int error = 0;
749 :
750 0 : if (!valid_block_ip(ip, el_blk)) {
751 0 : log_err(_("Inode #%"PRIu64" (0x%"PRIx64"): extended attribute block "
752 : "%"PRIu64" (0x%"PRIx64") has an extended leaf block #%"PRIu64" "
753 : "(0x%"PRIx64") that is invalid or out of range.\n"),
754 : ip->i_num.in_addr, ip->i_num.in_addr, ip->i_eattr, ip->i_eattr, el_blk, el_blk);
755 0 : fsck_blockmap_set(cx, ip, ip->i_eattr, _("bad (out of range) Extended Attribute "),
756 : GFS2_BLKST_UNLINKED);
757 0 : error = 1;
758 : } else {
759 0 : error = check_ealeaf_block(cx, ip, el_blk, GFS2_METATYPE_ED, &bh,
760 : private);
761 : }
762 0 : if (bh)
763 0 : lgfs2_brelse(bh);
764 0 : if (error) {
765 0 : log_err(_("Bad extended attribute found at block %"PRIu64" (0x%"PRIx64")"),
766 : be64_to_cpu(*data_ptr), be64_to_cpu(*data_ptr));
767 0 : if (query(cx, _("Repair the bad Extended Attribute? (y/n) "))) {
768 0 : ea_hdr->ea_num_ptrs = i;
769 0 : ea_hdr->ea_data_len = cpu_to_be32(tot_ealen);
770 0 : *data_ptr = 0;
771 0 : lgfs2_bmodified(leaf_bh);
772 : /* Endianness doesn't matter in this case because it's
773 : a single byte. */
774 0 : fsck_blockmap_set(cx, ip, ip->i_eattr,
775 : _("extended attribute"),
776 : GFS2_BLKST_USED);
777 0 : log_err( _("The EA was fixed.\n"));
778 0 : error = 0;
779 : } else {
780 0 : error = 1;
781 0 : log_err( _("The bad EA was not fixed.\n"));
782 : }
783 : }
784 0 : return error;
785 : }
786 :
787 0 : static int p1_check_eattr_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
788 : uint64_t parent, struct lgfs2_buffer_head **bh,
789 : void *private)
790 : {
791 0 : if (!valid_block_ip(ip, block)) {
792 0 : log_warn(_("Inode #%"PRIu64" (0x%"PRIx64"): extended attribute leaf "
793 : "block #%"PRIu64" (0x%"PRIx64") is invalid or out of "
794 : "range.\n"),
795 : ip->i_num.in_addr, ip->i_num.in_addr, block, block);
796 0 : fsck_blockmap_set(cx, ip, ip->i_eattr, _("bad (out of range) extended attribute leaf"),
797 : GFS2_BLKST_UNLINKED);
798 0 : return 1;
799 : }
800 0 : return check_ealeaf_block(cx, ip, block, GFS2_METATYPE_EA, bh, private);
801 : }
802 :
803 0 : static int ask_remove_eattr_entry(struct fsck_cx *cx,
804 : struct lgfs2_buffer_head *leaf_bh,
805 : struct gfs2_ea_header *curr,
806 : struct gfs2_ea_header *prev,
807 : int fix_curr, int fix_curr_len)
808 : {
809 0 : if (!query(cx, _("Remove the bad Extended Attribute entry? (y/n) "))) {
810 0 : log_err( _("Bad Extended Attribute not removed.\n"));
811 0 : return 0;
812 : }
813 0 : if (fix_curr)
814 0 : curr->ea_flags |= GFS2_EAFLAG_LAST;
815 0 : if (fix_curr_len) {
816 0 : uint32_t max_size = cx->sdp->sd_bsize;
817 0 : uint32_t offset = (uint32_t)(((unsigned long)curr) -
818 0 : ((unsigned long)leaf_bh->b_data));
819 0 : curr->ea_rec_len = cpu_to_be32(max_size - offset);
820 : }
821 0 : if (!prev)
822 0 : curr->ea_type = GFS2_EATYPE_UNUSED;
823 : else {
824 0 : uint32_t tmp32 = be32_to_cpu(curr->ea_rec_len) +
825 0 : be32_to_cpu(prev->ea_rec_len);
826 0 : prev->ea_rec_len = cpu_to_be32(tmp32);
827 0 : if (curr->ea_flags & GFS2_EAFLAG_LAST)
828 0 : prev->ea_flags |= GFS2_EAFLAG_LAST;
829 : }
830 0 : log_err(_("Bad Extended Attribute at block %"PRIu64" (0x%"PRIx64") removed.\n"),
831 : leaf_bh->b_blocknr, leaf_bh->b_blocknr);
832 0 : lgfs2_bmodified(leaf_bh);
833 0 : return 1;
834 : }
835 :
836 0 : static int eatype_max(unsigned fs_format)
837 : {
838 0 : int max = 4;
839 0 : if (fs_format < 1802)
840 0 : max = 3;
841 0 : return max;
842 : }
843 :
844 0 : static int p1_check_eattr_entry(struct fsck_cx *cx, struct lgfs2_inode *ip,
845 : struct lgfs2_buffer_head *leaf_bh,
846 : struct gfs2_ea_header *ea_hdr,
847 : struct gfs2_ea_header *ea_hdr_prev,
848 : void *private)
849 : {
850 0 : struct lgfs2_sbd *sdp = ip->i_sbd;
851 : char ea_name[256];
852 0 : uint32_t offset_limit = sdp->sd_bsize - sizeof(struct gfs2_ea_header);
853 0 : uint32_t offset = (uint32_t)(((unsigned long)ea_hdr) -
854 0 : ((unsigned long)leaf_bh->b_data));
855 0 : uint32_t rec_len = be32_to_cpu(ea_hdr->ea_rec_len);
856 : uint32_t avail_size;
857 : int max_ptrs;
858 :
859 0 : if (!ea_hdr->ea_name_len){
860 0 : log_err( _("EA has name length of zero\n"));
861 0 : return ask_remove_eattr_entry(cx, leaf_bh, ea_hdr,
862 : ea_hdr_prev, 1, 1);
863 : }
864 0 : if (offset + rec_len > offset_limit &&
865 0 : offset + rec_len != sdp->sd_bsize) {
866 0 : log_err( _("EA record length too long (%"PRIu32"+%"PRIu32")\n"),
867 : offset, rec_len);
868 0 : return ask_remove_eattr_entry(cx, leaf_bh, ea_hdr,
869 : ea_hdr_prev, 1, 1);
870 : }
871 0 : if (offset + rec_len == sdp->sd_bsize &&
872 0 : (ea_hdr->ea_flags & GFS2_EAFLAG_LAST) == 0){
873 0 : log_err( _("last EA has no last entry flag\n"));
874 0 : return ask_remove_eattr_entry(cx, leaf_bh, ea_hdr,
875 : ea_hdr_prev, 0, 0);
876 : }
877 0 : if (!ea_hdr->ea_name_len){
878 0 : log_err( _("EA has name length of zero\n"));
879 0 : return ask_remove_eattr_entry(cx, leaf_bh, ea_hdr,
880 : ea_hdr_prev, 0, 0);
881 : }
882 :
883 0 : memset(ea_name, 0, sizeof(ea_name));
884 0 : strncpy(ea_name, (char *)ea_hdr + sizeof(struct gfs2_ea_header),
885 0 : ea_hdr->ea_name_len);
886 :
887 0 : if (ea_hdr->ea_type > eatype_max(sdp->sd_fs_format) &&
888 0 : ((ea_hdr_prev) || (!ea_hdr_prev && ea_hdr->ea_type))){
889 : /* Skip invalid entry */
890 0 : log_err(_("EA (%s) type is invalid (%d > %d).\n"),
891 : ea_name, ea_hdr->ea_type, eatype_max(sdp->sd_fs_format));
892 0 : return ask_remove_eattr_entry(cx, leaf_bh, ea_hdr,
893 : ea_hdr_prev, 0, 0);
894 : }
895 :
896 0 : if (!ea_hdr->ea_num_ptrs)
897 0 : return 0;
898 :
899 0 : avail_size = sdp->sd_bsize - sizeof(struct gfs2_meta_header);
900 0 : max_ptrs = (be32_to_cpu(ea_hdr->ea_data_len)+avail_size-1)/avail_size;
901 :
902 0 : if (max_ptrs > ea_hdr->ea_num_ptrs) {
903 0 : log_err(_("EA (%s) has incorrect number of pointers.\n"),
904 : ea_name);
905 0 : log_err(_(" Required: %d\n Reported: %d\n"),
906 : max_ptrs, ea_hdr->ea_num_ptrs);
907 0 : return ask_remove_eattr_entry(cx, leaf_bh, ea_hdr,
908 : ea_hdr_prev, 0, 0);
909 : } else {
910 0 : log_debug( _(" Pointers Required: %d\n Pointers Reported: %d\n"),
911 : max_ptrs, ea_hdr->ea_num_ptrs);
912 : }
913 0 : return 0;
914 : }
915 :
916 : /**
917 : * Check for massive amounts of pointer corruption. If the block has
918 : * lots of out-of-range pointers, we can't trust any of the pointers.
919 : * For example, a stray pointer with a value of 0x1d might be
920 : * corruption/nonsense, and if so, we don't want to delete an
921 : * important file (like master or the root directory) because of it.
922 : * We need to check for a large number of bad pointers BEFORE we start
923 : * messing with them because we don't want to mark a block as a
924 : * duplicate (for example) until we know if the pointers in general can
925 : * be trusted. Thus it needs to be in a separate loop.
926 : * Returns: 0 if good range, otherwise != 0
927 : */
928 : enum b_types { BTYPE_META, BTYPE_LEAF, BTYPE_DATA, BTYPE_IEATTR, BTYPE_EATTR};
929 : static const char *btypes[5] = {
930 : "metadata", "leaf", "data", "indirect extended attribute",
931 : "extended attribute" };
932 :
933 1981046 : static int rangecheck_block(struct lgfs2_inode *ip, uint64_t block,
934 : struct lgfs2_buffer_head **bh, enum b_types btype,
935 : void *private)
936 : {
937 1981046 : long *bad_pointers = (long *)private;
938 : int q;
939 :
940 1981046 : if (!valid_block_ip(ip, block)) {
941 0 : (*bad_pointers)++;
942 0 : log_info(_("Bad %s block pointer (invalid or out of range "
943 : "#%ld) found in inode %"PRIu64" (0x%"PRIx64").\n"),
944 : btypes[btype], *bad_pointers, ip->i_num.in_addr, ip->i_num.in_addr);
945 0 : if ((*bad_pointers) <= BAD_POINTER_TOLERANCE)
946 0 : return META_IS_GOOD;
947 : else
948 0 : return META_ERROR; /* Exits check_metatree quicker */
949 : }
950 : /* See how many duplicate blocks it has */
951 1981046 : q = block_type(bl, block);
952 1981046 : if (q != GFS2_BLKST_FREE) {
953 0 : (*bad_pointers)++;
954 0 : log_info(_("Duplicated %s block pointer (violation %ld, block %"PRIu64
955 : " (0x%"PRIx64")) found in inode %"PRIu64" (0x%"PRIx64").\n"),
956 : btypes[btype], *bad_pointers, block, block, ip->i_num.in_addr, ip->i_num.in_addr);
957 0 : if ((*bad_pointers) <= BAD_POINTER_TOLERANCE)
958 0 : return META_IS_GOOD;
959 : else {
960 0 : log_debug(_("Inode 0x%"PRIx64" bad pointer tolerance "
961 : "exceeded: block 0x%"PRIx64".\n"),
962 : ip->i_num.in_addr, block);
963 0 : return META_ERROR; /* Exits check_metatree quicker */
964 : }
965 : }
966 1981046 : return META_IS_GOOD;
967 : }
968 :
969 7361 : static int rangecheck_metadata(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
970 : int *is_valid, int *was_duplicate, void *private)
971 : {
972 7361 : struct lgfs2_inode *ip = iptr.ipt_ip;
973 7361 : uint64_t block = iptr_block(iptr);
974 :
975 7361 : *is_valid = 1;
976 7361 : *was_duplicate = 0;
977 7361 : return rangecheck_block(ip, block, bh, BTYPE_META, private);
978 : }
979 :
980 9 : static int rangecheck_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
981 : void *private)
982 : {
983 9 : return rangecheck_block(ip, block, NULL, BTYPE_LEAF, private);
984 : }
985 :
986 1973676 : static int rangecheck_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
987 : uint64_t block, void *private,
988 : struct lgfs2_buffer_head *bh, __be64 *ptr)
989 : {
990 1973676 : return rangecheck_block(ip, block, NULL, BTYPE_DATA, private);
991 : }
992 :
993 0 : static int rangecheck_eattr_indir(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
994 : uint64_t parent,
995 : struct lgfs2_buffer_head **bh, void *private)
996 : {
997 0 : return rangecheck_block(ip, block, NULL, BTYPE_IEATTR, private);
998 : }
999 :
1000 0 : static int rangecheck_eattr_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
1001 : uint64_t parent, struct lgfs2_buffer_head **bh,
1002 : void *private)
1003 : {
1004 0 : return rangecheck_block(ip, block, NULL, BTYPE_EATTR, private);
1005 : }
1006 :
1007 : static struct metawalk_fxns rangecheck_fxns = {
1008 : .private = NULL,
1009 : .readahead = 1,
1010 : .check_metalist = rangecheck_metadata,
1011 : .check_data = rangecheck_data,
1012 : .check_leaf = rangecheck_leaf,
1013 : .check_eattr_indir = rangecheck_eattr_indir,
1014 : .check_eattr_leaf = rangecheck_eattr_leaf,
1015 : .delete_block = p1_delete_block,
1016 : };
1017 :
1018 : static struct metawalk_fxns eattr_undo_fxns = {
1019 : .private = NULL,
1020 : .check_eattr_indir = undo_eattr_indir_or_leaf,
1021 : .check_eattr_leaf = undo_eattr_indir_or_leaf,
1022 : .finish_eattr_indir = p1_finish_eattr_indir,
1023 : .delete_block = p1_delete_block,
1024 : };
1025 : /* set_ip_blockmap - set the blockmap for a dinode
1026 : *
1027 : * returns: 0 if no error, -EINVAL if dinode has a bad mode, -EPERM on error
1028 : */
1029 700 : static int set_ip_blockmap(struct fsck_cx *cx, struct lgfs2_inode *ip)
1030 : {
1031 700 : uint64_t block = ip->i_bh->b_blocknr;
1032 : struct lgfs2_inum no;
1033 : uint32_t mode;
1034 : const char *ty;
1035 :
1036 700 : mode = ip->i_mode & S_IFMT;
1037 :
1038 700 : switch (mode) {
1039 224 : case S_IFDIR:
1040 224 : ty = "directory";
1041 224 : break;
1042 476 : case S_IFREG:
1043 476 : ty = "file";
1044 476 : break;
1045 0 : case S_IFLNK:
1046 0 : ty = "symlink";
1047 0 : break;
1048 0 : case S_IFBLK:
1049 0 : ty = "block device";
1050 0 : break;
1051 0 : case S_IFCHR:
1052 0 : ty = "character device";
1053 0 : break;
1054 0 : case S_IFIFO:
1055 0 : ty = "fifo";
1056 0 : break;
1057 0 : case S_IFSOCK:
1058 0 : ty = "socket";
1059 0 : break;
1060 0 : default:
1061 0 : return -EINVAL;
1062 : }
1063 700 : no = ip->i_num;
1064 700 : if (fsck_blockmap_set(cx, ip, block, ty, GFS2_BLKST_DINODE) ||
1065 224 : (mode == S_IFDIR && !dirtree_insert(cx, no))) {
1066 0 : stack;
1067 0 : return -EPERM;
1068 : }
1069 700 : return 0;
1070 : }
1071 :
1072 0 : static int alloc_metalist(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
1073 : int *is_valid, int *was_duplicate, void *private)
1074 : {
1075 0 : const char *desc = (const char *)private;
1076 0 : struct lgfs2_inode *ip = iptr.ipt_ip;
1077 0 : uint64_t block = iptr_block(iptr);
1078 : int q;
1079 :
1080 : /* No need to range_check here--if it was added, it's in range. */
1081 : /* We can't check the bitmap here because this function is called
1082 : after the bitmap has been set but before the blockmap has. */
1083 0 : *is_valid = 1;
1084 0 : *was_duplicate = 0;
1085 0 : *bh = lgfs2_bread(ip->i_sbd, block);
1086 0 : q = bitmap_type(ip->i_sbd, block);
1087 0 : if (q == GFS2_BLKST_FREE) {
1088 0 : log_debug(_("%s reference to new metadata block %"PRIu64" (0x%"PRIx64") is now marked as indirect.\n"),
1089 : desc, block, block);
1090 0 : blockmap_set(bl, block, GFS2_BLKST_USED);
1091 : }
1092 0 : return META_IS_GOOD;
1093 : }
1094 :
1095 0 : static int alloc_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
1096 : uint64_t block, void *private,
1097 : struct lgfs2_buffer_head *bh, __be64 *ptr)
1098 : {
1099 : int q;
1100 0 : const char *desc = (const char *)private;
1101 :
1102 : /* No need to range_check here--if it was added, it's in range. */
1103 : /* We can't check the bitmap here because this function is called
1104 : after the bitmap has been set but before the blockmap has. */
1105 0 : q = bitmap_type(ip->i_sbd, block);
1106 0 : if (q == GFS2_BLKST_FREE) {
1107 0 : log_debug(_("%s reference to new data block %"PRIu64" (0x%"PRIx64") is now marked as data.\n"),
1108 : desc, block, block);
1109 0 : blockmap_set(bl, block, GFS2_BLKST_USED);
1110 : }
1111 0 : return 0;
1112 : }
1113 :
1114 0 : static int alloc_leaf(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block, void *private)
1115 : {
1116 : int q;
1117 :
1118 : /* No need to range_check here--if it was added, it's in range. */
1119 : /* We can't check the bitmap here because this function is called
1120 : after the bitmap has been set but before the blockmap has. */
1121 0 : q = bitmap_type(ip->i_sbd, block);
1122 0 : if (q == GFS2_BLKST_FREE)
1123 0 : fsck_blockmap_set(cx, ip, block, "newly allocated leaf",
1124 : GFS2_BLKST_USED);
1125 0 : return 0;
1126 : }
1127 :
1128 : static struct metawalk_fxns alloc_fxns = {
1129 : .private = NULL,
1130 : .check_leaf = alloc_leaf,
1131 : .check_metalist = alloc_metalist,
1132 : .check_data = alloc_data,
1133 : .check_eattr_indir = NULL,
1134 : .check_eattr_leaf = NULL,
1135 : .check_dentry = NULL,
1136 : .check_eattr_entry = NULL,
1137 : .check_eattr_extentry = NULL,
1138 : .finish_eattr_indir = NULL,
1139 : .delete_block = p1_delete_block,
1140 : };
1141 :
1142 : /*
1143 : * pass1_check_metatree - wrapper function for check_metatree
1144 : *
1145 : * Generic function check_metatree sets the bitmap values, but not the
1146 : * corresponding values in the blockmap. If we get an error, the inode will
1147 : * have been freed in the bitmap. We need to set the inode address as free
1148 : * as well.
1149 : */
1150 1407 : static int pass1_check_metatree(struct fsck_cx *cx, struct lgfs2_inode *ip,
1151 : struct metawalk_fxns *pass)
1152 : {
1153 : int error;
1154 :
1155 1407 : error = check_metatree(cx, ip, pass);
1156 1407 : if (error)
1157 0 : blockmap_set(bl, ip->i_num.in_addr, GFS2_BLKST_FREE);
1158 1407 : return error;
1159 : }
1160 :
1161 : /*
1162 : * reprocess_inode - fixes the blockmap to match the bitmap due to an
1163 : * unexpected block allocation via libgfs2.
1164 : *
1165 : * The problem we're trying to overcome here is when a new block must be
1166 : * added to a dinode because of a write. This will happen when lost+found
1167 : * needs a new indirect block for its hash table. In that case, the write
1168 : * causes a new block to be assigned in the bitmap but that block is not yet
1169 : * accurately reflected in the fsck blockmap. We need to compensate here.
1170 : *
1171 : * We can't really use fsck_blockmap_set here because the new block
1172 : * was already allocated by libgfs2 and therefore it took care of
1173 : * the rgrp free space variable. fsck_blockmap_set adjusts the free space
1174 : * in the rgrp according to the change, which has already been done.
1175 : * So it's only our blockmap that now disagrees with the rgrp bitmap, so we
1176 : * need to fix only that.
1177 : */
1178 0 : static void reprocess_inode(struct fsck_cx *cx, struct lgfs2_inode *ip, const char *desc)
1179 : {
1180 : int error;
1181 :
1182 0 : alloc_fxns.private = (void *)desc;
1183 0 : log_info(_("%s inode %"PRIu64" (0x%"PRIx64") had blocks added; reprocessing "
1184 : "its metadata tree at height=%d.\n"), desc,
1185 : ip->i_num.in_addr, ip->i_num.in_addr, ip->i_height);
1186 0 : error = pass1_check_metatree(cx, ip, &alloc_fxns);
1187 0 : if (error)
1188 0 : log_err( _("Error %d reprocessing the %s metadata tree.\n"),
1189 : error, desc);
1190 0 : }
1191 :
1192 : /*
1193 : * handle_ip - process an incore structure representing a dinode.
1194 : */
1195 700 : static int handle_ip(struct fsck_cx *cx, struct lgfs2_inode *ip)
1196 : {
1197 : int error;
1198 700 : struct block_count bc = {0};
1199 : long bad_pointers;
1200 700 : uint64_t lf_blks = 0;
1201 :
1202 700 : bad_pointers = 0L;
1203 :
1204 : /* First, check the metadata for massive amounts of pointer corruption.
1205 : Such corruption can only lead us to ruin trying to clean it up,
1206 : so it's better to check it up front and delete the inode if
1207 : there is corruption. */
1208 700 : rangecheck_fxns.private = &bad_pointers;
1209 700 : error = pass1_check_metatree(cx, ip, &rangecheck_fxns);
1210 700 : if (bad_pointers > BAD_POINTER_TOLERANCE) {
1211 0 : log_err(_("Error: inode %"PRIu64" (0x%"PRIx64") has more than %d bad pointers.\n"),
1212 : ip->i_num.in_addr, ip->i_num.in_addr, BAD_POINTER_TOLERANCE);
1213 0 : fsck_blockmap_set(cx, ip, ip->i_num.in_addr, _("badly corrupt"), GFS2_BLKST_FREE);
1214 0 : return 0;
1215 : }
1216 :
1217 700 : error = set_ip_blockmap(cx, ip);
1218 700 : if (error == -EINVAL) {
1219 : /* We found a dinode that has an invalid mode. At this point
1220 : set_ip_blockmap returned an error, which means it never
1221 : got inserted into the inode tree. Since we haven't even
1222 : processed its metadata with pass1_fxns, none of its
1223 : metadata will be flagged as metadata or data blocks yet.
1224 : Therefore, we don't need to invalidate anything. */
1225 0 : fsck_blockmap_set(cx, ip, ip->i_num.in_addr, _("invalid mode"), GFS2_BLKST_FREE);
1226 0 : return 0;
1227 700 : } else if (error)
1228 0 : goto bad_dinode;
1229 :
1230 700 : if (set_di_nlink(cx, ip))
1231 0 : goto bad_dinode;
1232 :
1233 700 : if (lf_dip)
1234 0 : lf_blks = lf_dip->i_blocks;
1235 :
1236 700 : pass1_fxns.private = &bc;
1237 700 : error = pass1_check_metatree(cx, ip, &pass1_fxns);
1238 :
1239 : /* Pass1 may have added some blocks to lost+found by virtue of leafs
1240 : that were misplaced. If it did, we need to reprocess lost+found
1241 : to correctly account for its blocks. */
1242 700 : if (lf_dip && lf_dip->i_blocks != lf_blks)
1243 0 : reprocess_inode(cx, lf_dip, "lost+found");
1244 :
1245 : /* We there was an error, we return 0 because we want fsck to continue
1246 : and analyze the other dinodes as well. */
1247 700 : if (fsck_abort)
1248 0 : return 0;
1249 :
1250 700 : if (!error) {
1251 700 : error = check_inode_eattr(cx, ip, &pass1_fxns);
1252 :
1253 700 : if (error) {
1254 0 : if (!query(cx, _("Clear the bad Extended Attributes? (y/n) "))) {
1255 0 : log_err(_("The bad Extended Attributes were not fixed.\n"));
1256 0 : return 0;
1257 : }
1258 0 : log_err(_("Clearing the bad Extended Attributes in "
1259 : "inode %"PRIu64" (0x%"PRIx64").\n"),
1260 : ip->i_num.in_addr, ip->i_num.in_addr);
1261 0 : eattr_undo_fxns.private = &bc;
1262 0 : check_inode_eattr(cx, ip, &eattr_undo_fxns);
1263 0 : ask_remove_inode_eattr(cx, ip, &bc);
1264 0 : return 1;
1265 : }
1266 : }
1267 :
1268 700 : if (ip->i_blocks != (1 + bc.indir_count + bc.data_count + bc.ea_count)) {
1269 0 : log_err(_("Inode #%"PRIu64" (0x%"PRIx64"): Ondisk block count (%"PRIu64
1270 : ") does not match what fsck found (%"PRIu64")\n"),
1271 : ip->i_num.in_addr, ip->i_num.in_addr, ip->i_blocks, 1 + bc.indir_count +
1272 : bc.data_count + bc.ea_count);
1273 0 : log_info(_("inode has: %"PRIu64", but fsck counts: Dinode:1 + "
1274 : "indir:%"PRIu64" + data: %"PRIu64" + ea: %"PRIu64"\n"),
1275 : ip->i_blocks, bc.indir_count, bc.data_count, bc.ea_count);
1276 0 : if (query(cx, _("Fix ondisk block count? (y/n) "))) {
1277 0 : ip->i_blocks = 1 + bc.indir_count + bc.data_count + bc.ea_count;
1278 0 : lgfs2_bmodified(ip->i_bh);
1279 0 : log_err(_("Block count for #%"PRIu64" (0x%"PRIx64") fixed\n"),
1280 : ip->i_num.in_addr, ip->i_num.in_addr);
1281 : } else
1282 0 : log_err(_("Bad block count for #%"PRIu64" (0x%"PRIx64") not fixed\n"),
1283 : ip->i_num.in_addr, ip->i_num.in_addr);
1284 : }
1285 :
1286 700 : return 0;
1287 0 : bad_dinode:
1288 0 : stack;
1289 0 : return -1;
1290 : }
1291 :
1292 700 : static void check_i_goal(struct fsck_cx *cx, struct lgfs2_inode *ip)
1293 : {
1294 700 : if (ip->i_flags & GFS2_DIF_SYSTEM)
1295 644 : return;
1296 :
1297 56 : if (ip->i_goal_meta <= LGFS2_SB_ADDR(cx->sdp) ||
1298 55 : ip->i_goal_meta > cx->sdp->fssize) {
1299 1 : log_err(_("Inode #%"PRIu64" (0x%"PRIx64"): Bad allocation goal block "
1300 : "found: %"PRIu64" (0x%"PRIx64")\n"),
1301 : ip->i_num.in_addr, ip->i_num.in_addr, ip->i_goal_meta, ip->i_goal_meta);
1302 1 : if (query(cx, _("Fix goal block in inode #%"PRIu64" (0x%"PRIx64")? (y/n) "),
1303 : ip->i_num.in_addr, ip->i_num.in_addr)) {
1304 1 : ip->i_goal_meta = ip->i_num.in_addr;
1305 1 : lgfs2_bmodified(ip->i_bh);
1306 : } else
1307 0 : log_err(_("Allocation goal block in inode #%"PRIu64
1308 : " (0x%"PRIx64") not fixed\n"),
1309 : ip->i_num.in_addr, ip->i_num.in_addr);
1310 : }
1311 : }
1312 :
1313 : /*
1314 : * handle_di - This is now a wrapper function that takes a lgfs2_buffer_head
1315 : * and calls handle_ip, which takes an in-code dinode structure.
1316 : */
1317 189 : static int handle_di(struct fsck_cx *cx, struct lgfs2_rgrp_tree *rgd,
1318 : struct lgfs2_buffer_head *bh)
1319 : {
1320 189 : int error = 0;
1321 189 : uint64_t block = bh->b_blocknr;
1322 : struct lgfs2_inode *ip;
1323 :
1324 189 : ip = fsck_inode_get(cx->sdp, rgd, bh);
1325 :
1326 189 : if (ip->i_num.in_addr != block) {
1327 0 : log_err(_("Inode #%"PRIu64" (0x%"PRIx64"): Bad inode address found: %"PRIu64
1328 : " (0x%"PRIx64")\n"),
1329 : block, block, ip->i_num.in_addr, ip->i_num.in_addr);
1330 0 : if (query(cx, _("Fix address in inode at block #%"PRIu64" (0x%"PRIx64")? (y/n) "),
1331 : block, block)) {
1332 0 : ip->i_num.in_addr = ip->i_num.in_formal_ino = block;
1333 0 : lgfs2_bmodified(ip->i_bh);
1334 : } else
1335 0 : log_err(_("Address in inode at block #%"PRIu64" (0x%"PRIx64" not fixed\n"),
1336 : block, block);
1337 : }
1338 189 : check_i_goal(cx, ip);
1339 189 : error = handle_ip(cx, ip);
1340 189 : fsck_inode_put(&ip);
1341 189 : return error;
1342 : }
1343 :
1344 : /* Check system inode and verify it's marked "in use" in the bitmap: */
1345 : /* Should work for all system inodes: root, master, jindex, per_node, etc. */
1346 : /* We have to pass the sysinode as ** because the pointer may change out from
1347 : under the reference by way of the builder() function. */
1348 511 : static int check_system_inode(struct fsck_cx *cx,
1349 : struct lgfs2_inode **sysinode,
1350 : const char *filename,
1351 : int builder(struct lgfs2_sbd *sdp), int isdir,
1352 : struct lgfs2_inode *sysdir, int needs_sysbit)
1353 : {
1354 511 : uint64_t iblock = 0;
1355 511 : struct dir_status ds = {0};
1356 511 : int error, err = 0;
1357 :
1358 511 : log_info( _("Checking system inode '%s'\n"), filename);
1359 511 : if (*sysinode) {
1360 : /* Read in the system inode, look at its dentries, and start
1361 : * reading through them */
1362 510 : iblock = (*sysinode)->i_num.in_addr;
1363 510 : log_info(_("System inode for '%s' is located at block %"PRIu64" (0x%"PRIx64")\n"),
1364 : filename, iblock, iblock);
1365 510 : if (lgfs2_check_meta((*sysinode)->i_bh->b_data, GFS2_METATYPE_DI)) {
1366 0 : log_err(_("Found invalid system dinode at block %"PRIu64" (0x%"PRIx64")\n"),
1367 : iblock, iblock);
1368 0 : blockmap_set(bl, iblock, GFS2_BLKST_FREE);
1369 0 : check_n_fix_bitmap(cx, (*sysinode)->i_rgd, iblock, 0,
1370 : GFS2_BLKST_FREE);
1371 0 : lgfs2_inode_put(sysinode);
1372 : }
1373 : }
1374 511 : if (*sysinode) {
1375 510 : ds.q = block_type(bl, iblock);
1376 : /* If the inode exists but the block is marked free, we might
1377 : be recovering from a corrupt bitmap. In that case, don't
1378 : rebuild the inode. Just reuse the inode and fix the
1379 : bitmap. */
1380 510 : if (ds.q == GFS2_BLKST_FREE) {
1381 0 : log_info( _("The inode exists but the block is not "
1382 : "marked 'in use'; fixing it.\n"));
1383 0 : fsck_blockmap_set(cx, *sysinode, (*sysinode)->i_num.in_addr,
1384 : filename, GFS2_BLKST_DINODE);
1385 0 : ds.q = GFS2_BLKST_DINODE;
1386 0 : if (isdir) {
1387 0 : struct lgfs2_inum no = (*sysinode)->i_num;
1388 0 : dirtree_insert(cx, no);
1389 : }
1390 : }
1391 : /* Make sure it's marked as a system file/directory */
1392 510 : if (needs_sysbit &&
1393 454 : !((*sysinode)->i_flags & GFS2_DIF_SYSTEM)) {
1394 0 : log_err( _("System inode %s is missing the 'system' "
1395 : "flag. It should be rebuilt.\n"), filename);
1396 0 : if (sysdir && query(cx, _("Delete the corrupt %s system "
1397 : "inode? (y/n) "), filename)) {
1398 0 : lgfs2_inode_put(sysinode);
1399 0 : lgfs2_dirent_del(sysdir, filename,
1400 0 : strlen(filename));
1401 : /* Set the blockmap (but not bitmap) back to
1402 : 'free' so that it gets checked like any
1403 : normal dinode. */
1404 0 : blockmap_set(bl, iblock, GFS2_BLKST_FREE);
1405 0 : log_err( _("Removed system inode \"%s\".\n"),
1406 : filename);
1407 : }
1408 : }
1409 : } else
1410 1 : log_info( _("System inode for '%s' is corrupt or missing.\n"),
1411 : filename);
1412 : /* If there are errors with the inode here, we need to create a new
1413 : inode and get it all setup - of course, everything will be in
1414 : lost+found then, but we *need* our system inodes before we can
1415 : do any of that. */
1416 511 : if (!(*sysinode) || ds.q != GFS2_BLKST_DINODE) {
1417 1 : log_err(_("Invalid or missing %s system inode (is '%s', "
1418 : "should be '%s').\n"), filename,
1419 : block_type_string(ds.q),
1420 : block_type_string(GFS2_BLKST_DINODE));
1421 1 : if (query(cx, _("Create new %s system inode? (y/n) "), filename)) {
1422 1 : log_err( _("Rebuilding system file \"%s\"\n"),
1423 : filename);
1424 1 : error = builder(cx->sdp);
1425 1 : if (error || *sysinode == NULL) {
1426 0 : log_err( _("Error rebuilding system "
1427 : "inode %s: Cannot continue\n"),
1428 : filename);
1429 0 : return error;
1430 : }
1431 1 : if (*sysinode == cx->sdp->md.jiinode)
1432 0 : ji_update(cx->sdp);
1433 1 : fsck_blockmap_set(cx, *sysinode, (*sysinode)->i_num.in_addr,
1434 : filename, GFS2_BLKST_DINODE);
1435 1 : ds.q = GFS2_BLKST_DINODE;
1436 1 : if (isdir) {
1437 0 : struct lgfs2_inum no = (*sysinode)->i_num;
1438 0 : dirtree_insert(cx, no);
1439 : }
1440 : } else {
1441 0 : log_err( _("Cannot continue without valid %s inode\n"),
1442 : filename);
1443 0 : return -1;
1444 : }
1445 : }
1446 511 : if (is_dir(*sysinode)) {
1447 224 : struct block_count bc = {0};
1448 :
1449 224 : sysdir_fxns.private = &bc;
1450 224 : if ((*sysinode)->i_flags & GFS2_DIF_EXHASH)
1451 7 : pass1_check_metatree(cx, *sysinode, &sysdir_fxns);
1452 : else {
1453 217 : err = check_linear_dir(cx, *sysinode, (*sysinode)->i_bh,
1454 : &sysdir_fxns);
1455 : /* If we encountered an error in our directory check
1456 : we should still call handle_ip, but return the
1457 : error later. */
1458 217 : if (err)
1459 0 : log_err(_("Error found in %s while checking "
1460 : "directory entries.\n"), filename);
1461 : }
1462 : }
1463 511 : check_i_goal(cx, *sysinode);
1464 511 : error = handle_ip(cx, *sysinode);
1465 511 : return error ? error : err;
1466 : }
1467 :
1468 1 : static int build_a_journal(struct lgfs2_sbd *sdp)
1469 : {
1470 : char name[256];
1471 1 : int err = 0;
1472 :
1473 : /* First, try to delete the journal if it's in jindex */
1474 1 : sprintf(name, "journal%u", sdp->md.journals);
1475 1 : lgfs2_dirent_del(sdp->md.jiinode, name, strlen(name));
1476 : /* Now rebuild it */
1477 1 : err = lgfs2_build_journal(sdp, sdp->md.journals, sdp->md.jiinode);
1478 1 : if (err) {
1479 0 : log_crit(_("Error %d building journal\n"), err);
1480 0 : exit(FSCK_ERROR);
1481 : }
1482 1 : return 0;
1483 : }
1484 :
1485 0 : int build_per_node(struct lgfs2_sbd *sdp)
1486 : {
1487 : struct lgfs2_inode *per_node;
1488 : unsigned int j;
1489 :
1490 : /* coverity[identity_transfer:SUPPRESS] False positive */
1491 0 : per_node = lgfs2_createi(sdp->master_dir, "per_node", S_IFDIR | 0700,
1492 : GFS2_DIF_SYSTEM);
1493 0 : if (per_node == NULL) {
1494 0 : log_err(_("Error building '%s': %s\n"), "per_node", strerror(errno));
1495 0 : return -1;
1496 : }
1497 0 : for (j = 0; j < sdp->md.journals; j++) {
1498 : struct lgfs2_inode *ip;
1499 :
1500 : /* coverity[identity_transfer:SUPPRESS] False positive */
1501 0 : ip = lgfs2_build_inum_range(per_node, j);
1502 0 : if (ip == NULL) {
1503 0 : log_err(_("Error building '%s': %s\n"), "inum_range",
1504 : strerror(errno));
1505 0 : lgfs2_inode_put(&per_node);
1506 0 : return 1;
1507 : }
1508 0 : lgfs2_inode_put(&ip);
1509 :
1510 : /* coverity[identity_transfer:SUPPRESS] False positive */
1511 0 : ip = lgfs2_build_statfs_change(per_node, j);
1512 0 : if (ip == NULL) {
1513 0 : log_err(_("Error building '%s': %s\n"), "statfs_change",
1514 : strerror(errno));
1515 0 : lgfs2_inode_put(&per_node);
1516 0 : return 1;
1517 : }
1518 0 : lgfs2_inode_put(&ip);
1519 :
1520 : /* coverity[identity_transfer:SUPPRESS] False positive */
1521 0 : ip = lgfs2_build_quota_change(per_node, j);
1522 0 : if (ip == NULL) {
1523 0 : log_err(_("Error building '%s': %s\n"), "quota_change",
1524 : strerror(errno));
1525 : /* coverity[deref_arg:SUPPRESS] */
1526 0 : lgfs2_inode_put(&per_node);
1527 0 : return 1;
1528 : }
1529 0 : lgfs2_inode_put(&ip);
1530 : }
1531 0 : lgfs2_inode_put(&per_node);
1532 0 : return 0;
1533 : }
1534 :
1535 0 : static int build_inum(struct lgfs2_sbd *sdp)
1536 : {
1537 0 : struct lgfs2_inode *ip = lgfs2_build_inum(sdp);
1538 0 : if (ip == NULL)
1539 0 : return -1;
1540 0 : lgfs2_inode_put(&ip);
1541 0 : return 0;
1542 : }
1543 :
1544 0 : static int build_statfs(struct lgfs2_sbd *sdp)
1545 : {
1546 0 : struct lgfs2_inode *ip = lgfs2_build_statfs(sdp);
1547 0 : if (ip == NULL)
1548 0 : return -1;
1549 0 : lgfs2_inode_put(&ip);
1550 0 : return 0;
1551 : }
1552 :
1553 0 : static int build_rindex(struct lgfs2_sbd *sdp)
1554 : {
1555 0 : struct lgfs2_inode *ip = lgfs2_build_rindex(sdp);
1556 0 : if (ip == NULL)
1557 0 : return -1;
1558 0 : lgfs2_inode_put(&ip);
1559 0 : return 0;
1560 : }
1561 :
1562 0 : static int build_quota(struct lgfs2_sbd *sdp)
1563 : {
1564 0 : struct lgfs2_inode *ip = lgfs2_build_quota(sdp);
1565 0 : if (ip == NULL)
1566 0 : return -1;
1567 0 : lgfs2_inode_put(&ip);
1568 0 : return 0;
1569 : }
1570 :
1571 56 : static int check_system_inodes(struct fsck_cx *cx)
1572 : {
1573 56 : struct lgfs2_sbd *sdp = cx->sdp;
1574 : int journal_count;
1575 :
1576 : /* Mark the master system dinode as a "dinode" in the block map.
1577 : All other system dinodes in master will be taken care of by function
1578 : resuscitate_metalist. But master won't since it has no parent.*/
1579 56 : fsck_blockmap_set(cx, sdp->master_dir, sdp->master_dir->i_num.in_addr,
1580 : "master", GFS2_BLKST_DINODE);
1581 56 : if (check_system_inode(cx, &sdp->master_dir, "master",
1582 : lgfs2_build_master, 1, NULL, 1)) {
1583 0 : stack;
1584 0 : return -1;
1585 : }
1586 : /* Mark the root dinode as a "dinode" in the block map as we did
1587 : for master, since it has no parent. */
1588 56 : fsck_blockmap_set(cx, sdp->md.rooti, sdp->md.rooti->i_num.in_addr,
1589 : "root", GFS2_BLKST_DINODE);
1590 56 : if (check_system_inode(cx, &sdp->md.rooti, "root", lgfs2_build_root, 1,
1591 : NULL, 0)) {
1592 0 : stack;
1593 0 : return -1;
1594 : }
1595 56 : if (check_system_inode(cx, &sdp->md.inum, "inum", build_inum, 0,
1596 : sdp->master_dir, 1)) {
1597 0 : stack;
1598 0 : return -1;
1599 : }
1600 56 : if (check_system_inode(cx, &sdp->md.statfs, "statfs", build_statfs, 0,
1601 : sdp->master_dir, 1)) {
1602 0 : stack;
1603 0 : return -1;
1604 : }
1605 56 : if (check_system_inode(cx, &sdp->md.jiinode, "jindex", build_jindex,
1606 : 1, sdp->master_dir, 1)) {
1607 0 : stack;
1608 0 : return -1;
1609 : }
1610 56 : if (check_system_inode(cx, &sdp->md.riinode, "rindex", build_rindex,
1611 : 0, sdp->master_dir, 1)) {
1612 0 : stack;
1613 0 : return -1;
1614 : }
1615 56 : if (check_system_inode(cx, &sdp->md.qinode, "quota", build_quota,
1616 : 0, sdp->master_dir, 1)) {
1617 0 : stack;
1618 0 : return -1;
1619 : }
1620 56 : if (check_system_inode(cx, &sdp->md.pinode, "per_node",
1621 : build_per_node, 1, sdp->master_dir, 1)) {
1622 0 : stack;
1623 0 : return -1;
1624 : }
1625 : /* We have to play a trick on lgfs2_build_journal: We swap md.journals
1626 : in order to keep a count of which journal we need to build. */
1627 56 : journal_count = sdp->md.journals;
1628 119 : for (sdp->md.journals = 0; sdp->md.journals < journal_count;
1629 63 : sdp->md.journals++) {
1630 : char jname[16];
1631 :
1632 63 : sprintf(jname, "journal%d", sdp->md.journals);
1633 63 : if (check_system_inode(cx, &sdp->md.journal[sdp->md.journals],
1634 : jname, build_a_journal, 0,
1635 : sdp->md.jiinode, 1)) {
1636 0 : stack;
1637 0 : return -1;
1638 : }
1639 : }
1640 :
1641 56 : return 0;
1642 : }
1643 :
1644 177 : static int pass1_process_bitmap(struct fsck_cx *cx, struct lgfs2_rgrp_tree *rgd, uint64_t *ibuf, unsigned n)
1645 : {
1646 : struct lgfs2_buffer_head *bh;
1647 177 : struct lgfs2_sbd *sdp = cx->sdp;
1648 : unsigned i;
1649 : uint64_t block;
1650 : struct lgfs2_inode *ip;
1651 : int q;
1652 : /* Readahead numbers arrived at by experiment */
1653 177 : unsigned rawin = 50;
1654 177 : unsigned ralen = 100 * sdp->sd_bsize;
1655 177 : unsigned r = 0;
1656 :
1657 878 : for (i = 0; i < n; i++) {
1658 : int is_inode;
1659 :
1660 701 : block = ibuf[i];
1661 :
1662 701 : if (r++ == rawin) {
1663 0 : (void)posix_fadvise(sdp->device_fd, block * sdp->sd_bsize, ralen, POSIX_FADV_WILLNEED);
1664 0 : r = 0;
1665 : }
1666 :
1667 701 : display_progress(block);
1668 :
1669 701 : if (fsck_abort)
1670 0 : return FSCK_OK;
1671 :
1672 701 : if (skip_this_pass) {
1673 0 : printf( _("Skipping pass 1 is not a good idea.\n"));
1674 0 : skip_this_pass = 0;
1675 0 : fflush(stdout);
1676 : }
1677 701 : if (fsck_system_inode(sdp, block)) {
1678 511 : log_debug(_("Already processed system inode %"PRIu64" (0x%"PRIx64")\n"),
1679 : block, block);
1680 511 : continue;
1681 : }
1682 :
1683 190 : bh = lgfs2_bread(sdp, block);
1684 :
1685 190 : is_inode = 0;
1686 190 : if (lgfs2_check_meta(bh->b_data, GFS2_METATYPE_DI) == 0)
1687 189 : is_inode = 1;
1688 :
1689 190 : q = block_type(bl, block);
1690 190 : if (q != GFS2_BLKST_FREE) {
1691 0 : log_err(_("Found a duplicate inode block at %"PRIu64" (0x%"PRIx64") "
1692 : "previously marked as a %s\n"),
1693 : block, block, block_type_string(q));
1694 0 : ip = fsck_inode_get(sdp, rgd, bh);
1695 0 : if (is_inode && ip->i_num.in_addr == block)
1696 0 : add_duplicate_ref(cx, ip, block, REF_IS_INODE, 0,
1697 : INODE_VALID);
1698 : else
1699 0 : log_info(_("dinum.no_addr is wrong, so I "
1700 : "assume the bitmap is just "
1701 : "wrong.\n"));
1702 0 : fsck_inode_put(&ip);
1703 0 : lgfs2_brelse(bh);
1704 0 : continue;
1705 : }
1706 :
1707 190 : if (!is_inode) {
1708 1 : log_err(_("Found invalid inode at block %"PRIu64" (0x%"PRIx64")\n"),
1709 : block, block);
1710 1 : check_n_fix_bitmap(cx, rgd, block, 0, GFS2_BLKST_FREE);
1711 189 : } else if (handle_di(cx, rgd, bh) < 0) {
1712 0 : stack;
1713 0 : lgfs2_brelse(bh);
1714 0 : return FSCK_ERROR;
1715 : }
1716 : /* Ignore everything else - they should be hit by the
1717 : handle_di step. Don't check NONE either, because
1718 : check_meta passes everything if GFS2_METATYPE_NONE
1719 : is specified. Hopefully, other metadata types such
1720 : as indirect blocks will be handled when the inode
1721 : itself is processed, and if it's not, it should be
1722 : caught in pass5. */
1723 190 : lgfs2_brelse(bh);
1724 : }
1725 :
1726 177 : return 0;
1727 : }
1728 :
1729 4359 : static int pass1_process_rgrp(struct fsck_cx *cx, struct lgfs2_rgrp_tree *rgd)
1730 : {
1731 : unsigned k, n;
1732 4359 : uint64_t *ibuf = malloc(cx->sdp->sd_bsize * GFS2_NBBY * sizeof(uint64_t));
1733 4359 : int ret = 0;
1734 :
1735 4359 : if (ibuf == NULL)
1736 0 : return FSCK_ERROR;
1737 :
1738 136822 : for (k = 0; k < rgd->rt_length; k++) {
1739 132463 : n = lgfs2_bm_scan(rgd, k, ibuf, GFS2_BLKST_DINODE);
1740 :
1741 132463 : if (n) {
1742 177 : ret = pass1_process_bitmap(cx, rgd, ibuf, n);
1743 177 : if (ret)
1744 0 : goto out;
1745 : }
1746 :
1747 132463 : if (fsck_abort)
1748 0 : goto out;
1749 : }
1750 :
1751 4359 : out:
1752 4359 : free(ibuf);
1753 4359 : return ret;
1754 : }
1755 :
1756 56 : static int blockmap_create(struct bmap *bmap, uint64_t size)
1757 : {
1758 56 : bmap->size = size;
1759 :
1760 : /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs
1761 : * must be 1-based */
1762 56 : bmap->mapsize = BLOCKMAP_SIZE2(size) + 1;
1763 :
1764 56 : if (!(bmap->map = calloc(bmap->mapsize, sizeof(char))))
1765 0 : return -ENOMEM;
1766 56 : return 0;
1767 : }
1768 :
1769 :
1770 112 : static int link1_create(struct bmap *bmap, uint64_t size)
1771 : {
1772 112 : bmap->size = size;
1773 :
1774 : /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs
1775 : * must be 1-based */
1776 112 : bmap->mapsize = BLOCKMAP_SIZE1(size) + 1;
1777 :
1778 112 : if (!(bmap->map = calloc(bmap->mapsize, sizeof(char))))
1779 0 : return -ENOMEM;
1780 112 : return 0;
1781 : }
1782 :
1783 56 : static struct bmap *bmap_create(struct lgfs2_sbd *sdp, uint64_t size,
1784 : uint64_t *addl_mem_needed)
1785 : {
1786 : struct bmap *il;
1787 :
1788 56 : *addl_mem_needed = 0L;
1789 56 : il = calloc(1, sizeof(*il));
1790 56 : if (!il)
1791 0 : return NULL;
1792 :
1793 56 : if (blockmap_create(il, size)) {
1794 0 : *addl_mem_needed = il->mapsize;
1795 0 : free(il);
1796 0 : il = NULL;
1797 : }
1798 56 : return il;
1799 : }
1800 :
1801 56 : static void blockmap_destroy(struct bmap *bmap)
1802 : {
1803 56 : if (bmap->map)
1804 56 : free(bmap->map);
1805 56 : bmap->size = 0;
1806 56 : bmap->mapsize = 0;
1807 56 : }
1808 :
1809 56 : static void *bmap_destroy(struct lgfs2_sbd *sdp, struct bmap *il)
1810 : {
1811 56 : if (il) {
1812 56 : blockmap_destroy(il);
1813 56 : free(il);
1814 56 : il = NULL;
1815 : }
1816 56 : return il;
1817 : }
1818 :
1819 0 : static void enomem(uint64_t addl_mem_needed)
1820 : {
1821 0 : log_crit( _("This system doesn't have enough memory and swap space to fsck this file system.\n"));
1822 0 : log_crit( _("Additional memory needed is approximately: %"PRIu64"MB\n"),
1823 : (uint64_t)(addl_mem_needed / 1048576ULL));
1824 0 : log_crit( _("Please increase your swap space by that amount and run fsck.gfs2 again.\n"));
1825 0 : }
1826 :
1827 : /**
1828 : * pass1 - walk through inodes and check inode state
1829 : *
1830 : * this walk can be done using root inode and depth first search,
1831 : * watching for repeat inode numbers
1832 : *
1833 : * format & type
1834 : * link count
1835 : * duplicate blocks
1836 : * bad blocks
1837 : * inodes size
1838 : * dir info
1839 : */
1840 56 : int pass1(struct fsck_cx *cx)
1841 : {
1842 56 : struct lgfs2_sbd *sdp = cx->sdp;
1843 56 : struct osi_node *n, *next = NULL;
1844 : struct lgfs2_rgrp_tree *rgd;
1845 : uint64_t i;
1846 56 : uint64_t rg_count = 0;
1847 : struct timeval timer;
1848 56 : int ret = FSCK_OK;
1849 : uint64_t addl_mem_needed;
1850 :
1851 56 : bl = bmap_create(sdp, last_fs_block+1, &addl_mem_needed);
1852 56 : if (!bl) {
1853 0 : enomem(addl_mem_needed);
1854 0 : return FSCK_ERROR;
1855 : }
1856 56 : addl_mem_needed = link1_create(&nlink1map, last_fs_block+1);
1857 56 : if (addl_mem_needed) {
1858 0 : enomem(addl_mem_needed);
1859 0 : bmap_destroy(sdp, bl);
1860 0 : return FSCK_ERROR;
1861 : }
1862 56 : addl_mem_needed = link1_create(&clink1map, last_fs_block+1);
1863 56 : if (addl_mem_needed) {
1864 0 : enomem(addl_mem_needed);
1865 0 : link1_destroy(&nlink1map);
1866 0 : bmap_destroy(sdp, bl);
1867 0 : return FSCK_ERROR;
1868 : }
1869 :
1870 : /* FIXME: In the gfs fsck, we had to mark things like the
1871 : * journals and indices and such as 'other_meta' - in gfs2,
1872 : * the journals are files and are found in the normal file
1873 : * sweep - is there any metadata we need to mark here before
1874 : * the sweeps start that we won't find otherwise? */
1875 :
1876 : /* Make sure the system inodes are okay & represented in the bitmap. */
1877 56 : check_system_inodes(cx);
1878 :
1879 : /* So, do we do a depth first search starting at the root
1880 : * inode, or use the rg bitmaps, or just read every fs block
1881 : * to find the inodes? If we use the depth first search, why
1882 : * have pass3 at all - if we use the rg bitmaps, pass5 is at
1883 : * least partially invalidated - if we read every fs block,
1884 : * things will probably be intolerably slow. The current fsck
1885 : * uses the rg bitmaps, so maybe that's the best way to start
1886 : * things - we can change the method later if necessary.
1887 : */
1888 4415 : for (n = osi_first(&sdp->rgtree); n; n = next, rg_count++) {
1889 4359 : if (fsck_abort) {
1890 0 : ret = FSCK_CANCELED;
1891 0 : goto out;
1892 : }
1893 4359 : next = osi_next(n);
1894 4359 : log_debug("Checking metadata in resource group #%"PRIu64"\n", rg_count);
1895 4359 : rgd = (struct lgfs2_rgrp_tree *)n;
1896 136822 : for (i = 0; i < rgd->rt_length; i++) {
1897 132463 : log_debug("rgrp block %"PRIu64" (0x%"PRIx64") is now marked as 'rgrp data'\n",
1898 : rgd->rt_addr + i, rgd->rt_addr + i);
1899 132463 : if (blockmap_set(bl, rgd->rt_addr + i, GFS2_BLKST_USED)) {
1900 0 : stack;
1901 0 : ret = FSCK_ERROR;
1902 0 : goto out;
1903 : }
1904 : /* rgrps and bitmaps don't have bits to represent
1905 : their blocks, so don't do this:
1906 : check_n_fix_bitmap(sdp, rgd, rgd->ri.ri_num.in_addr + i, 0,
1907 : gfs2_meta_rgrp);*/
1908 : }
1909 :
1910 4359 : ret = pass1_process_rgrp(cx, rgd);
1911 4359 : if (ret)
1912 0 : goto out;
1913 : }
1914 56 : log_notice(_("Reconciling bitmaps.\n"));
1915 56 : gettimeofday(&timer, NULL);
1916 56 : pass5(cx, bl);
1917 56 : print_pass_duration("reconcile_bitmaps", &timer);
1918 56 : out:
1919 56 : if (bl)
1920 56 : bmap_destroy(sdp, bl);
1921 56 : return ret;
1922 : }
1923 :
1924 : static struct metawalk_fxns pass1_fxns = {
1925 : .private = NULL,
1926 : .check_leaf = p1_check_leaf,
1927 : .check_metalist = p1_check_metalist,
1928 : .check_data = p1_check_data,
1929 : .check_eattr_indir = p1_check_eattr_indir,
1930 : .check_eattr_leaf = p1_check_eattr_leaf,
1931 : .check_dentry = NULL,
1932 : .check_eattr_entry = p1_check_eattr_entry,
1933 : .check_eattr_extentry = p1_check_extended_leaf_eattr,
1934 : .big_file_msg = big_file_comfort,
1935 : .repair_leaf = p1_repair_leaf,
1936 : .undo_check_meta = p1_undo_check_metalist,
1937 : .undo_check_data = p1_undo_check_data,
1938 : .delete_block = p1_delete_block,
1939 : };
|