Blame


1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro #include "dat.h"
3 6f4d00ee 2013-09-23 0intro #include "fns.h"
4 6f4d00ee 2013-09-23 0intro
5 6f4d00ee 2013-09-23 0intro static void checkDirs(Fsck*);
6 6f4d00ee 2013-09-23 0intro static void checkEpochs(Fsck*);
7 6f4d00ee 2013-09-23 0intro static void checkLeak(Fsck*);
8 6f4d00ee 2013-09-23 0intro static void closenop(Fsck*, Block*, u32int);
9 6f4d00ee 2013-09-23 0intro static void clrenop(Fsck*, Block*, int);
10 6f4d00ee 2013-09-23 0intro static void clrinop(Fsck*, char*, MetaBlock*, int, Block*);
11 6f4d00ee 2013-09-23 0intro static void error(Fsck*, char*, ...);
12 6f4d00ee 2013-09-23 0intro static int getBit(uchar*, u32int);
13 6f4d00ee 2013-09-23 0intro static int printnop(char*, ...);
14 6f4d00ee 2013-09-23 0intro static void setBit(uchar*, u32int);
15 6f4d00ee 2013-09-23 0intro static int walkEpoch(Fsck *chk, Block *b, uchar score[VtScoreSize],
16 6f4d00ee 2013-09-23 0intro int type, u32int tag, u32int epoch);
17 6f4d00ee 2013-09-23 0intro static void warn(Fsck*, char*, ...);
18 6f4d00ee 2013-09-23 0intro
19 6f4d00ee 2013-09-23 0intro #pragma varargck argpos error 2
20 6f4d00ee 2013-09-23 0intro #pragma varargck argpos printnop 1
21 6f4d00ee 2013-09-23 0intro #pragma varargck argpos warn 2
22 6f4d00ee 2013-09-23 0intro
23 6f4d00ee 2013-09-23 0intro static Fsck*
24 6f4d00ee 2013-09-23 0intro checkInit(Fsck *chk)
25 6f4d00ee 2013-09-23 0intro {
26 6f4d00ee 2013-09-23 0intro chk->cache = chk->fs->cache;
27 6f4d00ee 2013-09-23 0intro chk->nblocks = cacheLocalSize(chk->cache, PartData);;
28 6f4d00ee 2013-09-23 0intro chk->bsize = chk->fs->blockSize;
29 6f4d00ee 2013-09-23 0intro chk->walkdepth = 0;
30 6f4d00ee 2013-09-23 0intro chk->hint = 0;
31 6f4d00ee 2013-09-23 0intro chk->quantum = chk->nblocks/100;
32 6f4d00ee 2013-09-23 0intro if(chk->quantum == 0)
33 6f4d00ee 2013-09-23 0intro chk->quantum = 1;
34 6f4d00ee 2013-09-23 0intro if(chk->print == nil)
35 6f4d00ee 2013-09-23 0intro chk->print = printnop;
36 6f4d00ee 2013-09-23 0intro if(chk->clre == nil)
37 6f4d00ee 2013-09-23 0intro chk->clre = clrenop;
38 6f4d00ee 2013-09-23 0intro if(chk->close == nil)
39 6f4d00ee 2013-09-23 0intro chk->close = closenop;
40 6f4d00ee 2013-09-23 0intro if(chk->clri == nil)
41 6f4d00ee 2013-09-23 0intro chk->clri = clrinop;
42 6f4d00ee 2013-09-23 0intro return chk;
43 6f4d00ee 2013-09-23 0intro }
44 6f4d00ee 2013-09-23 0intro
45 6f4d00ee 2013-09-23 0intro /*
46 6f4d00ee 2013-09-23 0intro * BUG: Should merge checkEpochs and checkDirs so that
47 6f4d00ee 2013-09-23 0intro * bad blocks are only reported once, and so that errors in checkEpochs
48 6f4d00ee 2013-09-23 0intro * can have the affected file names attached, and so that the file system
49 6f4d00ee 2013-09-23 0intro * is only read once.
50 6f4d00ee 2013-09-23 0intro *
51 6f4d00ee 2013-09-23 0intro * Also should summarize the errors instead of printing for every one
52 6f4d00ee 2013-09-23 0intro * (e.g., XXX bad or unreachable blocks in /active/usr/rsc/foo).
53 6f4d00ee 2013-09-23 0intro */
54 6f4d00ee 2013-09-23 0intro
55 6f4d00ee 2013-09-23 0intro void
56 6f4d00ee 2013-09-23 0intro fsCheck(Fsck *chk)
57 6f4d00ee 2013-09-23 0intro {
58 6f4d00ee 2013-09-23 0intro Block *b;
59 6f4d00ee 2013-09-23 0intro Super super;
60 6f4d00ee 2013-09-23 0intro
61 6f4d00ee 2013-09-23 0intro checkInit(chk);
62 6f4d00ee 2013-09-23 0intro b = superGet(chk->cache, &super);
63 6f4d00ee 2013-09-23 0intro if(b == nil){
64 4b576658 2013-09-23 0intro chk->print("could not load super block: %r");
65 6f4d00ee 2013-09-23 0intro return;
66 6f4d00ee 2013-09-23 0intro }
67 6f4d00ee 2013-09-23 0intro blockPut(b);
68 6f4d00ee 2013-09-23 0intro
69 6f4d00ee 2013-09-23 0intro chk->hint = super.active;
70 6f4d00ee 2013-09-23 0intro checkEpochs(chk);
71 6f4d00ee 2013-09-23 0intro
72 4b576658 2013-09-23 0intro chk->smap = vtmallocz(chk->nblocks/8+1);
73 6f4d00ee 2013-09-23 0intro checkDirs(chk);
74 4b576658 2013-09-23 0intro vtfree(chk->smap);
75 6f4d00ee 2013-09-23 0intro }
76 6f4d00ee 2013-09-23 0intro
77 6f4d00ee 2013-09-23 0intro static void checkEpoch(Fsck*, u32int);
78 6f4d00ee 2013-09-23 0intro
79 6f4d00ee 2013-09-23 0intro /*
80 6f4d00ee 2013-09-23 0intro * Walk through all the blocks in the write buffer.
81 6f4d00ee 2013-09-23 0intro * Then we can look for ones we missed -- those are leaks.
82 6f4d00ee 2013-09-23 0intro */
83 6f4d00ee 2013-09-23 0intro static void
84 6f4d00ee 2013-09-23 0intro checkEpochs(Fsck *chk)
85 6f4d00ee 2013-09-23 0intro {
86 6f4d00ee 2013-09-23 0intro u32int e;
87 6f4d00ee 2013-09-23 0intro uint nb;
88 6f4d00ee 2013-09-23 0intro
89 6f4d00ee 2013-09-23 0intro nb = chk->nblocks;
90 4b576658 2013-09-23 0intro chk->amap = vtmallocz(nb/8+1);
91 4b576658 2013-09-23 0intro chk->emap = vtmallocz(nb/8+1);
92 4b576658 2013-09-23 0intro chk->xmap = vtmallocz(nb/8+1);
93 4b576658 2013-09-23 0intro chk->errmap = vtmallocz(nb/8+1);
94 6f4d00ee 2013-09-23 0intro
95 6f4d00ee 2013-09-23 0intro for(e = chk->fs->ehi; e >= chk->fs->elo; e--){
96 6f4d00ee 2013-09-23 0intro memset(chk->emap, 0, chk->nblocks/8+1);
97 6f4d00ee 2013-09-23 0intro memset(chk->xmap, 0, chk->nblocks/8+1);
98 6f4d00ee 2013-09-23 0intro checkEpoch(chk, e);
99 6f4d00ee 2013-09-23 0intro }
100 6f4d00ee 2013-09-23 0intro checkLeak(chk);
101 4b576658 2013-09-23 0intro vtfree(chk->amap);
102 4b576658 2013-09-23 0intro vtfree(chk->emap);
103 4b576658 2013-09-23 0intro vtfree(chk->xmap);
104 4b576658 2013-09-23 0intro vtfree(chk->errmap);
105 6f4d00ee 2013-09-23 0intro }
106 6f4d00ee 2013-09-23 0intro
107 6f4d00ee 2013-09-23 0intro static void
108 6f4d00ee 2013-09-23 0intro checkEpoch(Fsck *chk, u32int epoch)
109 6f4d00ee 2013-09-23 0intro {
110 6f4d00ee 2013-09-23 0intro u32int a;
111 6f4d00ee 2013-09-23 0intro Block *b;
112 6f4d00ee 2013-09-23 0intro Entry e;
113 6f4d00ee 2013-09-23 0intro Label l;
114 6f4d00ee 2013-09-23 0intro
115 6f4d00ee 2013-09-23 0intro chk->print("checking epoch %ud...\n", epoch);
116 6f4d00ee 2013-09-23 0intro
117 6f4d00ee 2013-09-23 0intro for(a=0; a<chk->nblocks; a++){
118 6f4d00ee 2013-09-23 0intro if(!readLabel(chk->cache, &l, (a+chk->hint)%chk->nblocks)){
119 6f4d00ee 2013-09-23 0intro error(chk, "could not read label for addr 0x%.8#ux", a);
120 6f4d00ee 2013-09-23 0intro continue;
121 6f4d00ee 2013-09-23 0intro }
122 6f4d00ee 2013-09-23 0intro if(l.tag == RootTag && l.epoch == epoch)
123 6f4d00ee 2013-09-23 0intro break;
124 6f4d00ee 2013-09-23 0intro }
125 6f4d00ee 2013-09-23 0intro
126 6f4d00ee 2013-09-23 0intro if(a == chk->nblocks){
127 6f4d00ee 2013-09-23 0intro chk->print("could not find root block for epoch %ud", epoch);
128 6f4d00ee 2013-09-23 0intro return;
129 6f4d00ee 2013-09-23 0intro }
130 6f4d00ee 2013-09-23 0intro
131 6f4d00ee 2013-09-23 0intro a = (a+chk->hint)%chk->nblocks;
132 6f4d00ee 2013-09-23 0intro b = cacheLocalData(chk->cache, a, BtDir, RootTag, OReadOnly, 0);
133 6f4d00ee 2013-09-23 0intro if(b == nil){
134 4b576658 2013-09-23 0intro error(chk, "could not read root block 0x%.8#ux: %r", a);
135 6f4d00ee 2013-09-23 0intro return;
136 6f4d00ee 2013-09-23 0intro }
137 6f4d00ee 2013-09-23 0intro
138 6f4d00ee 2013-09-23 0intro /* no one should point at root blocks */
139 6f4d00ee 2013-09-23 0intro setBit(chk->amap, a);
140 6f4d00ee 2013-09-23 0intro setBit(chk->emap, a);
141 6f4d00ee 2013-09-23 0intro setBit(chk->xmap, a);
142 6f4d00ee 2013-09-23 0intro
143 6f4d00ee 2013-09-23 0intro /*
144 6f4d00ee 2013-09-23 0intro * First entry is the rest of the file system.
145 6f4d00ee 2013-09-23 0intro * Second entry is link to previous epoch root,
146 6f4d00ee 2013-09-23 0intro * just a convenience to help the search.
147 6f4d00ee 2013-09-23 0intro */
148 6f4d00ee 2013-09-23 0intro if(!entryUnpack(&e, b->data, 0)){
149 4b576658 2013-09-23 0intro error(chk, "could not unpack root block 0x%.8#ux: %r", a);
150 6f4d00ee 2013-09-23 0intro blockPut(b);
151 6f4d00ee 2013-09-23 0intro return;
152 6f4d00ee 2013-09-23 0intro }
153 6f4d00ee 2013-09-23 0intro walkEpoch(chk, b, e.score, BtDir, e.tag, epoch);
154 6f4d00ee 2013-09-23 0intro if(entryUnpack(&e, b->data, 1))
155 6f4d00ee 2013-09-23 0intro chk->hint = globalToLocal(e.score);
156 6f4d00ee 2013-09-23 0intro blockPut(b);
157 6f4d00ee 2013-09-23 0intro }
158 6f4d00ee 2013-09-23 0intro
159 6f4d00ee 2013-09-23 0intro /*
160 6f4d00ee 2013-09-23 0intro * When b points at bb, need to check:
161 6f4d00ee 2013-09-23 0intro *
162 6f4d00ee 2013-09-23 0intro * (i) b.e in [bb.e, bb.eClose)
163 6f4d00ee 2013-09-23 0intro * (ii) if b.e==bb.e, then no other b' in e points at bb.
164 6f4d00ee 2013-09-23 0intro * (iii) if !(b.state&Copied) and b.e==bb.e then no other b' points at bb.
165 6f4d00ee 2013-09-23 0intro * (iv) if b is active then no other active b' points at bb.
166 6f4d00ee 2013-09-23 0intro * (v) if b is a past life of b' then only one of b and b' is active
167 6f4d00ee 2013-09-23 0intro * (too hard to check)
168 6f4d00ee 2013-09-23 0intro */
169 6f4d00ee 2013-09-23 0intro static int
170 6f4d00ee 2013-09-23 0intro walkEpoch(Fsck *chk, Block *b, uchar score[VtScoreSize], int type, u32int tag,
171 6f4d00ee 2013-09-23 0intro u32int epoch)
172 6f4d00ee 2013-09-23 0intro {
173 6f4d00ee 2013-09-23 0intro int i, ret;
174 6f4d00ee 2013-09-23 0intro u32int addr, ep;
175 6f4d00ee 2013-09-23 0intro Block *bb;
176 6f4d00ee 2013-09-23 0intro Entry e;
177 6f4d00ee 2013-09-23 0intro
178 6f4d00ee 2013-09-23 0intro if(b && chk->walkdepth == 0 && chk->printblocks)
179 6f4d00ee 2013-09-23 0intro chk->print("%V %d %#.8ux %#.8ux\n", b->score, b->l.type,
180 6f4d00ee 2013-09-23 0intro b->l.tag, b->l.epoch);
181 6f4d00ee 2013-09-23 0intro
182 6f4d00ee 2013-09-23 0intro if(!chk->useventi && globalToLocal(score) == NilBlock)
183 6f4d00ee 2013-09-23 0intro return 1;
184 6f4d00ee 2013-09-23 0intro
185 6f4d00ee 2013-09-23 0intro chk->walkdepth++;
186 6f4d00ee 2013-09-23 0intro
187 6f4d00ee 2013-09-23 0intro bb = cacheGlobal(chk->cache, score, type, tag, OReadOnly);
188 6f4d00ee 2013-09-23 0intro if(bb == nil){
189 4b576658 2013-09-23 0intro error(chk, "could not load block %V type %d tag %ux: %r",
190 6f4d00ee 2013-09-23 0intro score, type, tag);
191 6f4d00ee 2013-09-23 0intro chk->walkdepth--;
192 6f4d00ee 2013-09-23 0intro return 0;
193 6f4d00ee 2013-09-23 0intro }
194 6f4d00ee 2013-09-23 0intro if(chk->printblocks)
195 6f4d00ee 2013-09-23 0intro chk->print("%*s%V %d %#.8ux %#.8ux\n", chk->walkdepth*2, "",
196 6f4d00ee 2013-09-23 0intro score, type, tag, bb->l.epoch);
197 6f4d00ee 2013-09-23 0intro
198 6f4d00ee 2013-09-23 0intro ret = 0;
199 6f4d00ee 2013-09-23 0intro addr = globalToLocal(score);
200 6f4d00ee 2013-09-23 0intro if(addr == NilBlock){
201 6f4d00ee 2013-09-23 0intro ret = 1;
202 6f4d00ee 2013-09-23 0intro goto Exit;
203 6f4d00ee 2013-09-23 0intro }
204 6f4d00ee 2013-09-23 0intro
205 6f4d00ee 2013-09-23 0intro if(b){
206 6f4d00ee 2013-09-23 0intro /* (i) */
207 6f4d00ee 2013-09-23 0intro if(b->l.epoch < bb->l.epoch || bb->l.epochClose <= b->l.epoch){
208 6f4d00ee 2013-09-23 0intro error(chk, "walk: block %#ux [%ud, %ud) points at %#ux [%ud, %ud)",
209 6f4d00ee 2013-09-23 0intro b->addr, b->l.epoch, b->l.epochClose,
210 6f4d00ee 2013-09-23 0intro bb->addr, bb->l.epoch, bb->l.epochClose);
211 6f4d00ee 2013-09-23 0intro goto Exit;
212 6f4d00ee 2013-09-23 0intro }
213 6f4d00ee 2013-09-23 0intro
214 6f4d00ee 2013-09-23 0intro /* (ii) */
215 6f4d00ee 2013-09-23 0intro if(b->l.epoch == epoch && bb->l.epoch == epoch){
216 6f4d00ee 2013-09-23 0intro if(getBit(chk->emap, addr)){
217 6f4d00ee 2013-09-23 0intro error(chk, "walk: epoch join detected: addr %#ux %L",
218 6f4d00ee 2013-09-23 0intro bb->addr, &bb->l);
219 6f4d00ee 2013-09-23 0intro goto Exit;
220 6f4d00ee 2013-09-23 0intro }
221 6f4d00ee 2013-09-23 0intro setBit(chk->emap, addr);
222 6f4d00ee 2013-09-23 0intro }
223 6f4d00ee 2013-09-23 0intro
224 6f4d00ee 2013-09-23 0intro /* (iii) */
225 6f4d00ee 2013-09-23 0intro if(!(b->l.state&BsCopied) && b->l.epoch == bb->l.epoch){
226 6f4d00ee 2013-09-23 0intro if(getBit(chk->xmap, addr)){
227 6f4d00ee 2013-09-23 0intro error(chk, "walk: copy join detected; addr %#ux %L",
228 6f4d00ee 2013-09-23 0intro bb->addr, &bb->l);
229 6f4d00ee 2013-09-23 0intro goto Exit;
230 6f4d00ee 2013-09-23 0intro }
231 6f4d00ee 2013-09-23 0intro setBit(chk->xmap, addr);
232 6f4d00ee 2013-09-23 0intro }
233 6f4d00ee 2013-09-23 0intro }
234 6f4d00ee 2013-09-23 0intro
235 6f4d00ee 2013-09-23 0intro /* (iv) */
236 6f4d00ee 2013-09-23 0intro if(epoch == chk->fs->ehi){
237 6f4d00ee 2013-09-23 0intro /*
238 6f4d00ee 2013-09-23 0intro * since epoch==fs->ehi is first, amap is same as
239 6f4d00ee 2013-09-23 0intro * ``have seen active''
240 6f4d00ee 2013-09-23 0intro */
241 6f4d00ee 2013-09-23 0intro if(getBit(chk->amap, addr)){
242 6f4d00ee 2013-09-23 0intro error(chk, "walk: active join detected: addr %#ux %L",
243 6f4d00ee 2013-09-23 0intro bb->addr, &bb->l);
244 6f4d00ee 2013-09-23 0intro goto Exit;
245 6f4d00ee 2013-09-23 0intro }
246 6f4d00ee 2013-09-23 0intro if(bb->l.state&BsClosed)
247 6f4d00ee 2013-09-23 0intro error(chk, "walk: addr %#ux: block is in active tree but is closed",
248 6f4d00ee 2013-09-23 0intro addr);
249 6f4d00ee 2013-09-23 0intro }else
250 6f4d00ee 2013-09-23 0intro if(!getBit(chk->amap, addr))
251 6f4d00ee 2013-09-23 0intro if(!(bb->l.state&BsClosed)){
252 6f4d00ee 2013-09-23 0intro // error(chk, "walk: addr %#ux: block is not in active tree, not closed (%d)",
253 6f4d00ee 2013-09-23 0intro // addr, bb->l.epochClose);
254 6f4d00ee 2013-09-23 0intro chk->close(chk, bb, epoch+1);
255 6f4d00ee 2013-09-23 0intro chk->nclose++;
256 6f4d00ee 2013-09-23 0intro }
257 6f4d00ee 2013-09-23 0intro
258 6f4d00ee 2013-09-23 0intro if(getBit(chk->amap, addr)){
259 6f4d00ee 2013-09-23 0intro ret = 1;
260 6f4d00ee 2013-09-23 0intro goto Exit;
261 6f4d00ee 2013-09-23 0intro }
262 6f4d00ee 2013-09-23 0intro setBit(chk->amap, addr);
263 6f4d00ee 2013-09-23 0intro
264 6f4d00ee 2013-09-23 0intro if(chk->nseen++%chk->quantum == 0)
265 6f4d00ee 2013-09-23 0intro chk->print("check: visited %d/%d blocks (%.0f%%)\n",
266 6f4d00ee 2013-09-23 0intro chk->nseen, chk->nblocks, chk->nseen*100./chk->nblocks);
267 6f4d00ee 2013-09-23 0intro
268 6f4d00ee 2013-09-23 0intro b = nil; /* make sure no more refs to parent */
269 6f4d00ee 2013-09-23 0intro USED(b);
270 6f4d00ee 2013-09-23 0intro
271 6f4d00ee 2013-09-23 0intro switch(type){
272 6f4d00ee 2013-09-23 0intro default:
273 6f4d00ee 2013-09-23 0intro /* pointer block */
274 6f4d00ee 2013-09-23 0intro for(i = 0; i < chk->bsize/VtScoreSize; i++)
275 6f4d00ee 2013-09-23 0intro if(!walkEpoch(chk, bb, bb->data + i*VtScoreSize,
276 6f4d00ee 2013-09-23 0intro type-1, tag, epoch)){
277 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
278 6f4d00ee 2013-09-23 0intro chk->clrp(chk, bb, i);
279 6f4d00ee 2013-09-23 0intro chk->nclrp++;
280 6f4d00ee 2013-09-23 0intro }
281 6f4d00ee 2013-09-23 0intro break;
282 6f4d00ee 2013-09-23 0intro case BtData:
283 6f4d00ee 2013-09-23 0intro break;
284 6f4d00ee 2013-09-23 0intro case BtDir:
285 6f4d00ee 2013-09-23 0intro for(i = 0; i < chk->bsize/VtEntrySize; i++){
286 6f4d00ee 2013-09-23 0intro if(!entryUnpack(&e, bb->data, i)){
287 4b576658 2013-09-23 0intro // error(chk, "walk: could not unpack entry: %ux[%d]: %r",
288 6f4d00ee 2013-09-23 0intro // addr, i);
289 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
290 6f4d00ee 2013-09-23 0intro chk->clre(chk, bb, i);
291 6f4d00ee 2013-09-23 0intro chk->nclre++;
292 6f4d00ee 2013-09-23 0intro continue;
293 6f4d00ee 2013-09-23 0intro }
294 6f4d00ee 2013-09-23 0intro if(!(e.flags & VtEntryActive))
295 6f4d00ee 2013-09-23 0intro continue;
296 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "%x[%d] tag=%x snap=%d score=%V\n",
297 6f4d00ee 2013-09-23 0intro addr, i, e.tag, e.snap, e.score);
298 6f4d00ee 2013-09-23 0intro ep = epoch;
299 6f4d00ee 2013-09-23 0intro if(e.snap != 0){
300 6f4d00ee 2013-09-23 0intro if(e.snap >= epoch){
301 6f4d00ee 2013-09-23 0intro // error(chk, "bad snap in entry: %ux[%d] snap = %ud: epoch = %ud",
302 6f4d00ee 2013-09-23 0intro // addr, i, e.snap, epoch);
303 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
304 6f4d00ee 2013-09-23 0intro chk->clre(chk, bb, i);
305 6f4d00ee 2013-09-23 0intro chk->nclre++;
306 6f4d00ee 2013-09-23 0intro continue;
307 6f4d00ee 2013-09-23 0intro }
308 6f4d00ee 2013-09-23 0intro continue;
309 6f4d00ee 2013-09-23 0intro }
310 6f4d00ee 2013-09-23 0intro if(e.flags & VtEntryLocal){
311 6f4d00ee 2013-09-23 0intro if(e.tag < UserTag)
312 6f4d00ee 2013-09-23 0intro if(e.tag != RootTag || tag != RootTag || i != 1){
313 6f4d00ee 2013-09-23 0intro // error(chk, "bad tag in entry: %ux[%d] tag = %ux",
314 6f4d00ee 2013-09-23 0intro // addr, i, e.tag);
315 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
316 6f4d00ee 2013-09-23 0intro chk->clre(chk, bb, i);
317 6f4d00ee 2013-09-23 0intro chk->nclre++;
318 6f4d00ee 2013-09-23 0intro continue;
319 6f4d00ee 2013-09-23 0intro }
320 6f4d00ee 2013-09-23 0intro }else
321 6f4d00ee 2013-09-23 0intro if(e.tag != 0){
322 6f4d00ee 2013-09-23 0intro // error(chk, "bad tag in entry: %ux[%d] tag = %ux",
323 6f4d00ee 2013-09-23 0intro // addr, i, e.tag);
324 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
325 6f4d00ee 2013-09-23 0intro chk->clre(chk, bb, i);
326 6f4d00ee 2013-09-23 0intro chk->nclre++;
327 6f4d00ee 2013-09-23 0intro continue;
328 6f4d00ee 2013-09-23 0intro }
329 6f4d00ee 2013-09-23 0intro if(!walkEpoch(chk, bb, e.score, entryType(&e),
330 6f4d00ee 2013-09-23 0intro e.tag, ep)){
331 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
332 6f4d00ee 2013-09-23 0intro chk->clre(chk, bb, i);
333 6f4d00ee 2013-09-23 0intro chk->nclre++;
334 6f4d00ee 2013-09-23 0intro }
335 6f4d00ee 2013-09-23 0intro }
336 6f4d00ee 2013-09-23 0intro break;
337 6f4d00ee 2013-09-23 0intro }
338 6f4d00ee 2013-09-23 0intro
339 6f4d00ee 2013-09-23 0intro ret = 1;
340 6f4d00ee 2013-09-23 0intro
341 6f4d00ee 2013-09-23 0intro Exit:
342 6f4d00ee 2013-09-23 0intro chk->walkdepth--;
343 6f4d00ee 2013-09-23 0intro blockPut(bb);
344 6f4d00ee 2013-09-23 0intro return ret;
345 6f4d00ee 2013-09-23 0intro }
346 6f4d00ee 2013-09-23 0intro
347 6f4d00ee 2013-09-23 0intro /*
348 6f4d00ee 2013-09-23 0intro * We've just walked the whole write buffer. Notice blocks that
349 6f4d00ee 2013-09-23 0intro * aren't marked available but that we didn't visit. They are lost.
350 6f4d00ee 2013-09-23 0intro */
351 6f4d00ee 2013-09-23 0intro static void
352 6f4d00ee 2013-09-23 0intro checkLeak(Fsck *chk)
353 6f4d00ee 2013-09-23 0intro {
354 6f4d00ee 2013-09-23 0intro u32int a, nfree, nlost;
355 6f4d00ee 2013-09-23 0intro Block *b;
356 6f4d00ee 2013-09-23 0intro Label l;
357 6f4d00ee 2013-09-23 0intro
358 6f4d00ee 2013-09-23 0intro nfree = 0;
359 6f4d00ee 2013-09-23 0intro nlost = 0;
360 6f4d00ee 2013-09-23 0intro
361 6f4d00ee 2013-09-23 0intro for(a = 0; a < chk->nblocks; a++){
362 6f4d00ee 2013-09-23 0intro if(!readLabel(chk->cache, &l, a)){
363 4b576658 2013-09-23 0intro error(chk, "could not read label: addr 0x%ux %d %d: %r",
364 6f4d00ee 2013-09-23 0intro a, l.type, l.state);
365 6f4d00ee 2013-09-23 0intro continue;
366 6f4d00ee 2013-09-23 0intro }
367 6f4d00ee 2013-09-23 0intro if(getBit(chk->amap, a))
368 6f4d00ee 2013-09-23 0intro continue;
369 6f4d00ee 2013-09-23 0intro if(l.state == BsFree || l.epochClose <= chk->fs->elo ||
370 6f4d00ee 2013-09-23 0intro l.epochClose == l.epoch){
371 6f4d00ee 2013-09-23 0intro nfree++;
372 6f4d00ee 2013-09-23 0intro setBit(chk->amap, a);
373 6f4d00ee 2013-09-23 0intro continue;
374 6f4d00ee 2013-09-23 0intro }
375 6f4d00ee 2013-09-23 0intro if(l.state&BsClosed)
376 6f4d00ee 2013-09-23 0intro continue;
377 6f4d00ee 2013-09-23 0intro nlost++;
378 6f4d00ee 2013-09-23 0intro // warn(chk, "unreachable block: addr 0x%ux type %d tag 0x%ux "
379 6f4d00ee 2013-09-23 0intro // "state %s epoch %ud close %ud", a, l.type, l.tag,
380 6f4d00ee 2013-09-23 0intro // bsStr(l.state), l.epoch, l.epochClose);
381 6f4d00ee 2013-09-23 0intro b = cacheLocal(chk->cache, PartData, a, OReadOnly);
382 6f4d00ee 2013-09-23 0intro if(b == nil){
383 6f4d00ee 2013-09-23 0intro error(chk, "could not read block 0x%#.8ux", a);
384 6f4d00ee 2013-09-23 0intro continue;
385 6f4d00ee 2013-09-23 0intro }
386 6f4d00ee 2013-09-23 0intro chk->close(chk, b, 0);
387 6f4d00ee 2013-09-23 0intro chk->nclose++;
388 6f4d00ee 2013-09-23 0intro setBit(chk->amap, a);
389 6f4d00ee 2013-09-23 0intro blockPut(b);
390 6f4d00ee 2013-09-23 0intro }
391 6f4d00ee 2013-09-23 0intro chk->print("fsys blocks: total=%ud used=%ud(%.1f%%) free=%ud(%.1f%%) lost=%ud(%.1f%%)\n",
392 6f4d00ee 2013-09-23 0intro chk->nblocks,
393 6f4d00ee 2013-09-23 0intro chk->nblocks - nfree-nlost,
394 6f4d00ee 2013-09-23 0intro 100.*(chk->nblocks - nfree - nlost)/chk->nblocks,
395 6f4d00ee 2013-09-23 0intro nfree, 100.*nfree/chk->nblocks,
396 6f4d00ee 2013-09-23 0intro nlost, 100.*nlost/chk->nblocks);
397 6f4d00ee 2013-09-23 0intro }
398 6f4d00ee 2013-09-23 0intro
399 6f4d00ee 2013-09-23 0intro
400 6f4d00ee 2013-09-23 0intro /*
401 6f4d00ee 2013-09-23 0intro * Check that all sources in the tree are accessible.
402 6f4d00ee 2013-09-23 0intro */
403 6f4d00ee 2013-09-23 0intro static Source *
404 6f4d00ee 2013-09-23 0intro openSource(Fsck *chk, Source *s, char *name, uchar *bm, u32int offset,
405 6f4d00ee 2013-09-23 0intro u32int gen, int dir, MetaBlock *mb, int i, Block *b)
406 6f4d00ee 2013-09-23 0intro {
407 6f4d00ee 2013-09-23 0intro Source *r;
408 6f4d00ee 2013-09-23 0intro
409 6f4d00ee 2013-09-23 0intro r = nil;
410 6f4d00ee 2013-09-23 0intro if(getBit(bm, offset)){
411 6f4d00ee 2013-09-23 0intro warn(chk, "multiple references to source: %s -> %d",
412 6f4d00ee 2013-09-23 0intro name, offset);
413 6f4d00ee 2013-09-23 0intro goto Err;
414 6f4d00ee 2013-09-23 0intro }
415 6f4d00ee 2013-09-23 0intro setBit(bm, offset);
416 6f4d00ee 2013-09-23 0intro
417 6f4d00ee 2013-09-23 0intro r = sourceOpen(s, offset, OReadOnly, 0);
418 6f4d00ee 2013-09-23 0intro if(r == nil){
419 4b576658 2013-09-23 0intro warn(chk, "could not open source: %s -> %d: %r", name, offset);
420 6f4d00ee 2013-09-23 0intro goto Err;
421 6f4d00ee 2013-09-23 0intro }
422 6f4d00ee 2013-09-23 0intro
423 6f4d00ee 2013-09-23 0intro if(r->gen != gen){
424 6f4d00ee 2013-09-23 0intro warn(chk, "source has been removed: %s -> %d", name, offset);
425 6f4d00ee 2013-09-23 0intro goto Err;
426 6f4d00ee 2013-09-23 0intro }
427 6f4d00ee 2013-09-23 0intro
428 6f4d00ee 2013-09-23 0intro if(r->dir != dir){
429 6f4d00ee 2013-09-23 0intro warn(chk, "dir mismatch: %s -> %d", name, offset);
430 6f4d00ee 2013-09-23 0intro goto Err;
431 6f4d00ee 2013-09-23 0intro }
432 6f4d00ee 2013-09-23 0intro return r;
433 6f4d00ee 2013-09-23 0intro Err:
434 6f4d00ee 2013-09-23 0intro chk->clri(chk, name, mb, i, b);
435 6f4d00ee 2013-09-23 0intro chk->nclri++;
436 6f4d00ee 2013-09-23 0intro if(r)
437 6f4d00ee 2013-09-23 0intro sourceClose(r);
438 6f4d00ee 2013-09-23 0intro return nil;
439 6f4d00ee 2013-09-23 0intro }
440 6f4d00ee 2013-09-23 0intro
441 6f4d00ee 2013-09-23 0intro typedef struct MetaChunk MetaChunk;
442 6f4d00ee 2013-09-23 0intro struct MetaChunk {
443 6f4d00ee 2013-09-23 0intro ushort offset;
444 6f4d00ee 2013-09-23 0intro ushort size;
445 6f4d00ee 2013-09-23 0intro ushort index;
446 6f4d00ee 2013-09-23 0intro };
447 6f4d00ee 2013-09-23 0intro
448 6f4d00ee 2013-09-23 0intro static int
449 b29ebaab 2013-10-23 0intro offsetCmp(const void *s0, const void *s1)
450 6f4d00ee 2013-09-23 0intro {
451 6f4d00ee 2013-09-23 0intro MetaChunk *mc0, *mc1;
452 6f4d00ee 2013-09-23 0intro
453 b29ebaab 2013-10-23 0intro mc0 = (MetaChunk*)s0;
454 b29ebaab 2013-10-23 0intro mc1 = (MetaChunk*)s1;
455 6f4d00ee 2013-09-23 0intro if(mc0->offset < mc1->offset)
456 6f4d00ee 2013-09-23 0intro return -1;
457 6f4d00ee 2013-09-23 0intro if(mc0->offset > mc1->offset)
458 6f4d00ee 2013-09-23 0intro return 1;
459 6f4d00ee 2013-09-23 0intro return 0;
460 6f4d00ee 2013-09-23 0intro }
461 6f4d00ee 2013-09-23 0intro
462 6f4d00ee 2013-09-23 0intro /*
463 6f4d00ee 2013-09-23 0intro * Fsck that MetaBlock has reasonable header, sorted entries,
464 6f4d00ee 2013-09-23 0intro */
465 6f4d00ee 2013-09-23 0intro static int
466 6f4d00ee 2013-09-23 0intro chkMetaBlock(MetaBlock *mb)
467 6f4d00ee 2013-09-23 0intro {
468 6f4d00ee 2013-09-23 0intro MetaChunk *mc;
469 6f4d00ee 2013-09-23 0intro int oo, o, n, i;
470 6f4d00ee 2013-09-23 0intro uchar *p;
471 6f4d00ee 2013-09-23 0intro
472 4b576658 2013-09-23 0intro mc = vtmalloc(mb->nindex*sizeof(MetaChunk));
473 6f4d00ee 2013-09-23 0intro p = mb->buf + MetaHeaderSize;
474 6f4d00ee 2013-09-23 0intro for(i = 0; i < mb->nindex; i++){
475 6f4d00ee 2013-09-23 0intro mc[i].offset = p[0]<<8 | p[1];
476 6f4d00ee 2013-09-23 0intro mc[i].size = p[2]<<8 | p[3];
477 6f4d00ee 2013-09-23 0intro mc[i].index = i;
478 6f4d00ee 2013-09-23 0intro p += MetaIndexSize;
479 6f4d00ee 2013-09-23 0intro }
480 6f4d00ee 2013-09-23 0intro
481 6f4d00ee 2013-09-23 0intro qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp);
482 6f4d00ee 2013-09-23 0intro
483 6f4d00ee 2013-09-23 0intro /* check block looks ok */
484 6f4d00ee 2013-09-23 0intro oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
485 6f4d00ee 2013-09-23 0intro o = oo;
486 6f4d00ee 2013-09-23 0intro n = 0;
487 6f4d00ee 2013-09-23 0intro for(i = 0; i < mb->nindex; i++){
488 6f4d00ee 2013-09-23 0intro o = mc[i].offset;
489 6f4d00ee 2013-09-23 0intro n = mc[i].size;
490 6f4d00ee 2013-09-23 0intro if(o < oo)
491 6f4d00ee 2013-09-23 0intro goto Err;
492 6f4d00ee 2013-09-23 0intro oo += n;
493 6f4d00ee 2013-09-23 0intro }
494 6f4d00ee 2013-09-23 0intro if(o+n > mb->size || mb->size - oo != mb->free)
495 6f4d00ee 2013-09-23 0intro goto Err;
496 6f4d00ee 2013-09-23 0intro
497 4b576658 2013-09-23 0intro vtfree(mc);
498 6f4d00ee 2013-09-23 0intro return 1;
499 6f4d00ee 2013-09-23 0intro
500 6f4d00ee 2013-09-23 0intro Err:
501 6f4d00ee 2013-09-23 0intro if(0){
502 6f4d00ee 2013-09-23 0intro fprint(2, "metaChunks failed!\n");
503 6f4d00ee 2013-09-23 0intro oo = MetaHeaderSize + mb->maxindex*MetaIndexSize;
504 6f4d00ee 2013-09-23 0intro for(i=0; i<mb->nindex; i++){
505 6f4d00ee 2013-09-23 0intro fprint(2, "\t%d: %d %d\n", i, mc[i].offset,
506 6f4d00ee 2013-09-23 0intro mc[i].offset + mc[i].size);
507 6f4d00ee 2013-09-23 0intro oo += mc[i].size;
508 6f4d00ee 2013-09-23 0intro }
509 6f4d00ee 2013-09-23 0intro fprint(2, "\tused=%d size=%d free=%d free2=%d\n",
510 6f4d00ee 2013-09-23 0intro oo, mb->size, mb->free, mb->size - oo);
511 6f4d00ee 2013-09-23 0intro }
512 4b576658 2013-09-23 0intro vtfree(mc);
513 6f4d00ee 2013-09-23 0intro return 0;
514 6f4d00ee 2013-09-23 0intro }
515 6f4d00ee 2013-09-23 0intro
516 6f4d00ee 2013-09-23 0intro static void
517 6f4d00ee 2013-09-23 0intro scanSource(Fsck *chk, char *name, Source *r)
518 6f4d00ee 2013-09-23 0intro {
519 6f4d00ee 2013-09-23 0intro u32int a, nb, o;
520 6f4d00ee 2013-09-23 0intro Block *b;
521 6f4d00ee 2013-09-23 0intro Entry e;
522 6f4d00ee 2013-09-23 0intro
523 6f4d00ee 2013-09-23 0intro if(!chk->useventi && globalToLocal(r->score)==NilBlock)
524 6f4d00ee 2013-09-23 0intro return;
525 6f4d00ee 2013-09-23 0intro if(!sourceGetEntry(r, &e)){
526 6f4d00ee 2013-09-23 0intro error(chk, "could not get entry for %s", name);
527 6f4d00ee 2013-09-23 0intro return;
528 6f4d00ee 2013-09-23 0intro }
529 6f4d00ee 2013-09-23 0intro a = globalToLocal(e.score);
530 6f4d00ee 2013-09-23 0intro if(!chk->useventi && a==NilBlock)
531 6f4d00ee 2013-09-23 0intro return;
532 6f4d00ee 2013-09-23 0intro if(getBit(chk->smap, a))
533 6f4d00ee 2013-09-23 0intro return;
534 6f4d00ee 2013-09-23 0intro setBit(chk->smap, a);
535 6f4d00ee 2013-09-23 0intro
536 6f4d00ee 2013-09-23 0intro nb = (sourceGetSize(r) + r->dsize-1) / r->dsize;
537 6f4d00ee 2013-09-23 0intro for(o = 0; o < nb; o++){
538 6f4d00ee 2013-09-23 0intro b = sourceBlock(r, o, OReadOnly);
539 6f4d00ee 2013-09-23 0intro if(b == nil){
540 6f4d00ee 2013-09-23 0intro error(chk, "could not read block in data file %s", name);
541 6f4d00ee 2013-09-23 0intro continue;
542 6f4d00ee 2013-09-23 0intro }
543 6f4d00ee 2013-09-23 0intro if(b->addr != NilBlock && getBit(chk->errmap, b->addr)){
544 6f4d00ee 2013-09-23 0intro warn(chk, "previously reported error in block %ux is in file %s",
545 6f4d00ee 2013-09-23 0intro b->addr, name);
546 6f4d00ee 2013-09-23 0intro }
547 6f4d00ee 2013-09-23 0intro blockPut(b);
548 6f4d00ee 2013-09-23 0intro }
549 6f4d00ee 2013-09-23 0intro }
550 6f4d00ee 2013-09-23 0intro
551 6f4d00ee 2013-09-23 0intro /*
552 6f4d00ee 2013-09-23 0intro * Walk the source tree making sure that the BtData
553 6f4d00ee 2013-09-23 0intro * sources containing directory entries are okay.
554 6f4d00ee 2013-09-23 0intro */
555 6f4d00ee 2013-09-23 0intro static void
556 6f4d00ee 2013-09-23 0intro chkDir(Fsck *chk, char *name, Source *source, Source *meta)
557 6f4d00ee 2013-09-23 0intro {
558 6f4d00ee 2013-09-23 0intro int i;
559 6f4d00ee 2013-09-23 0intro u32int a1, a2, nb, o;
560 6f4d00ee 2013-09-23 0intro char *s, *nn;
561 6f4d00ee 2013-09-23 0intro uchar *bm;
562 6f4d00ee 2013-09-23 0intro Block *b, *bb;
563 6f4d00ee 2013-09-23 0intro DirEntry de;
564 6f4d00ee 2013-09-23 0intro Entry e1, e2;
565 6f4d00ee 2013-09-23 0intro MetaBlock mb;
566 6f4d00ee 2013-09-23 0intro MetaEntry me;
567 6f4d00ee 2013-09-23 0intro Source *r, *mr;
568 6f4d00ee 2013-09-23 0intro
569 6f4d00ee 2013-09-23 0intro if(!chk->useventi && globalToLocal(source->score)==NilBlock &&
570 6f4d00ee 2013-09-23 0intro globalToLocal(meta->score)==NilBlock)
571 6f4d00ee 2013-09-23 0intro return;
572 6f4d00ee 2013-09-23 0intro
573 6f4d00ee 2013-09-23 0intro if(!sourceLock2(source, meta, OReadOnly)){
574 4b576658 2013-09-23 0intro warn(chk, "could not lock sources for %s: %r", name);
575 6f4d00ee 2013-09-23 0intro return;
576 6f4d00ee 2013-09-23 0intro }
577 6f4d00ee 2013-09-23 0intro if(!sourceGetEntry(source, &e1) || !sourceGetEntry(meta, &e2)){
578 4b576658 2013-09-23 0intro warn(chk, "could not load entries for %s: %r", name);
579 6f4d00ee 2013-09-23 0intro return;
580 6f4d00ee 2013-09-23 0intro }
581 6f4d00ee 2013-09-23 0intro a1 = globalToLocal(e1.score);
582 6f4d00ee 2013-09-23 0intro a2 = globalToLocal(e2.score);
583 6f4d00ee 2013-09-23 0intro if((!chk->useventi && a1==NilBlock && a2==NilBlock)
584 6f4d00ee 2013-09-23 0intro || (getBit(chk->smap, a1) && getBit(chk->smap, a2))){
585 6f4d00ee 2013-09-23 0intro sourceUnlock(source);
586 6f4d00ee 2013-09-23 0intro sourceUnlock(meta);
587 6f4d00ee 2013-09-23 0intro return;
588 6f4d00ee 2013-09-23 0intro }
589 6f4d00ee 2013-09-23 0intro setBit(chk->smap, a1);
590 6f4d00ee 2013-09-23 0intro setBit(chk->smap, a2);
591 6f4d00ee 2013-09-23 0intro
592 4b576658 2013-09-23 0intro bm = vtmallocz(sourceGetDirSize(source)/8 + 1);
593 6f4d00ee 2013-09-23 0intro
594 6f4d00ee 2013-09-23 0intro nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize;
595 6f4d00ee 2013-09-23 0intro for(o = 0; o < nb; o++){
596 6f4d00ee 2013-09-23 0intro b = sourceBlock(meta, o, OReadOnly);
597 6f4d00ee 2013-09-23 0intro if(b == nil){
598 4b576658 2013-09-23 0intro error(chk, "could not read block in meta file: %s[%ud]: %r",
599 6f4d00ee 2013-09-23 0intro name, o);
600 6f4d00ee 2013-09-23 0intro continue;
601 6f4d00ee 2013-09-23 0intro }
602 6f4d00ee 2013-09-23 0intro if(0) fprint(2, "source %V:%d block %d addr %d\n", source->score,
603 6f4d00ee 2013-09-23 0intro source->offset, o, b->addr);
604 6f4d00ee 2013-09-23 0intro if(b->addr != NilBlock && getBit(chk->errmap, b->addr))
605 6f4d00ee 2013-09-23 0intro warn(chk, "previously reported error in block %ux is in %s",
606 6f4d00ee 2013-09-23 0intro b->addr, name);
607 6f4d00ee 2013-09-23 0intro
608 6f4d00ee 2013-09-23 0intro if(!mbUnpack(&mb, b->data, meta->dsize)){
609 4b576658 2013-09-23 0intro error(chk, "could not unpack meta block: %s[%ud]: %r",
610 6f4d00ee 2013-09-23 0intro name, o);
611 6f4d00ee 2013-09-23 0intro blockPut(b);
612 6f4d00ee 2013-09-23 0intro continue;
613 6f4d00ee 2013-09-23 0intro }
614 6f4d00ee 2013-09-23 0intro if(!chkMetaBlock(&mb)){
615 4b576658 2013-09-23 0intro error(chk, "bad meta block: %s[%ud]: %r", name, o);
616 6f4d00ee 2013-09-23 0intro blockPut(b);
617 6f4d00ee 2013-09-23 0intro continue;
618 6f4d00ee 2013-09-23 0intro }
619 6f4d00ee 2013-09-23 0intro s = nil;
620 6f4d00ee 2013-09-23 0intro for(i=mb.nindex-1; i>=0; i--){
621 6f4d00ee 2013-09-23 0intro meUnpack(&me, &mb, i);
622 6f4d00ee 2013-09-23 0intro if(!deUnpack(&de, &me)){
623 6f4d00ee 2013-09-23 0intro error(chk,
624 4b576658 2013-09-23 0intro "could not unpack dir entry: %s[%ud][%d]: %r",
625 6f4d00ee 2013-09-23 0intro name, o, i);
626 6f4d00ee 2013-09-23 0intro continue;
627 6f4d00ee 2013-09-23 0intro }
628 6f4d00ee 2013-09-23 0intro if(s && strcmp(s, de.elem) <= 0)
629 6f4d00ee 2013-09-23 0intro error(chk,
630 6f4d00ee 2013-09-23 0intro "dir entry out of order: %s[%ud][%d] = %s last = %s",
631 6f4d00ee 2013-09-23 0intro name, o, i, de.elem, s);
632 4b576658 2013-09-23 0intro vtfree(s);
633 4b576658 2013-09-23 0intro s = vtstrdup(de.elem);
634 6f4d00ee 2013-09-23 0intro nn = smprint("%s/%s", name, de.elem);
635 6f4d00ee 2013-09-23 0intro if(nn == nil){
636 6f4d00ee 2013-09-23 0intro error(chk, "out of memory");
637 6f4d00ee 2013-09-23 0intro continue;
638 6f4d00ee 2013-09-23 0intro }
639 6f4d00ee 2013-09-23 0intro if(chk->printdirs)
640 6f4d00ee 2013-09-23 0intro if(de.mode&ModeDir)
641 6f4d00ee 2013-09-23 0intro chk->print("%s/\n", nn);
642 6f4d00ee 2013-09-23 0intro if(chk->printfiles)
643 6f4d00ee 2013-09-23 0intro if(!(de.mode&ModeDir))
644 6f4d00ee 2013-09-23 0intro chk->print("%s\n", nn);
645 6f4d00ee 2013-09-23 0intro if(!(de.mode & ModeDir)){
646 6f4d00ee 2013-09-23 0intro r = openSource(chk, source, nn, bm, de.entry,
647 6f4d00ee 2013-09-23 0intro de.gen, 0, &mb, i, b);
648 6f4d00ee 2013-09-23 0intro if(r != nil){
649 6f4d00ee 2013-09-23 0intro if(sourceLock(r, OReadOnly)){
650 6f4d00ee 2013-09-23 0intro scanSource(chk, nn, r);
651 6f4d00ee 2013-09-23 0intro sourceUnlock(r);
652 6f4d00ee 2013-09-23 0intro }
653 6f4d00ee 2013-09-23 0intro sourceClose(r);
654 6f4d00ee 2013-09-23 0intro }
655 6f4d00ee 2013-09-23 0intro deCleanup(&de);
656 6f4d00ee 2013-09-23 0intro free(nn);
657 6f4d00ee 2013-09-23 0intro continue;
658 6f4d00ee 2013-09-23 0intro }
659 6f4d00ee 2013-09-23 0intro
660 6f4d00ee 2013-09-23 0intro r = openSource(chk, source, nn, bm, de.entry,
661 6f4d00ee 2013-09-23 0intro de.gen, 1, &mb, i, b);
662 6f4d00ee 2013-09-23 0intro if(r == nil){
663 6f4d00ee 2013-09-23 0intro deCleanup(&de);
664 6f4d00ee 2013-09-23 0intro free(nn);
665 6f4d00ee 2013-09-23 0intro continue;
666 6f4d00ee 2013-09-23 0intro }
667 6f4d00ee 2013-09-23 0intro
668 6f4d00ee 2013-09-23 0intro mr = openSource(chk, source, nn, bm, de.mentry,
669 6f4d00ee 2013-09-23 0intro de.mgen, 0, &mb, i, b);
670 6f4d00ee 2013-09-23 0intro if(mr == nil){
671 6f4d00ee 2013-09-23 0intro sourceClose(r);
672 6f4d00ee 2013-09-23 0intro deCleanup(&de);
673 6f4d00ee 2013-09-23 0intro free(nn);
674 6f4d00ee 2013-09-23 0intro continue;
675 6f4d00ee 2013-09-23 0intro }
676 6f4d00ee 2013-09-23 0intro
677 6f4d00ee 2013-09-23 0intro if(!(de.mode&ModeSnapshot) || chk->walksnapshots)
678 6f4d00ee 2013-09-23 0intro chkDir(chk, nn, r, mr);
679 6f4d00ee 2013-09-23 0intro
680 6f4d00ee 2013-09-23 0intro sourceClose(mr);
681 6f4d00ee 2013-09-23 0intro sourceClose(r);
682 6f4d00ee 2013-09-23 0intro deCleanup(&de);
683 6f4d00ee 2013-09-23 0intro free(nn);
684 6f4d00ee 2013-09-23 0intro deCleanup(&de);
685 6f4d00ee 2013-09-23 0intro
686 6f4d00ee 2013-09-23 0intro }
687 4b576658 2013-09-23 0intro vtfree(s);
688 6f4d00ee 2013-09-23 0intro blockPut(b);
689 6f4d00ee 2013-09-23 0intro }
690 6f4d00ee 2013-09-23 0intro
691 6f4d00ee 2013-09-23 0intro nb = sourceGetDirSize(source);
692 6f4d00ee 2013-09-23 0intro for(o=0; o<nb; o++){
693 6f4d00ee 2013-09-23 0intro if(getBit(bm, o))
694 6f4d00ee 2013-09-23 0intro continue;
695 6f4d00ee 2013-09-23 0intro r = sourceOpen(source, o, OReadOnly, 0);
696 6f4d00ee 2013-09-23 0intro if(r == nil)
697 6f4d00ee 2013-09-23 0intro continue;
698 6f4d00ee 2013-09-23 0intro warn(chk, "non referenced entry in source %s[%d]", name, o);
699 6f4d00ee 2013-09-23 0intro if((bb = sourceBlock(source, o/(source->dsize/VtEntrySize),
700 6f4d00ee 2013-09-23 0intro OReadOnly)) != nil){
701 6f4d00ee 2013-09-23 0intro if(bb->addr != NilBlock){
702 6f4d00ee 2013-09-23 0intro setBit(chk->errmap, bb->addr);
703 6f4d00ee 2013-09-23 0intro chk->clre(chk, bb, o%(source->dsize/VtEntrySize));
704 6f4d00ee 2013-09-23 0intro chk->nclre++;
705 6f4d00ee 2013-09-23 0intro }
706 6f4d00ee 2013-09-23 0intro blockPut(bb);
707 6f4d00ee 2013-09-23 0intro }
708 6f4d00ee 2013-09-23 0intro sourceClose(r);
709 6f4d00ee 2013-09-23 0intro }
710 6f4d00ee 2013-09-23 0intro
711 6f4d00ee 2013-09-23 0intro sourceUnlock(source);
712 6f4d00ee 2013-09-23 0intro sourceUnlock(meta);
713 4b576658 2013-09-23 0intro vtfree(bm);
714 6f4d00ee 2013-09-23 0intro }
715 6f4d00ee 2013-09-23 0intro
716 6f4d00ee 2013-09-23 0intro static void
717 6f4d00ee 2013-09-23 0intro checkDirs(Fsck *chk)
718 6f4d00ee 2013-09-23 0intro {
719 6f4d00ee 2013-09-23 0intro Source *r, *mr;
720 6f4d00ee 2013-09-23 0intro
721 6f4d00ee 2013-09-23 0intro sourceLock(chk->fs->source, OReadOnly);
722 6f4d00ee 2013-09-23 0intro r = sourceOpen(chk->fs->source, 0, OReadOnly, 0);
723 6f4d00ee 2013-09-23 0intro mr = sourceOpen(chk->fs->source, 1, OReadOnly, 0);
724 6f4d00ee 2013-09-23 0intro sourceUnlock(chk->fs->source);
725 6f4d00ee 2013-09-23 0intro chkDir(chk, "", r, mr);
726 6f4d00ee 2013-09-23 0intro
727 6f4d00ee 2013-09-23 0intro sourceClose(r);
728 6f4d00ee 2013-09-23 0intro sourceClose(mr);
729 6f4d00ee 2013-09-23 0intro }
730 6f4d00ee 2013-09-23 0intro
731 6f4d00ee 2013-09-23 0intro static void
732 6f4d00ee 2013-09-23 0intro setBit(uchar *bmap, u32int addr)
733 6f4d00ee 2013-09-23 0intro {
734 6f4d00ee 2013-09-23 0intro if(addr == NilBlock)
735 6f4d00ee 2013-09-23 0intro return;
736 6f4d00ee 2013-09-23 0intro
737 6f4d00ee 2013-09-23 0intro bmap[addr>>3] |= 1 << (addr & 7);
738 6f4d00ee 2013-09-23 0intro }
739 6f4d00ee 2013-09-23 0intro
740 6f4d00ee 2013-09-23 0intro static int
741 6f4d00ee 2013-09-23 0intro getBit(uchar *bmap, u32int addr)
742 6f4d00ee 2013-09-23 0intro {
743 6f4d00ee 2013-09-23 0intro if(addr == NilBlock)
744 6f4d00ee 2013-09-23 0intro return 0;
745 6f4d00ee 2013-09-23 0intro
746 6f4d00ee 2013-09-23 0intro return (bmap[addr>>3] >> (addr & 7)) & 1;
747 6f4d00ee 2013-09-23 0intro }
748 6f4d00ee 2013-09-23 0intro
749 6f4d00ee 2013-09-23 0intro static void
750 6f4d00ee 2013-09-23 0intro error(Fsck *chk, char *fmt, ...)
751 6f4d00ee 2013-09-23 0intro {
752 6f4d00ee 2013-09-23 0intro char buf[256];
753 6f4d00ee 2013-09-23 0intro va_list arg;
754 6f4d00ee 2013-09-23 0intro
755 6f4d00ee 2013-09-23 0intro va_start(arg, fmt);
756 6f4d00ee 2013-09-23 0intro vseprint(buf, buf+sizeof buf, fmt, arg);
757 6f4d00ee 2013-09-23 0intro va_end(arg);
758 6f4d00ee 2013-09-23 0intro
759 6f4d00ee 2013-09-23 0intro chk->print("error: %s\n", buf);
760 6f4d00ee 2013-09-23 0intro
761 6f4d00ee 2013-09-23 0intro // if(nerr++ > 20)
762 4b576658 2013-09-23 0intro // sysfatal("too many errors");
763 6f4d00ee 2013-09-23 0intro }
764 6f4d00ee 2013-09-23 0intro
765 6f4d00ee 2013-09-23 0intro static void
766 6f4d00ee 2013-09-23 0intro warn(Fsck *chk, char *fmt, ...)
767 6f4d00ee 2013-09-23 0intro {
768 6f4d00ee 2013-09-23 0intro char buf[256];
769 6f4d00ee 2013-09-23 0intro va_list arg;
770 6f4d00ee 2013-09-23 0intro
771 6f4d00ee 2013-09-23 0intro va_start(arg, fmt);
772 6f4d00ee 2013-09-23 0intro vseprint(buf, buf+sizeof buf, fmt, arg);
773 6f4d00ee 2013-09-23 0intro va_end(arg);
774 6f4d00ee 2013-09-23 0intro
775 6f4d00ee 2013-09-23 0intro chk->print("error: %s\n", buf);
776 6f4d00ee 2013-09-23 0intro }
777 6f4d00ee 2013-09-23 0intro
778 6f4d00ee 2013-09-23 0intro static void
779 b32de4ae 2013-09-26 0intro clrenop(Fsck *chk, Block *b, int i)
780 6f4d00ee 2013-09-23 0intro {
781 b32de4ae 2013-09-26 0intro USED(chk);
782 b32de4ae 2013-09-26 0intro USED(b);
783 b32de4ae 2013-09-26 0intro USED(i);
784 6f4d00ee 2013-09-23 0intro }
785 6f4d00ee 2013-09-23 0intro
786 6f4d00ee 2013-09-23 0intro static void
787 b32de4ae 2013-09-26 0intro closenop(Fsck *chk, Block *b, u32int i)
788 6f4d00ee 2013-09-23 0intro {
789 b32de4ae 2013-09-26 0intro USED(chk);
790 b32de4ae 2013-09-26 0intro USED(b);
791 b32de4ae 2013-09-26 0intro USED(i);
792 6f4d00ee 2013-09-23 0intro }
793 6f4d00ee 2013-09-23 0intro
794 6f4d00ee 2013-09-23 0intro static void
795 b32de4ae 2013-09-26 0intro clrinop(Fsck *chk, char *c, MetaBlock *mb, int i, Block *b)
796 6f4d00ee 2013-09-23 0intro {
797 b32de4ae 2013-09-26 0intro USED(chk);
798 b32de4ae 2013-09-26 0intro USED(c);
799 b32de4ae 2013-09-26 0intro USED(mb);
800 b32de4ae 2013-09-26 0intro USED(i);
801 b32de4ae 2013-09-26 0intro USED(b);
802 6f4d00ee 2013-09-23 0intro }
803 6f4d00ee 2013-09-23 0intro
804 6f4d00ee 2013-09-23 0intro static int
805 b32de4ae 2013-09-26 0intro printnop(char *c, ...)
806 6f4d00ee 2013-09-23 0intro {
807 b32de4ae 2013-09-26 0intro USED(c);
808 6f4d00ee 2013-09-23 0intro return 0;
809 6f4d00ee 2013-09-23 0intro }