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