Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <stdio.h>
4 : #include <string.h>
5 : #include <inttypes.h>
6 : #include <stdlib.h>
7 : #include <libintl.h>
8 : #define _(String) gettext(String)
9 :
10 : #include <logging.h>
11 : #include "libgfs2.h"
12 : #include "fsck.h"
13 : #include "util.h"
14 :
15 : #define GFS1_BLKST_USEDMETA 4
16 :
17 132866 : static int check_block_status(struct fsck_cx *cx, struct bmap *bl,
18 : char *buffer, unsigned int buflen,
19 : uint64_t *rg_block, uint64_t rg_data,
20 : uint32_t *count)
21 : {
22 132866 : struct lgfs2_sbd *sdp = cx->sdp;
23 : unsigned char *byte, *end;
24 : unsigned int bit;
25 : unsigned char rg_status;
26 : int q;
27 : uint64_t block;
28 :
29 : /* FIXME verify cast */
30 132866 : byte = (unsigned char *) buffer;
31 132866 : bit = 0;
32 132866 : end = (unsigned char *) buffer + buflen;
33 :
34 482876546 : while (byte < end) {
35 482743680 : rg_status = ((*byte >> bit) & GFS2_BIT_MASK);
36 482743680 : block = rg_data + *rg_block;
37 482743680 : display_progress(block);
38 482743680 : if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
39 0 : return 0;
40 :
41 482743680 : q = block_type(bl, block);
42 482743680 : count[q]++;
43 :
44 : /* If one node opens a file and another node deletes it, we
45 : may be left with a block that appears to be "unlinked" in
46 : the bitmap, but nothing links to it. This is a valid case
47 : and should be cleaned up by the file system eventually.
48 : So we ignore it. */
49 482743680 : if (q == GFS2_BLKST_UNLINKED) {
50 0 : log_err(_("Unlinked inode found at block %"PRIu64" (0x%"PRIx64").\n"),
51 : block, block);
52 0 : if (query(cx, _("Do you want to reclaim the block? (y/n) "))) {
53 0 : lgfs2_rgrp_t rg = lgfs2_blk2rgrpd(sdp, block);
54 0 : if (lgfs2_set_bitmap(rg, block, GFS2_BLKST_FREE))
55 0 : log_err(_("Unlinked block %"PRIu64" (0x%"PRIx64") bitmap not fixed.\n"),
56 : block, block);
57 : else {
58 0 : log_err(_("Unlinked block %"PRIu64" (0x%"PRIx64") bitmap fixed.\n"),
59 : block, block);
60 0 : count[GFS2_BLKST_UNLINKED]--;
61 0 : count[GFS2_BLKST_FREE]++;
62 : }
63 : } else {
64 0 : log_info(_("Unlinked block found at block %"PRIu64" (0x%"PRIx64"), left unchanged.\n"),
65 : block, block);
66 : }
67 482743680 : } else if (rg_status != q) {
68 32833 : log_err(_("Block %"PRIu64" (0x%"PRIx64") bitmap says %u (%s) but FSCK saw %u (%s)\n"),
69 : block, block, rg_status,
70 : block_type_string(rg_status), q,
71 : block_type_string(q));
72 32833 : if (q) /* Don't print redundant "free" */
73 0 : log_err( _("Metadata type is %u (%s)\n"), q,
74 : block_type_string(q));
75 :
76 32833 : if (query(cx, _("Fix bitmap for block %"PRIu64" (0x%"PRIx64")? (y/n) "),
77 : block, block)) {
78 32833 : lgfs2_rgrp_t rg = lgfs2_blk2rgrpd(sdp, block);
79 32833 : if (lgfs2_set_bitmap(rg, block, q))
80 0 : log_err( _("Repair failed.\n"));
81 : else
82 32833 : log_err( _("Fixed.\n"));
83 : } else
84 0 : log_err(_("Bitmap at block %"PRIu64" (0x%"PRIx64") left inconsistent\n"),
85 : block, block);
86 : }
87 482743680 : (*rg_block)++;
88 482743680 : bit += GFS2_BIT_SIZE;
89 482743680 : if (bit >= 8){
90 120685920 : bit = 0;
91 120685920 : byte++;
92 : }
93 : }
94 :
95 132866 : return 0;
96 : }
97 :
98 4440 : static void update_rgrp(struct fsck_cx *cx, struct lgfs2_rgrp_tree *rgp,
99 : struct bmap *bl, uint32_t *count)
100 : {
101 : uint32_t i;
102 : struct lgfs2_bitmap *bits;
103 4440 : uint64_t rg_block = 0;
104 4440 : int update = 0;
105 :
106 137306 : for(i = 0; i < rgp->rt_length; i++) {
107 132866 : bits = &rgp->rt_bits[i];
108 :
109 : /* update the bitmaps */
110 132866 : if (check_block_status(cx, bl, bits->bi_data + bits->bi_offset,
111 : bits->bi_len, &rg_block, rgp->rt_data0, count))
112 0 : return;
113 132866 : if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
114 0 : return;
115 : }
116 :
117 : /* actually adjust counters and write out to disk */
118 4440 : if (rgp->rt_free != count[GFS2_BLKST_FREE]) {
119 1 : log_err(_("RG #%"PRIu64" (0x%"PRIx64") free count inconsistent: "
120 : "is %u should be %u\n"),
121 : rgp->rt_addr, rgp->rt_addr, rgp->rt_free, count[GFS2_BLKST_FREE]);
122 1 : rgp->rt_free = count[GFS2_BLKST_FREE];
123 1 : update = 1;
124 : }
125 4440 : if (rgp->rt_dinodes != count[GFS2_BLKST_DINODE]) {
126 4 : log_err(_("RG #%"PRIu64" (0x%"PRIx64") Inode count inconsistent: is "
127 : "%u should be %u\n"),
128 : rgp->rt_addr, rgp->rt_addr, rgp->rt_dinodes, count[GFS2_BLKST_DINODE]);
129 4 : rgp->rt_dinodes = count[GFS2_BLKST_DINODE];
130 4 : update = 1;
131 : }
132 4440 : if (rgp->rt_data != count[GFS2_BLKST_FREE] +
133 4440 : count[GFS2_BLKST_USED] +
134 4440 : count[GFS2_BLKST_UNLINKED] +
135 4440 : count[GFS2_BLKST_DINODE]) {
136 : /* FIXME not sure how to handle this case ATM - it
137 : * means that the total number of blocks we've counted
138 : * exceeds the blocks in the rg */
139 0 : log_err( _("Internal fsck error: %u != %u + %u + %u + %u\n"),
140 : rgp->rt_data, count[GFS2_BLKST_FREE],
141 : count[GFS2_BLKST_USED], count[GFS2_BLKST_UNLINKED],
142 : count[GFS2_BLKST_DINODE]);
143 0 : exit(FSCK_ERROR);
144 : }
145 4440 : if (update) {
146 5 : if (query(cx, _("Update resource group counts? (y/n) "))) {
147 5 : log_warn( _("Resource group counts updated\n"));
148 5 : lgfs2_rgrp_out(rgp, rgp->rt_bits[0].bi_data);
149 5 : rgp->rt_bits[0].bi_modified = 1;
150 : } else
151 0 : log_err( _("Resource group counts left inconsistent\n"));
152 : }
153 : }
154 :
155 : /**
156 : * pass5 - check resource groups
157 : *
158 : * fix free block maps
159 : * fix used inode maps
160 : */
161 57 : int pass5(struct fsck_cx *cx, struct bmap *bl)
162 : {
163 57 : struct lgfs2_sbd *sdp = cx->sdp;
164 57 : struct osi_node *n, *next = NULL;
165 57 : struct lgfs2_rgrp_tree *rgp = NULL;
166 : uint32_t count[5]; /* we need 5 because of GFS1 usedmeta */
167 57 : uint64_t rg_count = 0;
168 :
169 : /* Reconcile RG bitmaps with fsck bitmap */
170 4497 : for (n = osi_first(&sdp->rgtree); n; n = next) {
171 4440 : next = osi_next(n);
172 4440 : if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
173 0 : return FSCK_OK;
174 4440 : log_info(_("Verifying resource group %"PRIu64"\n"), rg_count);
175 4440 : memset(count, 0, sizeof(count));
176 4440 : rgp = (struct lgfs2_rgrp_tree *)n;
177 :
178 4440 : rg_count++;
179 : /* Compare the bitmaps and report the differences */
180 4440 : update_rgrp(cx, rgp, bl, count);
181 : }
182 : /* Fix up superblock info based on this - don't think there's
183 : * anything to do here... */
184 :
185 57 : return FSCK_OK;
186 : }
|