Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <inttypes.h>
4 : #include <stdlib.h>
5 : #include <string.h>
6 : #include <unistd.h>
7 : #include <libintl.h>
8 : #include <sys/stat.h>
9 : #define _(String) gettext(String)
10 :
11 : #include <logging.h>
12 : #include "libgfs2.h"
13 : #include "link.h"
14 : #include "fsck.h"
15 : #include "osi_list.h"
16 : #include "util.h"
17 : #include "metawalk.h"
18 : #include "inode_hash.h"
19 : #include "afterpass1_common.h"
20 :
21 : struct fxn_info {
22 : uint64_t block;
23 : int found;
24 : int ea_only; /* The only dups were found in EAs */
25 : };
26 :
27 : struct dup_handler {
28 : struct duptree *dt;
29 : int ref_inode_count;
30 : int ref_count;
31 : };
32 :
33 : struct clone_target {
34 : uint64_t dup_block;
35 : int first;
36 : };
37 :
38 : struct meta_blk_ref {
39 : uint64_t block; /* block to locate */
40 : uint64_t metablock; /* returned metadata block addr containing ref */
41 : int off; /* offset to the reference within the buffer */
42 : };
43 :
44 : static int clone_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
45 : uint64_t block, void *private,
46 : struct lgfs2_buffer_head *bh, __be64 *ptr);
47 :
48 0 : static void log_inode_reference(struct duptree *dt, osi_list_t *tmp, int inval)
49 : {
50 : char reftypestring[32];
51 : struct inode_with_dups *id;
52 :
53 0 : id = osi_list_entry(tmp, struct inode_with_dups, list);
54 0 : if (id->dup_count == 1)
55 0 : sprintf(reftypestring, "as %s", reftypes[get_ref_type(id)]);
56 : else
57 0 : sprintf(reftypestring, "%d/%d/%d/%d",
58 : id->reftypecount[REF_IS_INODE],
59 : id->reftypecount[REF_AS_DATA],
60 : id->reftypecount[REF_AS_META],
61 : id->reftypecount[REF_AS_EA]);
62 0 : if (inval)
63 0 : log_warn( _("Invalid "));
64 0 : log_warn(_("Inode %s (%"PRIu64"/0x%"PRIx64") has %d reference(s) to block %"PRIu64" (0x%"PRIx64") (%s)\n"),
65 : id->name, id->block_no, id->block_no, id->dup_count, dt->block, dt->block,
66 : reftypestring);
67 0 : }
68 :
69 0 : static int findref_meta(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
70 : int *is_valid, int *was_duplicate, void *private)
71 : {
72 0 : *is_valid = 1;
73 0 : *was_duplicate = 0;
74 0 : return META_IS_GOOD;
75 : }
76 :
77 0 : static int findref_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
78 : uint64_t block, void *private,
79 : struct lgfs2_buffer_head *bh, __be64 *ptr)
80 : {
81 0 : struct meta_blk_ref *mbr = (struct meta_blk_ref *)private;
82 :
83 0 : if (block == mbr->block) {
84 0 : mbr->metablock = bh->b_blocknr;
85 0 : mbr->off = (ptr - (__be64 *)bh->b_data);
86 0 : log_debug("Duplicate data reference located on metadata block 0x%"PRIx64", offset 0x%x\n",
87 : mbr->metablock, mbr->off);
88 : }
89 0 : return META_IS_GOOD;
90 : }
91 :
92 0 : static void clone_data_block(struct fsck_cx *cx, struct duptree *dt,
93 : struct inode_with_dups *id)
94 : {
95 0 : struct meta_blk_ref metaref = { .block = dt->block, };
96 0 : struct metawalk_fxns find1ref_fxns = {
97 : .private = &metaref,
98 : .check_metalist = findref_meta,
99 : .check_data = findref_data,
100 : };
101 0 : struct clone_target clone = {.dup_block = dt->block,};
102 : struct lgfs2_inode *ip;
103 : struct lgfs2_buffer_head *bh;
104 : __be64 *ptr;
105 :
106 0 : if (!(query(cx, _("Okay to clone data block %"PRIu64" (0x%"PRIx64") for inode %"PRIu64" (0x%"PRIx64")? (y/n) "),
107 : dt->block, dt->block, id->block_no, id->block_no))) {
108 0 : log_warn(_("The duplicate reference was not cloned.\n"));
109 0 : return;
110 : }
111 0 : ip = fsck_load_inode(cx->sdp, id->block_no);
112 0 : check_metatree(cx, ip, &find1ref_fxns);
113 0 : if (metaref.metablock == 0) {
114 0 : log_err(_("Unable to clone data block.\n"));
115 : } else {
116 0 : if (metaref.metablock != id->block_no)
117 0 : bh = lgfs2_bread(cx->sdp, metaref.metablock);
118 : else
119 0 : bh = ip->i_bh;
120 0 : ptr = (__be64 *)bh->b_data + metaref.off;
121 0 : clone_data(cx, ip, 0, dt->block, &clone, bh, ptr);
122 0 : if (metaref.metablock != id->block_no)
123 0 : lgfs2_brelse(bh);
124 : else
125 0 : lgfs2_bmodified(ip->i_bh);
126 : }
127 0 : fsck_inode_put(&ip); /* out, lgfs2_brelse, free */
128 : }
129 :
130 : /* revise_dup_handler - get current information about a duplicate reference
131 : *
132 : * Function resolve_dup_references can delete dinodes that reference blocks
133 : * which may have duplicate references. Therefore, the duplicate tree is
134 : * constantly being changed. This function revises the duplicate handler so
135 : * that it accurately matches what's in the duplicate tree regarding this block
136 : */
137 0 : static void revise_dup_handler(struct fsck_cx *cx, uint64_t dup_blk, struct dup_handler *dh)
138 : {
139 : osi_list_t *tmp;
140 : struct duptree *dt;
141 : struct inode_with_dups *id;
142 :
143 0 : dh->ref_inode_count = 0;
144 0 : dh->ref_count = 0;
145 0 : dh->dt = NULL;
146 :
147 0 : dt = dupfind(cx, dup_blk);
148 0 : if (!dt)
149 0 : return;
150 :
151 0 : dh->dt = dt;
152 : /* Count the duplicate references, both valid and invalid */
153 0 : osi_list_foreach(tmp, &dt->ref_invinode_list) {
154 0 : id = osi_list_entry(tmp, struct inode_with_dups, list);
155 0 : dh->ref_inode_count++;
156 0 : dh->ref_count += id->dup_count;
157 : }
158 0 : osi_list_foreach(tmp, &dt->ref_inode_list) {
159 0 : id = osi_list_entry(tmp, struct inode_with_dups, list);
160 0 : dh->ref_inode_count++;
161 0 : dh->ref_count += id->dup_count;
162 : }
163 : }
164 :
165 : /*
166 : * resolve_dup_references - resolve all but the last dinode that has a
167 : * duplicate reference to a given block.
168 : *
169 : * @sdp - pointer to the superblock structure
170 : * @dt - pointer to the duplicate reference rbtree to use
171 : * @ref_list - list of duplicate references to be resolved (invalid or valid)
172 : * @dh - duplicate handler
173 : * inval - The references on this ref_list are invalid. We prefer to delete
174 : * these first before resorting to deleting valid dinodes.
175 : * acceptable_ref - Delete dinodes that reference the given block as anything
176 : * _but_ this type. Try to save references as this type.
177 : */
178 0 : static void resolve_dup_references(struct fsck_cx *cx, struct duptree *dt,
179 : osi_list_t *ref_list,
180 : struct dup_handler *dh,
181 : int inval, int acceptable_ref)
182 : {
183 : struct lgfs2_inode *ip;
184 : struct inode_with_dups *id;
185 : osi_list_t *tmp, *x;
186 0 : struct metawalk_fxns pass1b_fxns_delete = {
187 : .private = NULL,
188 : .check_metalist = delete_metadata,
189 : .check_data = delete_data,
190 : .check_leaf = delete_leaf,
191 : .check_eattr_indir = delete_eattr_indir,
192 : .check_eattr_leaf = delete_eattr_leaf,
193 : .check_eattr_entry = delete_eattr_entry,
194 : .check_eattr_extentry = delete_eattr_extentry,
195 : };
196 : enum dup_ref_type this_ref;
197 : struct inode_info *ii;
198 : struct dir_info *di;
199 0 : int found_good_ref = 0;
200 : int q;
201 :
202 0 : osi_list_foreach_safe(tmp, ref_list, x) {
203 0 : if (skip_this_pass || fsck_abort)
204 0 : return;
205 :
206 0 : id = osi_list_entry(tmp, struct inode_with_dups, list);
207 0 : dh->dt = dt;
208 :
209 0 : if (dh->ref_inode_count == 1) /* down to the last reference */
210 0 : return;
211 :
212 0 : this_ref = get_ref_type(id);
213 0 : q = bitmap_type(cx->sdp, id->block_no);
214 0 : if (inval)
215 0 : log_warn( _("Invalid "));
216 : /* FIXME: If we already found an acceptable reference to this
217 : * block, we should really duplicate the block and fix all
218 : * references to it in this inode. Unfortunately, we would
219 : * have to traverse the entire metadata tree to do that. */
220 0 : if (acceptable_ref != REF_TYPES && /* If we're nuking all but
221 : an acceptable reference
222 : type and */
223 0 : this_ref == acceptable_ref) { /* this ref is acceptable */
224 : /* If this is an invalid inode, but not on the invalid
225 : list, it's better to delete it. */
226 0 : if (q == GFS2_BLKST_DINODE) {
227 0 : found_good_ref = 1;
228 0 : log_warn(_("Inode %s (%"PRIu64"/0x%"PRIx64")'s "
229 : "reference to block %"PRIu64" (0x%"PRIx64") "
230 : "as '%s' is acceptable.\n"),
231 : id->name,
232 : id->block_no, id->block_no, dt->block, dt->block,
233 : reftypes[this_ref]);
234 0 : continue; /* don't delete the dinode */
235 : }
236 : }
237 : /* If this reference is from a system inode, for example, if
238 : it's data or metadata inside a journal, the reference
239 : should take priority over user dinodes that reference the
240 : block. */
241 0 : if (!found_good_ref && fsck_system_inode(cx->sdp, id->block_no)) {
242 0 : found_good_ref = 1;
243 0 : continue; /* don't delete the dinode */
244 : }
245 0 : log_warn(_("Inode %s (%"PRIu64"/0x%"PRIx64") references block "
246 : "%"PRIu64" (0x%"PRIx64") as '%s', but the block is "
247 : "really %s.\n"),
248 : id->name, id->block_no, id->block_no, dt->block, dt->block,
249 : reftypes[this_ref], reftypes[acceptable_ref]);
250 0 : if (this_ref == REF_AS_EA) {
251 0 : if (!(query(cx, _("Okay to remove extended attributes "
252 : "from %s inode %"PRIu64" (0x%"PRIx64")? (y/n) "),
253 : (inval ? _("invalidated") : ""),
254 : id->block_no, id->block_no))) {
255 0 : log_warn( _("The bad EA reference was not "
256 : "cleared."));
257 : /* delete the list entry so we don't leak
258 : memory but leave the reference count. If we
259 : decrement the ref count, we could get down
260 : to 1 and the dinode would be changed
261 : without a 'Yes' answer. */
262 : /* (dh->ref_inode_count)--;*/
263 0 : dup_listent_delete(dt, id);
264 0 : continue;
265 : }
266 0 : } else if (acceptable_ref == REF_TYPES &&
267 : this_ref == REF_AS_DATA) {
268 0 : clone_data_block(cx, dt, id);
269 0 : dup_listent_delete(dt, id);
270 0 : revise_dup_handler(cx, dt->block, dh);
271 0 : continue;
272 0 : } else if (!(query(cx, _("Okay to delete %s inode %"PRIu64" (0x%"PRIx64")? (y/n) "),
273 : (inval ? _("invalidated") : ""),
274 : id->block_no, id->block_no))) {
275 0 : log_warn( _("The bad inode was not cleared."));
276 : /* delete the list entry so we don't leak memory but
277 : leave the reference count. If we decrement the
278 : ref count, we could get down to 1 and the dinode
279 : would be changed without a 'Yes' answer. */
280 : /* (dh->ref_inode_count)--;*/
281 0 : dup_listent_delete(dt, id);
282 0 : continue;
283 : }
284 0 : if (q == GFS2_BLKST_FREE)
285 0 : log_warn(_("Inode %"PRIu64" (0x%"PRIx64") was previously deleted.\n"),
286 : id->block_no, id->block_no);
287 0 : else if (this_ref == REF_AS_EA)
288 0 : log_warn(_("Pass1b is removing extended attributes from inode %"PRIu64" (0x%"PRIx64").\n"),
289 : id->block_no, id->block_no);
290 : else
291 0 : log_warn(_("Pass1b is deleting inode %"PRIu64" (0x%"PRIx64").\n"),
292 : id->block_no, id->block_no);
293 :
294 0 : ip = fsck_load_inode(cx->sdp, id->block_no);
295 : /* If we've already deleted this dinode, don't try to delete
296 : it again. That could free blocks that used to be duplicate
297 : references that are now resolved (and gone). */
298 0 : if (q != GFS2_BLKST_FREE) {
299 : /* If the inode's eattr pointer is to the duplicate
300 : ref block, we don't want to call check_inode_eattr
301 : because that would traverse the structure, and it's
302 : not ours to do anymore; it rightly belongs to a
303 : different dinode. On the other hand, if the dup
304 : block is buried deep within the eattr structure
305 : of this dinode, we need to traverse the structure
306 : because it IS ours, and we need to remove all the
307 : eattr leaf blocks: they do belong to us (except for
308 : the duplicate referenced one, which is handled). */
309 0 : if (ip->i_eattr == dt->block) {
310 0 : ip->i_eattr = 0;
311 0 : if (ip->i_blocks > 0)
312 0 : ip->i_blocks--;
313 0 : ip->i_flags &= ~GFS2_DIF_EA_INDIRECT;
314 0 : lgfs2_bmodified(ip->i_bh);
315 0 : dup_listent_delete(dt, id);
316 0 : (dh->ref_inode_count)--;
317 : } else {
318 : /* Clear the EAs for the inode first */
319 0 : check_inode_eattr(cx, ip, &pass1b_fxns_delete);
320 0 : (dh->ref_inode_count)--;
321 : }
322 : /* If the reference was as metadata or data, we've got
323 : a corrupt dinode that will be deleted. */
324 0 : if ((this_ref != REF_AS_EA) &&
325 0 : (inval || id->reftypecount[REF_AS_DATA] ||
326 0 : id->reftypecount[REF_AS_META])) {
327 : /* Fix the bitmap first, while the inodetree
328 : and dirtree entries exist. That way, the
329 : bitmap_set will do proper accounting for
330 : the rgrp dinode count. */
331 0 : fsck_bitmap_set(cx, ip, ip->i_num.in_addr,
332 : _("duplicate referencing bad"),
333 : GFS2_BLKST_FREE);
334 : /* Remove the inode from the inode tree */
335 0 : ii = inodetree_find(cx, ip->i_num.in_addr);
336 0 : if (ii)
337 0 : inodetree_delete(cx, ii);
338 0 : di = dirtree_find(cx, ip->i_num.in_addr);
339 0 : if (di)
340 0 : dirtree_delete(cx, di);
341 0 : link1_set(&nlink1map, ip->i_num.in_addr,
342 : 0);
343 : /* We delete the dup_handler inode count and
344 : duplicate id BEFORE clearing the metadata,
345 : because if this is the last reference to
346 : this metadata block, we need to traverse the
347 : tree and free the data blocks it references.
348 : However, we don't want to delete other
349 : duplicates that may be used by other
350 : dinodes. */
351 0 : (dh->ref_inode_count)--;
352 : /* FIXME: other option should be to duplicate
353 : the block for each duplicate and point the
354 : metadata at the cloned blocks */
355 0 : check_metatree(cx, ip, &pass1b_fxns_delete);
356 : }
357 : }
358 : /* Now we've got to go through and delete any other duplicate
359 : references from this dinode we're deleting. If we don't,
360 : pass1b will discover the other duplicate record, try to
361 : delete this dinode a second time, and this time its earlier
362 : duplicate references won't be seen as duplicates anymore
363 : (because they were eliminated earlier in pass1b). And so
364 : the blocks will be mistakenly freed, when, in fact, they're
365 : still being referenced by a valid dinode. */
366 0 : if (this_ref != REF_AS_EA)
367 0 : delete_all_dups(cx, ip);
368 0 : fsck_inode_put(&ip); /* out, lgfs2_brelse, free */
369 : }
370 0 : return;
371 : }
372 :
373 0 : static int clone_check_meta(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
374 : int *is_valid, int *was_duplicate, void *private)
375 : {
376 0 : struct lgfs2_inode *ip = iptr.ipt_ip;
377 0 : uint64_t block = iptr_block(iptr);
378 :
379 0 : *was_duplicate = 0;
380 0 : *is_valid = 1;
381 0 : *bh = lgfs2_bread(ip->i_sbd, block);
382 0 : return 0;
383 : }
384 :
385 : /* clone_data - clone a duplicate reference
386 : *
387 : * This function remembers the first reference to the specified block, and
388 : * clones all subsequent references to it (with permission).
389 : */
390 0 : static int clone_data(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
391 : uint64_t block, void *private,
392 : struct lgfs2_buffer_head *bh, __be64 *ptr)
393 : {
394 0 : struct clone_target *clonet = (struct clone_target *)private;
395 : struct lgfs2_buffer_head *clone_bh;
396 : uint64_t cloneblock;
397 : int error;
398 :
399 0 : if (block != clonet->dup_block)
400 0 : return 0;
401 :
402 0 : if (clonet->first) {
403 0 : log_debug(_("Inode %"PRIu64" (0x%"PRIx64")'s first reference to "
404 : "block %"PRIu64" (0x%"PRIx64") is targeted for cloning.\n"),
405 : ip->i_num.in_addr, ip->i_num.in_addr, block, block);
406 0 : clonet->first = 0;
407 0 : return 0;
408 : }
409 0 : log_err(_("Error: Inode %"PRIu64" (0x%"PRIx64")'s reference to block %"PRIu64
410 : " (0x%"PRIx64") should be replaced with a clone.\n"),
411 : ip->i_num.in_addr, ip->i_num.in_addr, block, block);
412 0 : if (query(cx, _("Okay to clone the duplicated reference? (y/n) "))) {
413 0 : error = lgfs2_meta_alloc(ip, &cloneblock);
414 0 : if (!error) {
415 0 : clone_bh = lgfs2_bread(ip->i_sbd, clonet->dup_block);
416 0 : if (clone_bh) {
417 0 : fsck_bitmap_set(cx, ip, cloneblock, _("data"),
418 : GFS2_BLKST_USED);
419 0 : clone_bh->b_blocknr = cloneblock;
420 0 : lgfs2_bmodified(clone_bh);
421 0 : lgfs2_brelse(clone_bh);
422 : /* Now fix the reference: */
423 0 : *ptr = cpu_to_be64(cloneblock);
424 0 : lgfs2_bmodified(bh);
425 0 : log_err(_("Duplicate reference to block %"PRIu64
426 : " (0x%"PRIx64") was cloned to block %"PRIu64
427 : " (0x%"PRIx64").\n"),
428 : block, block, cloneblock, cloneblock);
429 0 : return 0;
430 : }
431 : }
432 0 : log_err(_("Error: Unable to allocate a new data block.\n"));
433 0 : if (!query(cx, _("Zero the reference instead? (y/n)"))) {
434 0 : log_err(_("Duplicate reference to block %"PRIu64
435 : " (0x%"PRIx64") was not fixed.\n"),
436 : block, block);
437 0 : return 0;
438 : }
439 0 : *ptr = 0;
440 0 : lgfs2_bmodified(bh);
441 0 : log_err(_("Duplicate reference to block %"PRIu64" (0x%"PRIx64") was zeroed.\n"),
442 : block, block);
443 : } else {
444 0 : log_err(_("Duplicate reference to block %"PRIu64" (0x%"PRIx64") was not fixed.\n"),
445 : block, block);
446 : }
447 0 : return 0;
448 : }
449 :
450 : /* clone_dup_ref_in_inode - clone a duplicate reference within a single inode
451 : *
452 : * This function traverses the metadata tree of an inode, cloning all
453 : * but the first reference to a duplicate block reference.
454 : */
455 0 : static void clone_dup_ref_in_inode(struct fsck_cx *cx, struct lgfs2_inode *ip, struct duptree *dt)
456 : {
457 : int error;
458 0 : struct clone_target clonet = {.dup_block = dt->block, .first = 1};
459 0 : struct metawalk_fxns pass1b_fxns_clone = {
460 : .private = &clonet,
461 : .check_metalist = clone_check_meta,
462 : .check_data = clone_data,
463 : };
464 :
465 0 : log_err(_("There are multiple references to block %"PRIu64" (0x%"PRIx64") in "
466 : "inode %"PRIu64" (0x%"PRIx64")\n"),
467 : ip->i_num.in_addr, ip->i_num.in_addr, dt->block, dt->block);
468 0 : error = check_metatree(cx, ip, &pass1b_fxns_clone);
469 0 : if (error) {
470 0 : log_err(_("Error cloning duplicate reference(s) to block %"PRIu64
471 : " (0x%"PRIx64").\n"), dt->block, dt->block);
472 : }
473 0 : }
474 :
475 0 : static int set_ip_bitmap(struct fsck_cx *cx, struct lgfs2_inode *ip)
476 : {
477 0 : uint64_t block = ip->i_bh->b_blocknr;
478 : uint32_t mode;
479 : const char *ty;
480 :
481 0 : mode = ip->i_mode & S_IFMT;
482 :
483 0 : switch (mode) {
484 0 : case S_IFDIR:
485 0 : ty = "directory";
486 0 : break;
487 0 : case S_IFREG:
488 0 : ty = "file";
489 0 : break;
490 0 : case S_IFLNK:
491 0 : ty = "symlink";
492 0 : break;
493 0 : case S_IFBLK:
494 0 : ty = "block device";
495 0 : break;
496 0 : case S_IFCHR:
497 0 : ty = "character device";
498 0 : break;
499 0 : case S_IFIFO:
500 0 : ty = "fifo";
501 0 : break;
502 0 : case S_IFSOCK:
503 0 : ty = "socket";
504 0 : break;
505 0 : default:
506 0 : return -EINVAL;
507 : }
508 0 : fsck_bitmap_set(cx, ip, block, ty, GFS2_BLKST_DINODE);
509 0 : return 0;
510 : }
511 :
512 0 : static void resolve_last_reference(struct fsck_cx *cx, struct duptree *dt,
513 : enum dup_ref_type acceptable_ref)
514 : {
515 0 : struct lgfs2_sbd *sdp = cx->sdp;
516 : struct lgfs2_inode *ip;
517 : struct inode_with_dups *id;
518 : osi_list_t *tmp;
519 : int q;
520 :
521 0 : log_notice(_("Block %"PRIu64" (0x%"PRIx64") has only one remaining valid inode referencing it.\n"),
522 : dt->block, dt->block);
523 : /* If we're down to a single reference (and not all references
524 : deleted, which may be the case of an inode that has only
525 : itself and a reference), we need to reset the block type
526 : from invalid to data or metadata. Start at the first one
527 : in the list, not the structure's place holder. */
528 0 : tmp = dt->ref_inode_list.next;
529 0 : id = osi_list_entry(tmp, struct inode_with_dups, list);
530 0 : log_debug(_("----------------------------------------------\n"
531 : "Step 4. Set block type based on the remaining "
532 : "reference in inode %"PRIu64" (0x%"PRIx64").\n"),
533 : id->block_no, id->block_no);
534 0 : ip = fsck_load_inode(sdp, id->block_no);
535 :
536 0 : if (dt->dup_flags & DUPFLAG_REF1_IS_DUPL)
537 0 : clone_dup_ref_in_inode(cx, ip, dt);
538 :
539 0 : q = bitmap_type(sdp, id->block_no);
540 0 : if (q == GFS2_BLKST_FREE) {
541 0 : log_debug(_("The remaining reference inode %"PRIu64" (0x%"PRIx64") was "
542 : "already marked free.\n"),
543 : id->block_no, id->block_no);
544 0 : } else if (id->reftypecount[REF_IS_INODE]) {
545 0 : set_ip_bitmap(cx, ip);
546 0 : } else if (id->reftypecount[REF_AS_DATA]) {
547 0 : fsck_bitmap_set(cx, ip, dt->block, _("reference-repaired data"),
548 : GFS2_BLKST_USED);
549 0 : } else if (id->reftypecount[REF_AS_META]) {
550 0 : if (is_dir(ip))
551 0 : fsck_bitmap_set(cx, ip, dt->block,
552 : _("reference-repaired leaf"),
553 : GFS2_BLKST_USED);
554 : else
555 0 : fsck_bitmap_set(cx, ip, dt->block,
556 : _("reference-repaired indirect"),
557 : GFS2_BLKST_USED);
558 : } else {
559 0 : if (acceptable_ref == REF_AS_EA)
560 0 : fsck_bitmap_set(cx, ip, dt->block,
561 : _("reference-repaired extended "
562 : "attribute"),
563 : GFS2_BLKST_USED);
564 : else {
565 0 : log_err(_("Error: The remaining reference to block "
566 : " %"PRIu64" (0x%"PRIx64") is as extended attribute, "
567 : "in inode %"PRIu64" (0x%"PRIx64") but the block is "
568 : "not an extended attribute block.\n"),
569 : dt->block, dt->block, id->block_no, id->block_no);
570 0 : if (query(cx, _("Okay to remove the bad extended "
571 : "attribute from inode %"PRIu64" (0x%"PRIx64")? "
572 : "(y/n) "),
573 : id->block_no, id->block_no)) {
574 0 : ip->i_eattr = 0;
575 0 : ip->i_flags &= ~GFS2_DIF_EA_INDIRECT;
576 0 : ip->i_blocks--;
577 0 : lgfs2_bmodified(ip->i_bh);
578 0 : fsck_bitmap_set(cx, ip, dt->block,
579 : _("reference-repaired EA"),
580 : GFS2_BLKST_FREE);
581 0 : log_err(_("The bad extended attribute was "
582 : "removed.\n"));
583 : } else {
584 0 : log_err(_("The bad extended attribute was not "
585 : "removed.\n"));
586 : }
587 : }
588 : }
589 0 : fsck_inode_put(&ip); /* out, lgfs2_brelse, free */
590 0 : log_debug(_("Done with duplicate reference to block 0x%"PRIx64"\n"), dt->block);
591 0 : dup_delete(cx, dt);
592 0 : }
593 :
594 : /* handle_dup_blk - handle a duplicate block reference.
595 : *
596 : * This function should resolve and delete the duplicate block reference given,
597 : * iow dt.
598 : */
599 0 : static int handle_dup_blk(struct fsck_cx *cx, struct duptree *dt)
600 : {
601 : osi_list_t *tmp;
602 0 : struct dup_handler dh = {0};
603 : struct lgfs2_buffer_head *bh;
604 : __be32 cmagic, ctype;
605 : enum dup_ref_type acceptable_ref;
606 : uint64_t dup_blk;
607 :
608 0 : dup_blk = dt->block;
609 0 : revise_dup_handler(cx, dup_blk, &dh);
610 :
611 : /* Log the duplicate references */
612 0 : log_notice(_("Block %"PRIu64" (0x%"PRIx64") has %d inodes referencing it"
613 : " for a total of %d duplicate references:\n"),
614 : dt->block, dt->block, dh.ref_inode_count, dh.ref_count);
615 :
616 0 : osi_list_foreach(tmp, &dt->ref_invinode_list)
617 0 : log_inode_reference(dt, tmp, 1);
618 0 : osi_list_foreach(tmp, &dt->ref_inode_list)
619 0 : log_inode_reference(dt, tmp, 0);
620 :
621 : /* Figure out the block type to see if we can eliminate references
622 : to a different type. In other words, if the duplicate block looks
623 : like metadata, we can delete dinodes that reference it as data.
624 : If the block doesn't look like metadata, we can eliminate any
625 : references to it as metadata. Dinodes with such references are
626 : clearly corrupt and need to be deleted.
627 : And if we're left with a single reference, problem solved. */
628 0 : bh = lgfs2_bread(cx->sdp, dt->block);
629 0 : cmagic = ((struct gfs2_meta_header *)(bh->b_data))->mh_magic;
630 0 : ctype = ((struct gfs2_meta_header *)(bh->b_data))->mh_type;
631 0 : lgfs2_brelse(bh);
632 :
633 : /* If this is a dinode, any references to it (except in directory
634 : entries) are invalid and should be deleted. */
635 0 : if (be32_to_cpu(cmagic) == GFS2_MAGIC &&
636 0 : be32_to_cpu(ctype) == GFS2_METATYPE_DI)
637 0 : acceptable_ref = REF_IS_INODE;
638 0 : else if (be32_to_cpu(cmagic) == GFS2_MAGIC &&
639 0 : (be32_to_cpu(ctype) == GFS2_METATYPE_EA ||
640 0 : be32_to_cpu(ctype) == GFS2_METATYPE_ED))
641 0 : acceptable_ref = REF_AS_EA;
642 0 : else if (be32_to_cpu(cmagic) == GFS2_MAGIC &&
643 0 : be32_to_cpu(ctype) <= GFS2_METATYPE_QC)
644 0 : acceptable_ref = REF_AS_META;
645 : else
646 0 : acceptable_ref = REF_AS_DATA;
647 :
648 : /* A single reference to the block implies a possible situation where
649 : a data pointer points to a metadata block. In other words, the
650 : duplicate reference in the file system is (1) Metadata block X and
651 : (2) A dinode reference such as a data pointer pointing to block X.
652 : We can't really check for that in pass1 because user data might
653 : just _look_ like metadata by coincidence, and at the time we're
654 : checking, we might not have processed the referenced block.
655 : Here in pass1b we're sure. */
656 : /* Another possibility here is that there is a single reference
657 : because all the other metadata references were in inodes that got
658 : invalidated for other reasons, such as bad pointers. So we need to
659 : make sure at this point that any inode deletes reverse out any
660 : duplicate reference before we get to this point. */
661 :
662 : /* Step 1 - eliminate references from inodes that are not valid.
663 : * This may be because they were deleted due to corruption.
664 : * All block types are unacceptable, so we use REF_TYPES.
665 : */
666 0 : if (dh.ref_count > 1) {
667 0 : log_debug(_("----------------------------------------------\n"
668 : "Step 1: Eliminate references to block %"PRIu64" "
669 : "(0x%"PRIx64") that were previously marked "
670 : "invalid.\n"),
671 : dt->block, dt->block);
672 0 : resolve_dup_references(cx, dt, &dt->ref_invinode_list,
673 : &dh, 1, REF_TYPES);
674 0 : revise_dup_handler(cx, dup_blk, &dh);
675 : }
676 : /* Step 2 - eliminate reference from inodes that reference it as the
677 : * wrong type. For example, a data file referencing it as
678 : * a data block, but it's really a metadata block. Or a
679 : * directory inode referencing a data block as a leaf block.
680 : */
681 0 : if (dh.ref_count > 1) {
682 0 : log_debug(_("----------------------------------------------\n"
683 : "Step 2: Eliminate references to block %"PRIu64" "
684 : "(0x%"PRIx64") that need the wrong block type.\n"),
685 : dt->block, dt->block);
686 0 : resolve_dup_references(cx, dt, &dt->ref_inode_list, &dh, 0,
687 : acceptable_ref);
688 0 : revise_dup_handler(cx, dup_blk, &dh);
689 : }
690 : /* Step 3 - We have multiple dinodes referencing it as the correct
691 : * type. Just blast one of them.
692 : * All block types are fair game, so we use REF_TYPES.
693 : */
694 0 : if (dh.ref_count > 1) {
695 0 : log_debug(_("----------------------------------------------\n"
696 : "Step 3: Choose one reference to block %"PRIu64" "
697 : "(0x%"PRIx64") to keep.\n"),
698 : dt->block, dt->block);
699 0 : resolve_dup_references(cx, dt, &dt->ref_inode_list, &dh, 0,
700 : REF_TYPES);
701 0 : revise_dup_handler(cx, dup_blk, &dh);
702 : }
703 : /* If there's still a last remaining reference, and it's a valid
704 : reference, use it to determine the correct block type for our
705 : blockmap and bitmap. */
706 0 : if (dh.ref_inode_count == 1 && !osi_list_empty(&dt->ref_inode_list)) {
707 0 : resolve_last_reference(cx, dt, acceptable_ref);
708 : } else {
709 : /* They may have answered no and not fixed all references. */
710 0 : log_debug( _("All duplicate references to block 0x%"PRIx64" were processed.\n"), dup_blk);
711 0 : if (dh.ref_count) {
712 0 : log_debug(_("Done with duplicate reference to block "
713 : "0x%"PRIx64", but %d references remain.\n"),
714 : dup_blk, dh.ref_count);
715 : } else {
716 0 : log_notice(_("Block %"PRIu64" (0x%"PRIx64") has no more "
717 : "references; Marking as 'free'.\n"),
718 : dup_blk, dup_blk);
719 0 : if (dh.dt)
720 0 : dup_delete(cx, dh.dt);
721 0 : check_n_fix_bitmap(cx, NULL, dup_blk, 0,
722 : GFS2_BLKST_FREE);
723 : }
724 : }
725 0 : return 0;
726 : }
727 :
728 0 : static int check_leaf_refs(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
729 : void *private)
730 : {
731 0 : return add_duplicate_ref(cx, ip, block, REF_AS_META, 1, INODE_VALID);
732 : }
733 :
734 0 : static int check_metalist_refs(struct fsck_cx *cx, struct iptr iptr, struct lgfs2_buffer_head **bh, int h,
735 : int *is_valid, int *was_duplicate, void *private)
736 : {
737 0 : struct lgfs2_inode *ip = iptr.ipt_ip;
738 0 : uint64_t block = iptr_block(iptr);
739 :
740 0 : *was_duplicate = 0;
741 0 : *is_valid = 1;
742 0 : return add_duplicate_ref(cx, ip, block, REF_AS_META, 1, INODE_VALID);
743 : }
744 :
745 0 : static int check_data_refs(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t metablock,
746 : uint64_t block, void *private,
747 : struct lgfs2_buffer_head *bh, __be64 *ptr)
748 : {
749 0 : return add_duplicate_ref(cx, ip, block, REF_AS_DATA, 1, INODE_VALID);
750 : }
751 :
752 0 : static int check_eattr_indir_refs(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
753 : uint64_t parent,
754 : struct lgfs2_buffer_head **bh, void *private)
755 : {
756 0 : struct lgfs2_sbd *sdp = ip->i_sbd;
757 : int error;
758 :
759 0 : error = add_duplicate_ref(cx, ip, block, REF_AS_EA, 1, INODE_VALID);
760 0 : if (!error)
761 0 : *bh = lgfs2_bread(sdp, block);
762 :
763 0 : return error;
764 : }
765 :
766 0 : static int check_eattr_leaf_refs(struct fsck_cx *cx, struct lgfs2_inode *ip, uint64_t block,
767 : uint64_t parent, struct lgfs2_buffer_head **bh,
768 : void *private)
769 : {
770 0 : struct lgfs2_sbd *sdp = ip->i_sbd;
771 : int error;
772 :
773 0 : error = add_duplicate_ref(cx, ip, block, REF_AS_EA, 1, INODE_VALID);
774 0 : if (!error)
775 0 : *bh = lgfs2_bread(sdp, block);
776 0 : return error;
777 : }
778 :
779 0 : static int check_eattr_entry_refs(struct fsck_cx *cx, struct lgfs2_inode *ip,
780 : struct lgfs2_buffer_head *leaf_bh,
781 : struct gfs2_ea_header *ea_hdr,
782 : struct gfs2_ea_header *ea_hdr_prev,
783 : void *private)
784 : {
785 0 : return 0;
786 : }
787 :
788 0 : static int check_eattr_extentry_refs(struct fsck_cx *cx, struct lgfs2_inode *ip, int i,
789 : __be64 *ea_data_ptr,
790 : struct lgfs2_buffer_head *leaf_bh,
791 : uint32_t tot_ealen,
792 : struct gfs2_ea_header *ea_hdr,
793 : struct gfs2_ea_header *ea_hdr_prev,
794 : void *private)
795 : {
796 0 : uint64_t block = be64_to_cpu(*ea_data_ptr);
797 :
798 : /* This is a case where a bad return code may be sent back, and
799 : behavior has changed. Before, if add_duplicate_ref returned a
800 : non-zero return code, the caller would delete the eattr from
801 : the blockmap. In this case, we should be okay because the only
802 : error possible is a malloc that fails, in which case we don't
803 : want to delete the eattr anyway. */
804 0 : return add_duplicate_ref(cx, ip, block, REF_AS_EA, 1, INODE_VALID);
805 : }
806 :
807 : /* Finds all references to duplicate blocks in the metadata */
808 : /* Finds all references to duplicate blocks in the metadata */
809 0 : static int find_block_ref(struct fsck_cx *cx, uint64_t inode)
810 : {
811 : struct lgfs2_inode *ip;
812 0 : int error = 0;
813 0 : struct metawalk_fxns find_refs = {
814 : .private = NULL,
815 : .check_leaf = check_leaf_refs,
816 : .check_metalist = check_metalist_refs,
817 : .check_data = check_data_refs,
818 : .check_eattr_indir = check_eattr_indir_refs,
819 : .check_eattr_leaf = check_eattr_leaf_refs,
820 : .check_eattr_entry = check_eattr_entry_refs,
821 : .check_eattr_extentry = check_eattr_extentry_refs,
822 : };
823 :
824 0 : ip = fsck_load_inode(cx->sdp, inode); /* lgfs2_bread, inode_get */
825 :
826 : /* double-check the meta header just to be sure it's metadata */
827 0 : if (ip->i_magic != GFS2_MAGIC ||
828 0 : ip->i_mh_type != GFS2_METATYPE_DI) {
829 0 : log_debug(_("Block %"PRIu64" (0x%"PRIx64") is not a dinode.\n"),
830 : inode, inode);
831 0 : error = 1;
832 0 : goto out;
833 : }
834 : /* Check to see if this inode was referenced by another by mistake */
835 0 : add_duplicate_ref(cx, ip, inode, REF_IS_INODE, 1, INODE_VALID);
836 :
837 : /* Check this dinode's metadata for references to known duplicates */
838 0 : error = check_metatree(cx, ip, &find_refs);
839 0 : if (error < 0)
840 0 : stack;
841 :
842 : /* Check for ea references in the inode */
843 0 : if (!error)
844 0 : error = check_inode_eattr(cx, ip, &find_refs);
845 :
846 0 : out:
847 0 : fsck_inode_put(&ip); /* out, lgfs2_brelse, free */
848 0 : return error;
849 : }
850 :
851 : /* Pass 1b handles finding the previous inode for a duplicate block
852 : * When found, store the inodes pointing to the duplicate block for
853 : * use in pass2 */
854 57 : int pass1b(struct fsck_cx *cx)
855 : {
856 57 : struct lgfs2_sbd *sdp = cx->sdp;
857 : struct duptree *dt;
858 : uint64_t i;
859 : int q;
860 : struct osi_node *n;
861 57 : int rc = FSCK_OK;
862 :
863 57 : log_info( _("Looking for duplicate blocks...\n"));
864 :
865 : /* If there were no dups in the bitmap, we don't need to do anymore */
866 57 : if (cx->dup_blocks.osi_node == NULL) {
867 57 : log_info( _("No duplicate blocks found\n"));
868 57 : return FSCK_OK;
869 : }
870 :
871 : /* Rescan the fs looking for pointers to blocks that are in
872 : * the duplicate block map */
873 0 : log_info( _("Scanning filesystem for inodes containing duplicate blocks...\n"));
874 0 : log_debug(_("Filesystem has %"PRIu64" (0x%"PRIx64") blocks total\n"),
875 : last_fs_block, last_fs_block);
876 0 : for (i = 0; i < last_fs_block; i++) {
877 0 : if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
878 0 : goto out;
879 :
880 0 : if (dups_found_first == dups_found) {
881 0 : log_debug(_("Found all %d original references to "
882 : "duplicates.\n"), dups_found);
883 0 : break;
884 : }
885 0 : q = bitmap_type(sdp, i);
886 :
887 0 : if (q == GFS2_BLKST_FREE || q == GFS2_BLKST_USED || q < 0)
888 0 : continue;
889 :
890 0 : if (q == GFS2_BLKST_UNLINKED) {
891 0 : log_debug(_("Error: block %"PRIu64" (0x%"PRIx64") is still marked UNLINKED.\n"),
892 : i, i);
893 0 : return FSCK_ERROR;
894 : }
895 :
896 0 : display_progress(i);
897 0 : if (find_block_ref(cx, i) < 0) {
898 0 : stack;
899 0 : rc = FSCK_ERROR;
900 0 : goto out;
901 : }
902 : }
903 :
904 : /* Fix dups here - it's going to slow things down a lot to fix
905 : * it later */
906 0 : log_info( _("Handling duplicate blocks\n"));
907 0 : out:
908 : /* Resolve all duplicates by clearing out the dup tree */
909 0 : while ((n = osi_first(&cx->dup_blocks))) {
910 0 : dt = (struct duptree *)n;
911 0 : if (!skip_this_pass && !rc) /* no error & not asked to skip the rest */
912 0 : handle_dup_blk(cx, dt);
913 : }
914 0 : return rc;
915 : }
|