Blame


1 28b49df3 2006-07-18 devnull /*
2 28b49df3 2006-07-18 devnull * Check and fix an arena partition.
3 28b49df3 2006-07-18 devnull *
4 28b49df3 2006-07-18 devnull * This is a lot grittier than the rest of Venti because
5 28b49df3 2006-07-18 devnull * it can't just give up if a byte here or there is wrong.
6 28b49df3 2006-07-18 devnull *
7 28b49df3 2006-07-18 devnull * The rule here (hopefully followed!) is that block corruption
8 28b49df3 2006-07-18 devnull * only ever has a local effect -- there are no blocks that you
9 fa325e9b 2020-01-10 cross * can wipe out that will cause large portions of
10 28b49df3 2006-07-18 devnull * uncorrupted data blocks to be useless.
11 28b49df3 2006-07-18 devnull */
12 28b49df3 2006-07-18 devnull
13 28b49df3 2006-07-18 devnull #include "stdinc.h"
14 28b49df3 2006-07-18 devnull #include "dat.h"
15 28b49df3 2006-07-18 devnull #include "fns.h"
16 28b49df3 2006-07-18 devnull #include "whack.h"
17 67a65bba 2007-09-25 rsc
18 67a65bba 2007-09-25 rsc #define ROUNDUP(x,n) (((x)+(n)-1)&~((n)-1))
19 28b49df3 2006-07-18 devnull
20 28b49df3 2006-07-18 devnull #pragma varargck type "z" uvlong
21 28b49df3 2006-07-18 devnull #pragma varargck type "z" vlong
22 28b49df3 2006-07-18 devnull #pragma varargck type "t" uint
23 28b49df3 2006-07-18 devnull
24 28b49df3 2006-07-18 devnull enum
25 28b49df3 2006-07-18 devnull {
26 28b49df3 2006-07-18 devnull K = 1024,
27 28b49df3 2006-07-18 devnull M = 1024*1024,
28 28b49df3 2006-07-18 devnull G = 1024*1024*1024,
29 fa325e9b 2020-01-10 cross
30 28b49df3 2006-07-18 devnull Block = 4096,
31 28b49df3 2006-07-18 devnull };
32 28b49df3 2006-07-18 devnull
33 28b49df3 2006-07-18 devnull int debugsha1;
34 28b49df3 2006-07-18 devnull
35 28b49df3 2006-07-18 devnull int verbose;
36 28b49df3 2006-07-18 devnull Part *part;
37 28b49df3 2006-07-18 devnull char *file;
38 28b49df3 2006-07-18 devnull char *basename;
39 28b49df3 2006-07-18 devnull char *dumpbase;
40 28b49df3 2006-07-18 devnull int fix;
41 28b49df3 2006-07-18 devnull int badreads;
42 28b49df3 2006-07-18 devnull int unseal;
43 28b49df3 2006-07-18 devnull uchar zero[MaxDiskBlock];
44 28b49df3 2006-07-18 devnull
45 28b49df3 2006-07-18 devnull Arena lastarena;
46 28b49df3 2006-07-18 devnull ArenaPart ap;
47 28b49df3 2006-07-18 devnull uvlong arenasize;
48 28b49df3 2006-07-18 devnull int nbadread;
49 28b49df3 2006-07-18 devnull int nbad;
50 28b49df3 2006-07-18 devnull uvlong partend;
51 28b49df3 2006-07-18 devnull void checkarena(vlong, int);
52 28b49df3 2006-07-18 devnull
53 28b49df3 2006-07-18 devnull void
54 28b49df3 2006-07-18 devnull usage(void)
55 28b49df3 2006-07-18 devnull {
56 28b49df3 2006-07-18 devnull fprint(2, "usage: fixarenas [-fv] [-a arenasize] [-b blocksize] file [ranges]\n");
57 28b49df3 2006-07-18 devnull threadexitsall(0);
58 28b49df3 2006-07-18 devnull }
59 28b49df3 2006-07-18 devnull
60 28b49df3 2006-07-18 devnull /*
61 28b49df3 2006-07-18 devnull * Format number in simplest way that is okay with unittoull.
62 28b49df3 2006-07-18 devnull */
63 28b49df3 2006-07-18 devnull static int
64 28b49df3 2006-07-18 devnull zfmt(Fmt *fmt)
65 28b49df3 2006-07-18 devnull {
66 28b49df3 2006-07-18 devnull vlong x;
67 fa325e9b 2020-01-10 cross
68 28b49df3 2006-07-18 devnull x = va_arg(fmt->args, vlong);
69 28b49df3 2006-07-18 devnull if(x == 0)
70 28b49df3 2006-07-18 devnull return fmtstrcpy(fmt, "0");
71 28b49df3 2006-07-18 devnull if(x%G == 0)
72 28b49df3 2006-07-18 devnull return fmtprint(fmt, "%lldG", x/G);
73 28b49df3 2006-07-18 devnull if(x%M == 0)
74 28b49df3 2006-07-18 devnull return fmtprint(fmt, "%lldM", x/M);
75 28b49df3 2006-07-18 devnull if(x%K == 0)
76 28b49df3 2006-07-18 devnull return fmtprint(fmt, "%lldK", x/K);
77 28b49df3 2006-07-18 devnull return fmtprint(fmt, "%lld", x);
78 28b49df3 2006-07-18 devnull }
79 28b49df3 2006-07-18 devnull
80 28b49df3 2006-07-18 devnull /*
81 28b49df3 2006-07-18 devnull * Format time like ctime without newline.
82 28b49df3 2006-07-18 devnull */
83 28b49df3 2006-07-18 devnull static int
84 28b49df3 2006-07-18 devnull tfmt(Fmt *fmt)
85 28b49df3 2006-07-18 devnull {
86 28b49df3 2006-07-18 devnull uint t;
87 28b49df3 2006-07-18 devnull char buf[30];
88 fa325e9b 2020-01-10 cross
89 28b49df3 2006-07-18 devnull t = va_arg(fmt->args, uint);
90 28b49df3 2006-07-18 devnull strcpy(buf, ctime(t));
91 28b49df3 2006-07-18 devnull buf[28] = 0;
92 28b49df3 2006-07-18 devnull return fmtstrcpy(fmt, buf);
93 28b49df3 2006-07-18 devnull }
94 28b49df3 2006-07-18 devnull
95 28b49df3 2006-07-18 devnull /*
96 28b49df3 2006-07-18 devnull * Coalesce messages about unreadable sectors into larger ranges.
97 28b49df3 2006-07-18 devnull * bad(0, 0) flushes the buffer.
98 28b49df3 2006-07-18 devnull */
99 28b49df3 2006-07-18 devnull static void
100 28b49df3 2006-07-18 devnull bad(char *msg, vlong o, int len)
101 28b49df3 2006-07-18 devnull {
102 28b49df3 2006-07-18 devnull static vlong lb0, lb1;
103 28b49df3 2006-07-18 devnull static char *lmsg;
104 28b49df3 2006-07-18 devnull
105 28b49df3 2006-07-18 devnull if(msg == nil)
106 28b49df3 2006-07-18 devnull msg = lmsg;
107 28b49df3 2006-07-18 devnull if(o == -1){
108 28b49df3 2006-07-18 devnull lmsg = nil;
109 28b49df3 2006-07-18 devnull lb0 = 0;
110 28b49df3 2006-07-18 devnull lb1 = 0;
111 28b49df3 2006-07-18 devnull return;
112 28b49df3 2006-07-18 devnull }
113 28b49df3 2006-07-18 devnull if(lb1 != o || (msg && lmsg && strcmp(msg, lmsg) != 0)){
114 28b49df3 2006-07-18 devnull if(lb0 != lb1)
115 28b49df3 2006-07-18 devnull print("%s %#llux+%#llux (%,lld+%,lld)\n",
116 28b49df3 2006-07-18 devnull lmsg, lb0, lb1-lb0, lb0, lb1-lb0);
117 28b49df3 2006-07-18 devnull lb0 = o;
118 28b49df3 2006-07-18 devnull }
119 28b49df3 2006-07-18 devnull lmsg = msg;
120 28b49df3 2006-07-18 devnull lb1 = o+len;
121 28b49df3 2006-07-18 devnull }
122 28b49df3 2006-07-18 devnull
123 28b49df3 2006-07-18 devnull /*
124 28b49df3 2006-07-18 devnull * Read in the len bytes of data at the offset. If can't for whatever reason,
125 28b49df3 2006-07-18 devnull * fill it with garbage but print an error.
126 28b49df3 2006-07-18 devnull */
127 28b49df3 2006-07-18 devnull static uchar*
128 28b49df3 2006-07-18 devnull readdisk(uchar *buf, vlong offset, int len)
129 28b49df3 2006-07-18 devnull {
130 28b49df3 2006-07-18 devnull int i, j, k, n;
131 28b49df3 2006-07-18 devnull
132 28b49df3 2006-07-18 devnull if(offset >= partend){
133 0cfb3760 2012-10-21 rsc memset(buf, 0xFB, len);
134 28b49df3 2006-07-18 devnull return buf;
135 28b49df3 2006-07-18 devnull }
136 fa325e9b 2020-01-10 cross
137 28b49df3 2006-07-18 devnull if(offset+len > partend){
138 0cfb3760 2012-10-21 rsc memset(buf, 0xFB, len);
139 28b49df3 2006-07-18 devnull len = partend - offset;
140 28b49df3 2006-07-18 devnull }
141 28b49df3 2006-07-18 devnull
142 28b49df3 2006-07-18 devnull if(readpart(part, offset, buf, len) >= 0)
143 28b49df3 2006-07-18 devnull return buf;
144 fa325e9b 2020-01-10 cross
145 28b49df3 2006-07-18 devnull /*
146 28b49df3 2006-07-18 devnull * The read failed. Clear the buffer to nonsense, and
147 28b49df3 2006-07-18 devnull * then try reading in smaller pieces. If that fails,
148 28b49df3 2006-07-18 devnull * read in even smaller pieces. And so on down to sectors.
149 28b49df3 2006-07-18 devnull */
150 28b49df3 2006-07-18 devnull memset(buf, 0xFD, len);
151 28b49df3 2006-07-18 devnull for(i=0; i<len; i+=64*K){
152 28b49df3 2006-07-18 devnull n = 64*K;
153 28b49df3 2006-07-18 devnull if(i+n > len)
154 28b49df3 2006-07-18 devnull n = len-i;
155 28b49df3 2006-07-18 devnull if(readpart(part, offset+i, buf+i, n) >= 0)
156 28b49df3 2006-07-18 devnull continue;
157 28b49df3 2006-07-18 devnull for(j=i; j<len && j<i+64*K; j+=4*K){
158 28b49df3 2006-07-18 devnull n = 4*K;
159 28b49df3 2006-07-18 devnull if(j+n > len)
160 28b49df3 2006-07-18 devnull n = len-j;
161 28b49df3 2006-07-18 devnull if(readpart(part, offset+j, buf+j, n) >= 0)
162 28b49df3 2006-07-18 devnull continue;
163 28b49df3 2006-07-18 devnull for(k=j; k<len && k<j+4*K; k+=512){
164 28b49df3 2006-07-18 devnull if(readpart(part, offset+k, buf+k, 512) >= 0)
165 28b49df3 2006-07-18 devnull continue;
166 28b49df3 2006-07-18 devnull bad("disk read failed at", k, 512);
167 28b49df3 2006-07-18 devnull badreads++;
168 28b49df3 2006-07-18 devnull }
169 28b49df3 2006-07-18 devnull }
170 28b49df3 2006-07-18 devnull }
171 28b49df3 2006-07-18 devnull bad(nil, 0, 0);
172 28b49df3 2006-07-18 devnull return buf;
173 28b49df3 2006-07-18 devnull }
174 28b49df3 2006-07-18 devnull
175 28b49df3 2006-07-18 devnull /*
176 28b49df3 2006-07-18 devnull * Buffer to support running SHA1 hash of the disk.
177 28b49df3 2006-07-18 devnull */
178 28b49df3 2006-07-18 devnull typedef struct Shabuf Shabuf;
179 28b49df3 2006-07-18 devnull struct Shabuf
180 28b49df3 2006-07-18 devnull {
181 28b49df3 2006-07-18 devnull int fd;
182 28b49df3 2006-07-18 devnull vlong offset;
183 28b49df3 2006-07-18 devnull DigestState state;
184 28b49df3 2006-07-18 devnull int rollback;
185 28b49df3 2006-07-18 devnull vlong r0;
186 28b49df3 2006-07-18 devnull DigestState *hist;
187 28b49df3 2006-07-18 devnull int nhist;
188 28b49df3 2006-07-18 devnull };
189 28b49df3 2006-07-18 devnull
190 28b49df3 2006-07-18 devnull void
191 28b49df3 2006-07-18 devnull sbdebug(Shabuf *sb, char *file)
192 28b49df3 2006-07-18 devnull {
193 28b49df3 2006-07-18 devnull int fd;
194 fa325e9b 2020-01-10 cross
195 28b49df3 2006-07-18 devnull if(sb->fd > 0){
196 28b49df3 2006-07-18 devnull close(sb->fd);
197 28b49df3 2006-07-18 devnull sb->fd = 0;
198 28b49df3 2006-07-18 devnull }
199 28b49df3 2006-07-18 devnull if((fd = create(file, OWRITE, 0666)) < 0)
200 28b49df3 2006-07-18 devnull return;
201 28b49df3 2006-07-18 devnull if(fd == 0){
202 28b49df3 2006-07-18 devnull fd = dup(fd, -1);
203 28b49df3 2006-07-18 devnull close(0);
204 28b49df3 2006-07-18 devnull }
205 28b49df3 2006-07-18 devnull sb->fd = fd;
206 28b49df3 2006-07-18 devnull }
207 28b49df3 2006-07-18 devnull
208 28b49df3 2006-07-18 devnull void
209 28b49df3 2006-07-18 devnull sbupdate(Shabuf *sb, uchar *p, vlong offset, int len)
210 28b49df3 2006-07-18 devnull {
211 28b49df3 2006-07-18 devnull int n, x;
212 28b49df3 2006-07-18 devnull vlong o;
213 28b49df3 2006-07-18 devnull
214 28b49df3 2006-07-18 devnull if(sb->rollback && !sb->hist){
215 28b49df3 2006-07-18 devnull sb->r0 = offset;
216 28b49df3 2006-07-18 devnull sb->nhist = 1;
217 28b49df3 2006-07-18 devnull sb->hist = vtmalloc(sb->nhist*sizeof *sb->hist);
218 28b49df3 2006-07-18 devnull memset(sb->hist, 0, sizeof sb->hist[0]);
219 28b49df3 2006-07-18 devnull }
220 28b49df3 2006-07-18 devnull if(sb->r0 == 0)
221 28b49df3 2006-07-18 devnull sb->r0 = offset;
222 28b49df3 2006-07-18 devnull
223 28b49df3 2006-07-18 devnull if(sb->offset < offset || sb->offset >= offset+len){
224 28b49df3 2006-07-18 devnull if(0) print("sbupdate %p %#llux+%d but offset=%#llux\n",
225 28b49df3 2006-07-18 devnull p, offset, len, sb->offset);
226 28b49df3 2006-07-18 devnull return;
227 28b49df3 2006-07-18 devnull }
228 28b49df3 2006-07-18 devnull x = sb->offset - offset;
229 28b49df3 2006-07-18 devnull if(0) print("sbupdate %p %#llux+%d skip %d\n",
230 28b49df3 2006-07-18 devnull sb, offset, len, x);
231 28b49df3 2006-07-18 devnull if(x){
232 28b49df3 2006-07-18 devnull p += x;
233 28b49df3 2006-07-18 devnull offset += x;
234 28b49df3 2006-07-18 devnull len -= x;
235 28b49df3 2006-07-18 devnull }
236 28b49df3 2006-07-18 devnull assert(sb->offset == offset);
237 fa325e9b 2020-01-10 cross
238 28b49df3 2006-07-18 devnull if(sb->fd > 0)
239 28b49df3 2006-07-18 devnull pwrite(sb->fd, p, len, offset - sb->r0);
240 28b49df3 2006-07-18 devnull
241 28b49df3 2006-07-18 devnull if(!sb->rollback){
242 28b49df3 2006-07-18 devnull sha1(p, len, nil, &sb->state);
243 28b49df3 2006-07-18 devnull sb->offset += len;
244 28b49df3 2006-07-18 devnull return;
245 28b49df3 2006-07-18 devnull }
246 fa325e9b 2020-01-10 cross
247 28b49df3 2006-07-18 devnull /* save state every 4M so we can roll back quickly */
248 28b49df3 2006-07-18 devnull o = offset - sb->r0;
249 28b49df3 2006-07-18 devnull while(len > 0){
250 28b49df3 2006-07-18 devnull n = 4*M - o%(4*M);
251 28b49df3 2006-07-18 devnull if(n > len)
252 28b49df3 2006-07-18 devnull n = len;
253 28b49df3 2006-07-18 devnull sha1(p, n, nil, &sb->state);
254 28b49df3 2006-07-18 devnull sb->offset += n;
255 28b49df3 2006-07-18 devnull o += n;
256 28b49df3 2006-07-18 devnull p += n;
257 28b49df3 2006-07-18 devnull len -= n;
258 28b49df3 2006-07-18 devnull if(o%(4*M) == 0){
259 28b49df3 2006-07-18 devnull x = o/(4*M);
260 28b49df3 2006-07-18 devnull if(x >= sb->nhist){
261 28b49df3 2006-07-18 devnull if(x != sb->nhist)
262 28b49df3 2006-07-18 devnull print("oops! x=%d nhist=%d\n", x, sb->nhist);
263 28b49df3 2006-07-18 devnull sb->nhist += 32;
264 28b49df3 2006-07-18 devnull sb->hist = vtrealloc(sb->hist, sb->nhist*sizeof *sb->hist);
265 28b49df3 2006-07-18 devnull }
266 28b49df3 2006-07-18 devnull sb->hist[x] = sb->state;
267 28b49df3 2006-07-18 devnull }
268 fa325e9b 2020-01-10 cross }
269 28b49df3 2006-07-18 devnull }
270 28b49df3 2006-07-18 devnull
271 28b49df3 2006-07-18 devnull void
272 28b49df3 2006-07-18 devnull sbdiskhash(Shabuf *sb, vlong eoffset)
273 28b49df3 2006-07-18 devnull {
274 28b49df3 2006-07-18 devnull static uchar dbuf[4*M];
275 28b49df3 2006-07-18 devnull int n;
276 fa325e9b 2020-01-10 cross
277 28b49df3 2006-07-18 devnull while(sb->offset < eoffset){
278 28b49df3 2006-07-18 devnull n = sizeof dbuf;
279 28b49df3 2006-07-18 devnull if(sb->offset+n > eoffset)
280 28b49df3 2006-07-18 devnull n = eoffset - sb->offset;
281 28b49df3 2006-07-18 devnull readdisk(dbuf, sb->offset, n);
282 28b49df3 2006-07-18 devnull sbupdate(sb, dbuf, sb->offset, n);
283 28b49df3 2006-07-18 devnull }
284 28b49df3 2006-07-18 devnull }
285 28b49df3 2006-07-18 devnull
286 28b49df3 2006-07-18 devnull void
287 28b49df3 2006-07-18 devnull sbrollback(Shabuf *sb, vlong offset)
288 28b49df3 2006-07-18 devnull {
289 28b49df3 2006-07-18 devnull int x;
290 28b49df3 2006-07-18 devnull vlong o;
291 28b49df3 2006-07-18 devnull Dir d;
292 fa325e9b 2020-01-10 cross
293 28b49df3 2006-07-18 devnull if(!sb->rollback || !sb->r0){
294 28b49df3 2006-07-18 devnull print("cannot rollback sha\n");
295 28b49df3 2006-07-18 devnull return;
296 28b49df3 2006-07-18 devnull }
297 28b49df3 2006-07-18 devnull if(offset >= sb->offset)
298 28b49df3 2006-07-18 devnull return;
299 28b49df3 2006-07-18 devnull o = offset - sb->r0;
300 28b49df3 2006-07-18 devnull x = o/(4*M);
301 28b49df3 2006-07-18 devnull if(x >= sb->nhist){
302 28b49df3 2006-07-18 devnull print("cannot rollback sha\n");
303 28b49df3 2006-07-18 devnull return;
304 28b49df3 2006-07-18 devnull }
305 28b49df3 2006-07-18 devnull sb->state = sb->hist[x];
306 28b49df3 2006-07-18 devnull sb->offset = sb->r0 + x*4*M;
307 28b49df3 2006-07-18 devnull assert(sb->offset <= offset);
308 fa325e9b 2020-01-10 cross
309 28b49df3 2006-07-18 devnull if(sb->fd > 0){
310 28b49df3 2006-07-18 devnull nulldir(&d);
311 28b49df3 2006-07-18 devnull d.length = sb->offset - sb->r0;
312 28b49df3 2006-07-18 devnull dirfwstat(sb->fd, &d);
313 28b49df3 2006-07-18 devnull }
314 28b49df3 2006-07-18 devnull }
315 28b49df3 2006-07-18 devnull
316 28b49df3 2006-07-18 devnull void
317 28b49df3 2006-07-18 devnull sbscore(Shabuf *sb, uchar *score)
318 28b49df3 2006-07-18 devnull {
319 28b49df3 2006-07-18 devnull if(sb->hist){
320 28b49df3 2006-07-18 devnull free(sb->hist);
321 28b49df3 2006-07-18 devnull sb->hist = nil;
322 28b49df3 2006-07-18 devnull }
323 28b49df3 2006-07-18 devnull sha1(nil, 0, score, &sb->state);
324 28b49df3 2006-07-18 devnull }
325 28b49df3 2006-07-18 devnull
326 28b49df3 2006-07-18 devnull /*
327 28b49df3 2006-07-18 devnull * If we're fixing arenas, then editing this memory edits the disk!
328 fa325e9b 2020-01-10 cross * It will be written back out as new data is paged in.
329 28b49df3 2006-07-18 devnull */
330 28b49df3 2006-07-18 devnull uchar buf[4*M];
331 28b49df3 2006-07-18 devnull uchar sbuf[4*M];
332 28b49df3 2006-07-18 devnull vlong bufoffset;
333 28b49df3 2006-07-18 devnull int buflen;
334 28b49df3 2006-07-18 devnull
335 28b49df3 2006-07-18 devnull static void pageout(void);
336 28b49df3 2006-07-18 devnull static uchar*
337 28b49df3 2006-07-18 devnull pagein(vlong offset, int len)
338 28b49df3 2006-07-18 devnull {
339 28b49df3 2006-07-18 devnull pageout();
340 28b49df3 2006-07-18 devnull if(offset >= partend){
341 28b49df3 2006-07-18 devnull memset(buf, 0xFB, sizeof buf);
342 28b49df3 2006-07-18 devnull return buf;
343 28b49df3 2006-07-18 devnull }
344 fa325e9b 2020-01-10 cross
345 28b49df3 2006-07-18 devnull if(offset+len > partend){
346 28b49df3 2006-07-18 devnull memset(buf, 0xFB, sizeof buf);
347 28b49df3 2006-07-18 devnull len = partend - offset;
348 28b49df3 2006-07-18 devnull }
349 28b49df3 2006-07-18 devnull bufoffset = offset;
350 28b49df3 2006-07-18 devnull buflen = len;
351 28b49df3 2006-07-18 devnull readdisk(buf, offset, len);
352 28b49df3 2006-07-18 devnull memmove(sbuf, buf, len);
353 28b49df3 2006-07-18 devnull return buf;
354 28b49df3 2006-07-18 devnull }
355 28b49df3 2006-07-18 devnull
356 28b49df3 2006-07-18 devnull static void
357 28b49df3 2006-07-18 devnull pageout(void)
358 28b49df3 2006-07-18 devnull {
359 28b49df3 2006-07-18 devnull if(buflen==0 || !fix || memcmp(buf, sbuf, buflen) == 0){
360 28b49df3 2006-07-18 devnull buflen = 0;
361 28b49df3 2006-07-18 devnull return;
362 28b49df3 2006-07-18 devnull }
363 28b49df3 2006-07-18 devnull if(writepart(part, bufoffset, buf, buflen) < 0)
364 28b49df3 2006-07-18 devnull print("disk write failed at %#llux+%#ux (%,lld+%,d)\n",
365 28b49df3 2006-07-18 devnull bufoffset, buflen, bufoffset, buflen);
366 28b49df3 2006-07-18 devnull buflen = 0;
367 28b49df3 2006-07-18 devnull }
368 28b49df3 2006-07-18 devnull
369 28b49df3 2006-07-18 devnull static void
370 28b49df3 2006-07-18 devnull zerorange(vlong offset, int len)
371 28b49df3 2006-07-18 devnull {
372 28b49df3 2006-07-18 devnull int i;
373 28b49df3 2006-07-18 devnull vlong ooff;
374 28b49df3 2006-07-18 devnull int olen;
375 28b49df3 2006-07-18 devnull enum { MinBlock = 4*K, MaxBlock = 8*K };
376 fa325e9b 2020-01-10 cross
377 28b49df3 2006-07-18 devnull if(0)
378 28b49df3 2006-07-18 devnull if(bufoffset <= offset && offset+len <= bufoffset+buflen){
379 28b49df3 2006-07-18 devnull memset(buf+(offset-bufoffset), 0, len);
380 28b49df3 2006-07-18 devnull return;
381 28b49df3 2006-07-18 devnull }
382 fa325e9b 2020-01-10 cross
383 28b49df3 2006-07-18 devnull ooff = bufoffset;
384 28b49df3 2006-07-18 devnull olen = buflen;
385 fa325e9b 2020-01-10 cross
386 28b49df3 2006-07-18 devnull i = offset%MinBlock;
387 28b49df3 2006-07-18 devnull if(i+len < MaxBlock){
388 28b49df3 2006-07-18 devnull pagein(offset-i, (len+MinBlock-1)&~(MinBlock-1));
389 28b49df3 2006-07-18 devnull memset(buf+i, 0, len);
390 28b49df3 2006-07-18 devnull }else{
391 28b49df3 2006-07-18 devnull pagein(offset-i, MaxBlock);
392 28b49df3 2006-07-18 devnull memset(buf+i, 0, MaxBlock-i);
393 28b49df3 2006-07-18 devnull offset += MaxBlock-i;
394 28b49df3 2006-07-18 devnull len -= MaxBlock-i;
395 28b49df3 2006-07-18 devnull while(len >= MaxBlock){
396 28b49df3 2006-07-18 devnull pagein(offset, MaxBlock);
397 28b49df3 2006-07-18 devnull memset(buf, 0, MaxBlock);
398 28b49df3 2006-07-18 devnull offset += MaxBlock;
399 28b49df3 2006-07-18 devnull len -= MaxBlock;
400 28b49df3 2006-07-18 devnull }
401 28b49df3 2006-07-18 devnull pagein(offset, (len+MinBlock-1)&~(MinBlock-1));
402 28b49df3 2006-07-18 devnull memset(buf, 0, len);
403 28b49df3 2006-07-18 devnull }
404 28b49df3 2006-07-18 devnull pagein(ooff, olen);
405 28b49df3 2006-07-18 devnull }
406 28b49df3 2006-07-18 devnull
407 28b49df3 2006-07-18 devnull /*
408 28b49df3 2006-07-18 devnull * read/write integers
409 28b49df3 2006-07-18 devnull *
410 28b49df3 2006-07-18 devnull static void
411 28b49df3 2006-07-18 devnull p16(uchar *p, u16int u)
412 28b49df3 2006-07-18 devnull {
413 28b49df3 2006-07-18 devnull p[0] = (u>>8) & 0xFF;
414 28b49df3 2006-07-18 devnull p[1] = u & 0xFF;
415 28b49df3 2006-07-18 devnull }
416 28b49df3 2006-07-18 devnull */
417 28b49df3 2006-07-18 devnull
418 28b49df3 2006-07-18 devnull static u16int
419 28b49df3 2006-07-18 devnull u16(uchar *p)
420 28b49df3 2006-07-18 devnull {
421 28b49df3 2006-07-18 devnull return (p[0]<<8)|p[1];
422 28b49df3 2006-07-18 devnull }
423 28b49df3 2006-07-18 devnull
424 28b49df3 2006-07-18 devnull static void
425 28b49df3 2006-07-18 devnull p32(uchar *p, u32int u)
426 28b49df3 2006-07-18 devnull {
427 28b49df3 2006-07-18 devnull p[0] = (u>>24) & 0xFF;
428 28b49df3 2006-07-18 devnull p[1] = (u>>16) & 0xFF;
429 28b49df3 2006-07-18 devnull p[2] = (u>>8) & 0xFF;
430 28b49df3 2006-07-18 devnull p[3] = u & 0xFF;
431 28b49df3 2006-07-18 devnull }
432 28b49df3 2006-07-18 devnull
433 28b49df3 2006-07-18 devnull static u32int
434 28b49df3 2006-07-18 devnull u32(uchar *p)
435 28b49df3 2006-07-18 devnull {
436 28b49df3 2006-07-18 devnull return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];
437 28b49df3 2006-07-18 devnull }
438 28b49df3 2006-07-18 devnull
439 28b49df3 2006-07-18 devnull /*
440 28b49df3 2006-07-18 devnull static void
441 28b49df3 2006-07-18 devnull p64(uchar *p, u64int u)
442 28b49df3 2006-07-18 devnull {
443 28b49df3 2006-07-18 devnull p32(p, u>>32);
444 28b49df3 2006-07-18 devnull p32(p, u);
445 28b49df3 2006-07-18 devnull }
446 28b49df3 2006-07-18 devnull */
447 28b49df3 2006-07-18 devnull
448 28b49df3 2006-07-18 devnull static u64int
449 28b49df3 2006-07-18 devnull u64(uchar *p)
450 28b49df3 2006-07-18 devnull {
451 28b49df3 2006-07-18 devnull return ((u64int)u32(p)<<32) | u32(p+4);
452 28b49df3 2006-07-18 devnull }
453 28b49df3 2006-07-18 devnull
454 28b49df3 2006-07-18 devnull static int
455 28b49df3 2006-07-18 devnull vlongcmp(const void *va, const void *vb)
456 28b49df3 2006-07-18 devnull {
457 28b49df3 2006-07-18 devnull vlong a, b;
458 fa325e9b 2020-01-10 cross
459 28b49df3 2006-07-18 devnull a = *(vlong*)va;
460 28b49df3 2006-07-18 devnull b = *(vlong*)vb;
461 28b49df3 2006-07-18 devnull if(a < b)
462 28b49df3 2006-07-18 devnull return -1;
463 28b49df3 2006-07-18 devnull if(b > a)
464 28b49df3 2006-07-18 devnull return 1;
465 28b49df3 2006-07-18 devnull return 0;
466 28b49df3 2006-07-18 devnull }
467 28b49df3 2006-07-18 devnull
468 28b49df3 2006-07-18 devnull /* D and S are in draw.h */
469 28b49df3 2006-07-18 devnull #define D VD
470 28b49df3 2006-07-18 devnull #define S VS
471 28b49df3 2006-07-18 devnull
472 28b49df3 2006-07-18 devnull enum
473 28b49df3 2006-07-18 devnull {
474 28b49df3 2006-07-18 devnull D = 0x10000,
475 28b49df3 2006-07-18 devnull Z = 0x20000,
476 28b49df3 2006-07-18 devnull S = 0x30000,
477 28b49df3 2006-07-18 devnull T = 0x40000,
478 28b49df3 2006-07-18 devnull N = 0xFFFF
479 28b49df3 2006-07-18 devnull };
480 28b49df3 2006-07-18 devnull typedef struct Info Info;
481 28b49df3 2006-07-18 devnull struct Info
482 28b49df3 2006-07-18 devnull {
483 28b49df3 2006-07-18 devnull int len;
484 28b49df3 2006-07-18 devnull char *name;
485 28b49df3 2006-07-18 devnull };
486 28b49df3 2006-07-18 devnull
487 28b49df3 2006-07-18 devnull Info partinfo[] = {
488 28b49df3 2006-07-18 devnull 4, "magic",
489 28b49df3 2006-07-18 devnull D|4, "version",
490 28b49df3 2006-07-18 devnull Z|4, "blocksize",
491 28b49df3 2006-07-18 devnull 4, "arenabase",
492 28b49df3 2006-07-18 devnull 0
493 28b49df3 2006-07-18 devnull };
494 28b49df3 2006-07-18 devnull
495 28b49df3 2006-07-18 devnull Info headinfo4[] = {
496 28b49df3 2006-07-18 devnull 4, "magic",
497 28b49df3 2006-07-18 devnull D|4, "version",
498 28b49df3 2006-07-18 devnull S|ANameSize, "name",
499 28b49df3 2006-07-18 devnull Z|4, "blocksize",
500 28b49df3 2006-07-18 devnull Z|8, "size",
501 28b49df3 2006-07-18 devnull 0
502 28b49df3 2006-07-18 devnull };
503 28b49df3 2006-07-18 devnull
504 28b49df3 2006-07-18 devnull Info headinfo5[] = {
505 28b49df3 2006-07-18 devnull 4, "magic",
506 28b49df3 2006-07-18 devnull D|4, "version",
507 28b49df3 2006-07-18 devnull S|ANameSize, "name",
508 28b49df3 2006-07-18 devnull Z|4, "blocksize",
509 28b49df3 2006-07-18 devnull Z|8, "size",
510 28b49df3 2006-07-18 devnull 4, "clumpmagic",
511 28b49df3 2006-07-18 devnull 0
512 28b49df3 2006-07-18 devnull };
513 28b49df3 2006-07-18 devnull
514 28b49df3 2006-07-18 devnull Info tailinfo4[] = {
515 28b49df3 2006-07-18 devnull 4, "magic",
516 28b49df3 2006-07-18 devnull D|4, "version",
517 28b49df3 2006-07-18 devnull S|ANameSize, "name",
518 28b49df3 2006-07-18 devnull D|4, "clumps",
519 28b49df3 2006-07-18 devnull D|4, "cclumps",
520 28b49df3 2006-07-18 devnull T|4, "ctime",
521 28b49df3 2006-07-18 devnull T|4, "wtime",
522 28b49df3 2006-07-18 devnull D|8, "used",
523 28b49df3 2006-07-18 devnull D|8, "uncsize",
524 28b49df3 2006-07-18 devnull 1, "sealed",
525 28b49df3 2006-07-18 devnull 0
526 28b49df3 2006-07-18 devnull };
527 fa325e9b 2020-01-10 cross
528 28b49df3 2006-07-18 devnull Info tailinfo4a[] = {
529 28b49df3 2006-07-18 devnull /* tailinfo 4 */
530 28b49df3 2006-07-18 devnull 4, "magic",
531 28b49df3 2006-07-18 devnull D|4, "version",
532 28b49df3 2006-07-18 devnull S|ANameSize, "name",
533 28b49df3 2006-07-18 devnull D|4, "clumps",
534 28b49df3 2006-07-18 devnull D|4, "cclumps",
535 28b49df3 2006-07-18 devnull T|4, "ctime",
536 28b49df3 2006-07-18 devnull T|4, "wtime",
537 28b49df3 2006-07-18 devnull D|8, "used",
538 28b49df3 2006-07-18 devnull D|8, "uncsize",
539 28b49df3 2006-07-18 devnull 1, "sealed",
540 28b49df3 2006-07-18 devnull
541 28b49df3 2006-07-18 devnull /* mem stats */
542 28b49df3 2006-07-18 devnull 1, "extension",
543 28b49df3 2006-07-18 devnull D|4, "mem.clumps",
544 28b49df3 2006-07-18 devnull D|4, "mem.cclumps",
545 28b49df3 2006-07-18 devnull D|8, "mem.used",
546 28b49df3 2006-07-18 devnull D|8, "mem.uncsize",
547 28b49df3 2006-07-18 devnull 1, "mem.sealed",
548 28b49df3 2006-07-18 devnull 0
549 28b49df3 2006-07-18 devnull };
550 fa325e9b 2020-01-10 cross
551 28b49df3 2006-07-18 devnull Info tailinfo5[] = {
552 28b49df3 2006-07-18 devnull 4, "magic",
553 28b49df3 2006-07-18 devnull D|4, "version",
554 28b49df3 2006-07-18 devnull S|ANameSize, "name",
555 28b49df3 2006-07-18 devnull D|4, "clumps",
556 28b49df3 2006-07-18 devnull D|4, "cclumps",
557 28b49df3 2006-07-18 devnull T|4, "ctime",
558 28b49df3 2006-07-18 devnull T|4, "wtime",
559 28b49df3 2006-07-18 devnull 4, "clumpmagic",
560 28b49df3 2006-07-18 devnull D|8, "used",
561 28b49df3 2006-07-18 devnull D|8, "uncsize",
562 28b49df3 2006-07-18 devnull 1, "sealed",
563 28b49df3 2006-07-18 devnull 0
564 28b49df3 2006-07-18 devnull };
565 28b49df3 2006-07-18 devnull
566 28b49df3 2006-07-18 devnull Info tailinfo5a[] = {
567 28b49df3 2006-07-18 devnull /* tailinfo 5 */
568 28b49df3 2006-07-18 devnull 4, "magic",
569 28b49df3 2006-07-18 devnull D|4, "version",
570 28b49df3 2006-07-18 devnull S|ANameSize, "name",
571 28b49df3 2006-07-18 devnull D|4, "clumps",
572 28b49df3 2006-07-18 devnull D|4, "cclumps",
573 28b49df3 2006-07-18 devnull T|4, "ctime",
574 28b49df3 2006-07-18 devnull T|4, "wtime",
575 28b49df3 2006-07-18 devnull 4, "clumpmagic",
576 28b49df3 2006-07-18 devnull D|8, "used",
577 28b49df3 2006-07-18 devnull D|8, "uncsize",
578 28b49df3 2006-07-18 devnull 1, "sealed",
579 28b49df3 2006-07-18 devnull
580 28b49df3 2006-07-18 devnull /* mem stats */
581 28b49df3 2006-07-18 devnull 1, "extension",
582 28b49df3 2006-07-18 devnull D|4, "mem.clumps",
583 28b49df3 2006-07-18 devnull D|4, "mem.cclumps",
584 28b49df3 2006-07-18 devnull D|8, "mem.used",
585 28b49df3 2006-07-18 devnull D|8, "mem.uncsize",
586 28b49df3 2006-07-18 devnull 1, "mem.sealed",
587 28b49df3 2006-07-18 devnull 0
588 28b49df3 2006-07-18 devnull };
589 fa325e9b 2020-01-10 cross
590 28b49df3 2006-07-18 devnull void
591 28b49df3 2006-07-18 devnull showdiffs(uchar *want, uchar *have, int len, Info *info)
592 28b49df3 2006-07-18 devnull {
593 28b49df3 2006-07-18 devnull int n;
594 fa325e9b 2020-01-10 cross
595 28b49df3 2006-07-18 devnull while(len > 0 && (n=info->len&N) > 0){
596 28b49df3 2006-07-18 devnull if(memcmp(have, want, n) != 0){
597 28b49df3 2006-07-18 devnull switch(info->len){
598 28b49df3 2006-07-18 devnull case 1:
599 28b49df3 2006-07-18 devnull print("\t%s: correct=%d disk=%d\n",
600 28b49df3 2006-07-18 devnull info->name, *want, *have);
601 28b49df3 2006-07-18 devnull break;
602 28b49df3 2006-07-18 devnull case 4:
603 28b49df3 2006-07-18 devnull print("\t%s: correct=%#ux disk=%#ux\n",
604 28b49df3 2006-07-18 devnull info->name, u32(want), u32(have));
605 28b49df3 2006-07-18 devnull break;
606 28b49df3 2006-07-18 devnull case D|4:
607 28b49df3 2006-07-18 devnull print("\t%s: correct=%,ud disk=%,ud\n",
608 28b49df3 2006-07-18 devnull info->name, u32(want), u32(have));
609 28b49df3 2006-07-18 devnull break;
610 28b49df3 2006-07-18 devnull case T|4:
611 28b49df3 2006-07-18 devnull print("\t%s: correct=%t\n\t\tdisk=%t\n",
612 28b49df3 2006-07-18 devnull info->name, u32(want), u32(have));
613 28b49df3 2006-07-18 devnull break;
614 28b49df3 2006-07-18 devnull case Z|4:
615 28b49df3 2006-07-18 devnull print("\t%s: correct=%z disk=%z\n",
616 28b49df3 2006-07-18 devnull info->name, (uvlong)u32(want), (uvlong)u32(have));
617 28b49df3 2006-07-18 devnull break;
618 28b49df3 2006-07-18 devnull case D|8:
619 28b49df3 2006-07-18 devnull print("\t%s: correct=%,lld disk=%,lld\n",
620 28b49df3 2006-07-18 devnull info->name, u64(want), u64(have));
621 28b49df3 2006-07-18 devnull break;
622 28b49df3 2006-07-18 devnull case Z|8:
623 28b49df3 2006-07-18 devnull print("\t%s: correct=%z disk=%z\n",
624 28b49df3 2006-07-18 devnull info->name, u64(want), u64(have));
625 28b49df3 2006-07-18 devnull break;
626 28b49df3 2006-07-18 devnull case S|ANameSize:
627 28b49df3 2006-07-18 devnull print("\t%s: correct=%s disk=%.*s\n",
628 fa325e9b 2020-01-10 cross info->name, (char*)want,
629 28b49df3 2006-07-18 devnull utfnlen((char*)have, ANameSize-1),
630 28b49df3 2006-07-18 devnull (char*)have);
631 28b49df3 2006-07-18 devnull break;
632 28b49df3 2006-07-18 devnull default:
633 28b49df3 2006-07-18 devnull print("\t%s: correct=%.*H disk=%.*H\n",
634 28b49df3 2006-07-18 devnull info->name, n, want, n, have);
635 28b49df3 2006-07-18 devnull break;
636 28b49df3 2006-07-18 devnull }
637 28b49df3 2006-07-18 devnull }
638 28b49df3 2006-07-18 devnull have += n;
639 28b49df3 2006-07-18 devnull want += n;
640 28b49df3 2006-07-18 devnull len -= n;
641 28b49df3 2006-07-18 devnull info++;
642 28b49df3 2006-07-18 devnull }
643 28b49df3 2006-07-18 devnull if(len > 0 && memcmp(have, want, len) != 0){
644 28b49df3 2006-07-18 devnull if(memcmp(want, zero, len) != 0)
645 28b49df3 2006-07-18 devnull print("!!\textra want data in showdiffs (bug in fixarenas)\n");
646 28b49df3 2006-07-18 devnull else
647 28b49df3 2006-07-18 devnull print("\tnon-zero data on disk after structure\n");
648 28b49df3 2006-07-18 devnull if(verbose > 1){
649 28b49df3 2006-07-18 devnull print("want: %.*H\n", len, want);
650 28b49df3 2006-07-18 devnull print("have: %.*H\n", len, have);
651 28b49df3 2006-07-18 devnull }
652 28b49df3 2006-07-18 devnull }
653 28b49df3 2006-07-18 devnull }
654 28b49df3 2006-07-18 devnull
655 28b49df3 2006-07-18 devnull /*
656 c482feff 2007-05-03 devnull * Does part begin with an arena?
657 c482feff 2007-05-03 devnull */
658 c482feff 2007-05-03 devnull int
659 c482feff 2007-05-03 devnull isonearena(void)
660 c482feff 2007-05-03 devnull {
661 c482feff 2007-05-03 devnull return u32(pagein(0, Block)) == ArenaHeadMagic;
662 c482feff 2007-05-03 devnull }
663 c482feff 2007-05-03 devnull
664 45ac814c 2007-10-29 rsc static int tabsizes[] = { 16*1024, 64*1024, 512*1024, 768*1024, };
665 c482feff 2007-05-03 devnull /*
666 28b49df3 2006-07-18 devnull * Poke around on the disk to guess what the ArenaPart numbers are.
667 28b49df3 2006-07-18 devnull */
668 28b49df3 2006-07-18 devnull void
669 28b49df3 2006-07-18 devnull guessgeometry(void)
670 28b49df3 2006-07-18 devnull {
671 28b49df3 2006-07-18 devnull int i, j, n, bestn, ndiff, nhead, ntail;
672 28b49df3 2006-07-18 devnull uchar *p, *ep, *sp;
673 28b49df3 2006-07-18 devnull u64int diff[100], head[20], tail[20];
674 28b49df3 2006-07-18 devnull u64int offset, bestdiff;
675 fa325e9b 2020-01-10 cross
676 28b49df3 2006-07-18 devnull ap.version = ArenaPartVersion;
677 28b49df3 2006-07-18 devnull
678 28b49df3 2006-07-18 devnull if(arenasize == 0 || ap.blocksize == 0){
679 28b49df3 2006-07-18 devnull /*
680 28b49df3 2006-07-18 devnull * The ArenaPart block at offset PartBlank may be corrupt or just wrong.
681 28b49df3 2006-07-18 devnull * Instead, look for the individual arena headers and tails, which there
682 28b49df3 2006-07-18 devnull * are many of, and once we've seen enough, infer the spacing.
683 28b49df3 2006-07-18 devnull *
684 28b49df3 2006-07-18 devnull * Of course, nothing in the file format requires that arenas be evenly
685 28b49df3 2006-07-18 devnull * spaced, but fmtarenas always does that for us.
686 28b49df3 2006-07-18 devnull */
687 28b49df3 2006-07-18 devnull nhead = 0;
688 28b49df3 2006-07-18 devnull ntail = 0;
689 28b49df3 2006-07-18 devnull for(offset=PartBlank; offset<partend; offset+=4*M){
690 28b49df3 2006-07-18 devnull p = pagein(offset, 4*M);
691 28b49df3 2006-07-18 devnull for(sp=p, ep=p+4*M; p<ep; p+=K){
692 28b49df3 2006-07-18 devnull if(u32(p) == ArenaHeadMagic && nhead < nelem(head)){
693 28b49df3 2006-07-18 devnull if(verbose)
694 28b49df3 2006-07-18 devnull print("arena head at %#llx\n", offset+(p-sp));
695 28b49df3 2006-07-18 devnull head[nhead++] = offset+(p-sp);
696 28b49df3 2006-07-18 devnull }
697 28b49df3 2006-07-18 devnull if(u32(p) == ArenaMagic && ntail < nelem(tail)){
698 28b49df3 2006-07-18 devnull tail[ntail++] = offset+(p-sp);
699 28b49df3 2006-07-18 devnull if(verbose)
700 28b49df3 2006-07-18 devnull print("arena tail at %#llx\n", offset+(p-sp));
701 28b49df3 2006-07-18 devnull }
702 28b49df3 2006-07-18 devnull }
703 28b49df3 2006-07-18 devnull if(nhead == nelem(head) && ntail == nelem(tail))
704 28b49df3 2006-07-18 devnull break;
705 28b49df3 2006-07-18 devnull }
706 28b49df3 2006-07-18 devnull if(nhead < 3 && ntail < 3)
707 28b49df3 2006-07-18 devnull sysfatal("too few intact arenas: %d heads, %d tails", nhead, ntail);
708 fa325e9b 2020-01-10 cross
709 fa325e9b 2020-01-10 cross /*
710 28b49df3 2006-07-18 devnull * Arena size is likely the most common
711 28b49df3 2006-07-18 devnull * inter-head or inter-tail spacing.
712 28b49df3 2006-07-18 devnull */
713 28b49df3 2006-07-18 devnull ndiff = 0;
714 28b49df3 2006-07-18 devnull for(i=1; i<nhead; i++)
715 28b49df3 2006-07-18 devnull diff[ndiff++] = head[i] - head[i-1];
716 28b49df3 2006-07-18 devnull for(i=1; i<ntail; i++)
717 28b49df3 2006-07-18 devnull diff[ndiff++] = tail[i] - tail[i-1];
718 28b49df3 2006-07-18 devnull qsort(diff, ndiff, sizeof diff[0], vlongcmp);
719 28b49df3 2006-07-18 devnull bestn = 0;
720 28b49df3 2006-07-18 devnull bestdiff = 0;
721 28b49df3 2006-07-18 devnull for(i=1, n=1; i<=ndiff; i++, n++){
722 28b49df3 2006-07-18 devnull if(i==ndiff || diff[i] != diff[i-1]){
723 28b49df3 2006-07-18 devnull if(n > bestn){
724 28b49df3 2006-07-18 devnull bestn = n;
725 28b49df3 2006-07-18 devnull bestdiff = diff[i-1];
726 28b49df3 2006-07-18 devnull }
727 28b49df3 2006-07-18 devnull n = 0;
728 28b49df3 2006-07-18 devnull }
729 28b49df3 2006-07-18 devnull }
730 28b49df3 2006-07-18 devnull print("arena size likely %z (%d of %d)\n", bestdiff, bestn, ndiff);
731 28b49df3 2006-07-18 devnull if(arenasize != 0 && arenasize != bestdiff)
732 28b49df3 2006-07-18 devnull print("using user-specified size %z instead\n", arenasize);
733 28b49df3 2006-07-18 devnull else
734 28b49df3 2006-07-18 devnull arenasize = bestdiff;
735 28b49df3 2006-07-18 devnull
736 28b49df3 2006-07-18 devnull /*
737 28b49df3 2006-07-18 devnull * The arena tail for an arena is arenasize-blocksize from the head.
738 28b49df3 2006-07-18 devnull */
739 28b49df3 2006-07-18 devnull ndiff = 0;
740 28b49df3 2006-07-18 devnull for(i=j=0; i<nhead && j<ntail; ){
741 28b49df3 2006-07-18 devnull if(tail[j] < head[i]){
742 28b49df3 2006-07-18 devnull j++;
743 28b49df3 2006-07-18 devnull continue;
744 28b49df3 2006-07-18 devnull }
745 28b49df3 2006-07-18 devnull if(tail[j] < head[i]+arenasize){
746 28b49df3 2006-07-18 devnull diff[ndiff++] = head[i]+arenasize - tail[j];
747 28b49df3 2006-07-18 devnull j++;
748 28b49df3 2006-07-18 devnull continue;
749 28b49df3 2006-07-18 devnull }
750 28b49df3 2006-07-18 devnull i++;
751 28b49df3 2006-07-18 devnull }
752 28b49df3 2006-07-18 devnull if(ndiff < 3)
753 28b49df3 2006-07-18 devnull sysfatal("too few intact arenas: %d head, tail pairs", ndiff);
754 28b49df3 2006-07-18 devnull qsort(diff, ndiff, sizeof diff[0], vlongcmp);
755 28b49df3 2006-07-18 devnull bestn = 0;
756 28b49df3 2006-07-18 devnull bestdiff = 0;
757 28b49df3 2006-07-18 devnull for(i=1, n=1; i<=ndiff; i++, n++){
758 28b49df3 2006-07-18 devnull if(i==ndiff || diff[i] != diff[i-1]){
759 28b49df3 2006-07-18 devnull if(n > bestn){
760 28b49df3 2006-07-18 devnull bestn = n;
761 28b49df3 2006-07-18 devnull bestdiff = diff[i-1];
762 28b49df3 2006-07-18 devnull }
763 28b49df3 2006-07-18 devnull n = 0;
764 28b49df3 2006-07-18 devnull }
765 28b49df3 2006-07-18 devnull }
766 28b49df3 2006-07-18 devnull print("block size likely %z (%d of %d)\n", bestdiff, bestn, ndiff);
767 28b49df3 2006-07-18 devnull if(ap.blocksize != 0 && ap.blocksize != bestdiff)
768 28b49df3 2006-07-18 devnull print("using user-specified size %z instead\n", (vlong)ap.blocksize);
769 28b49df3 2006-07-18 devnull else
770 28b49df3 2006-07-18 devnull ap.blocksize = bestdiff;
771 28b49df3 2006-07-18 devnull if(ap.blocksize == 0 || ap.blocksize&(ap.blocksize-1))
772 28b49df3 2006-07-18 devnull sysfatal("block size not a power of two");
773 28b49df3 2006-07-18 devnull if(ap.blocksize > MaxDiskBlock)
774 28b49df3 2006-07-18 devnull sysfatal("block size too big (max=%d)", MaxDiskBlock);
775 28b49df3 2006-07-18 devnull
776 28b49df3 2006-07-18 devnull /*
777 28b49df3 2006-07-18 devnull * Use head/tail information to deduce arena base.
778 28b49df3 2006-07-18 devnull */
779 28b49df3 2006-07-18 devnull ndiff = 0;
780 28b49df3 2006-07-18 devnull for(i=0; i<nhead; i++)
781 28b49df3 2006-07-18 devnull diff[ndiff++] = head[i]%arenasize;
782 28b49df3 2006-07-18 devnull for(i=0; i<ntail; i++)
783 28b49df3 2006-07-18 devnull diff[ndiff++] = (tail[i]+ap.blocksize)%arenasize;
784 28b49df3 2006-07-18 devnull qsort(diff, ndiff, sizeof diff[0], vlongcmp);
785 28b49df3 2006-07-18 devnull bestn = 0;
786 28b49df3 2006-07-18 devnull bestdiff = 0;
787 28b49df3 2006-07-18 devnull for(i=1, n=1; i<=ndiff; i++, n++){
788 28b49df3 2006-07-18 devnull if(i==ndiff || diff[i] != diff[i-1]){
789 28b49df3 2006-07-18 devnull if(n > bestn){
790 28b49df3 2006-07-18 devnull bestn = n;
791 28b49df3 2006-07-18 devnull bestdiff = diff[i-1];
792 28b49df3 2006-07-18 devnull }
793 28b49df3 2006-07-18 devnull n = 0;
794 28b49df3 2006-07-18 devnull }
795 28b49df3 2006-07-18 devnull }
796 28b49df3 2006-07-18 devnull ap.arenabase = bestdiff;
797 28b49df3 2006-07-18 devnull }
798 67a65bba 2007-09-25 rsc
799 67a65bba 2007-09-25 rsc ap.tabbase = ROUNDUP(PartBlank+HeadSize, ap.blocksize);
800 28b49df3 2006-07-18 devnull /*
801 28b49df3 2006-07-18 devnull * XXX pick up table, check arenabase.
802 28b49df3 2006-07-18 devnull * XXX pick up table, record base name.
803 28b49df3 2006-07-18 devnull */
804 28b49df3 2006-07-18 devnull
805 28b49df3 2006-07-18 devnull /*
806 28b49df3 2006-07-18 devnull * Somewhat standard computation.
807 28b49df3 2006-07-18 devnull * Fmtarenas used to use 64k tab, now uses 512k tab.
808 28b49df3 2006-07-18 devnull */
809 28b49df3 2006-07-18 devnull if(ap.arenabase == 0){
810 45ac814c 2007-10-29 rsc print("trying standard arena bases...\n");
811 28b49df3 2006-07-18 devnull for(i=0; i<nelem(tabsizes); i++){
812 45ac814c 2007-10-29 rsc ap.arenabase = ROUNDUP(PartBlank+HeadSize+tabsizes[i], ap.blocksize);
813 28b49df3 2006-07-18 devnull p = pagein(ap.arenabase, Block);
814 28b49df3 2006-07-18 devnull if(u32(p) == ArenaHeadMagic)
815 28b49df3 2006-07-18 devnull break;
816 28b49df3 2006-07-18 devnull }
817 28b49df3 2006-07-18 devnull }
818 28b49df3 2006-07-18 devnull p = pagein(ap.arenabase, Block);
819 fa325e9b 2020-01-10 cross print("arena base likely %z%s\n", (vlong)ap.arenabase,
820 28b49df3 2006-07-18 devnull u32(p)!=ArenaHeadMagic ? " (but no arena head there)" : "");
821 28b49df3 2006-07-18 devnull
822 28b49df3 2006-07-18 devnull ap.tabsize = ap.arenabase - ap.tabbase;
823 28b49df3 2006-07-18 devnull }
824 28b49df3 2006-07-18 devnull
825 28b49df3 2006-07-18 devnull /*
826 28b49df3 2006-07-18 devnull * Check the arena partition blocks and then the arenas listed in range.
827 28b49df3 2006-07-18 devnull */
828 28b49df3 2006-07-18 devnull void
829 28b49df3 2006-07-18 devnull checkarenas(char *range)
830 28b49df3 2006-07-18 devnull {
831 28b49df3 2006-07-18 devnull char *s, *t;
832 28b49df3 2006-07-18 devnull int i, lo, hi, narena;
833 28b49df3 2006-07-18 devnull uchar dbuf[HeadSize];
834 28b49df3 2006-07-18 devnull uchar *p;
835 28b49df3 2006-07-18 devnull
836 28b49df3 2006-07-18 devnull guessgeometry();
837 28b49df3 2006-07-18 devnull
838 28b49df3 2006-07-18 devnull partend -= partend%ap.blocksize;
839 28b49df3 2006-07-18 devnull
840 28b49df3 2006-07-18 devnull memset(dbuf, 0, sizeof dbuf);
841 28b49df3 2006-07-18 devnull packarenapart(&ap, dbuf);
842 28b49df3 2006-07-18 devnull p = pagein(PartBlank, Block);
843 28b49df3 2006-07-18 devnull if(memcmp(p, dbuf, HeadSize) != 0){
844 28b49df3 2006-07-18 devnull print("on-disk arena part superblock incorrect\n");
845 28b49df3 2006-07-18 devnull showdiffs(dbuf, p, HeadSize, partinfo);
846 28b49df3 2006-07-18 devnull }
847 28b49df3 2006-07-18 devnull memmove(p, dbuf, HeadSize);
848 28b49df3 2006-07-18 devnull
849 28b49df3 2006-07-18 devnull narena = (partend-ap.arenabase + arenasize-1)/arenasize;
850 28b49df3 2006-07-18 devnull if(range == nil){
851 28b49df3 2006-07-18 devnull for(i=0; i<narena; i++)
852 28b49df3 2006-07-18 devnull checkarena(ap.arenabase+(vlong)i*arenasize, i);
853 28b49df3 2006-07-18 devnull }else if(strcmp(range, "none") == 0){
854 28b49df3 2006-07-18 devnull /* nothing */
855 28b49df3 2006-07-18 devnull }else{
856 28b49df3 2006-07-18 devnull /* parse, e.g., -4,8-9,10- */
857 28b49df3 2006-07-18 devnull for(s=range; *s; s=t){
858 28b49df3 2006-07-18 devnull t = strchr(s, ',');
859 28b49df3 2006-07-18 devnull if(t)
860 28b49df3 2006-07-18 devnull *t++ = 0;
861 28b49df3 2006-07-18 devnull else
862 28b49df3 2006-07-18 devnull t = s+strlen(s);
863 28b49df3 2006-07-18 devnull if(*s == '-')
864 28b49df3 2006-07-18 devnull lo = 0;
865 28b49df3 2006-07-18 devnull else
866 28b49df3 2006-07-18 devnull lo = strtol(s, &s, 0);
867 28b49df3 2006-07-18 devnull hi = lo;
868 28b49df3 2006-07-18 devnull if(*s == '-'){
869 28b49df3 2006-07-18 devnull s++;
870 28b49df3 2006-07-18 devnull if(*s == 0)
871 28b49df3 2006-07-18 devnull hi = narena-1;
872 28b49df3 2006-07-18 devnull else
873 28b49df3 2006-07-18 devnull hi = strtol(s, &s, 0);
874 28b49df3 2006-07-18 devnull }
875 28b49df3 2006-07-18 devnull if(*s != 0){
876 28b49df3 2006-07-18 devnull print("bad arena range: %s\n", s);
877 28b49df3 2006-07-18 devnull continue;
878 28b49df3 2006-07-18 devnull }
879 28b49df3 2006-07-18 devnull for(i=lo; i<=hi; i++)
880 28b49df3 2006-07-18 devnull checkarena(ap.arenabase+(vlong)i*arenasize, i);
881 28b49df3 2006-07-18 devnull }
882 28b49df3 2006-07-18 devnull }
883 28b49df3 2006-07-18 devnull }
884 28b49df3 2006-07-18 devnull
885 28b49df3 2006-07-18 devnull /*
886 28b49df3 2006-07-18 devnull * Is there a clump here at p?
887 28b49df3 2006-07-18 devnull */
888 28b49df3 2006-07-18 devnull static int
889 28b49df3 2006-07-18 devnull isclump(uchar *p, Clump *cl, u32int *pmagic)
890 28b49df3 2006-07-18 devnull {
891 28b49df3 2006-07-18 devnull int n;
892 28b49df3 2006-07-18 devnull u32int magic;
893 28b49df3 2006-07-18 devnull uchar score[VtScoreSize], *bp;
894 28b49df3 2006-07-18 devnull Unwhack uw;
895 28b49df3 2006-07-18 devnull uchar ubuf[70*1024];
896 fa325e9b 2020-01-10 cross
897 28b49df3 2006-07-18 devnull bp = p;
898 28b49df3 2006-07-18 devnull magic = u32(p);
899 28b49df3 2006-07-18 devnull if(magic == 0)
900 28b49df3 2006-07-18 devnull return 0;
901 28b49df3 2006-07-18 devnull p += U32Size;
902 28b49df3 2006-07-18 devnull
903 28b49df3 2006-07-18 devnull cl->info.type = vtfromdisktype(*p);
904 28b49df3 2006-07-18 devnull if(cl->info.type == 0xFF)
905 28b49df3 2006-07-18 devnull return 0;
906 28b49df3 2006-07-18 devnull p++;
907 28b49df3 2006-07-18 devnull cl->info.size = u16(p);
908 28b49df3 2006-07-18 devnull p += U16Size;
909 28b49df3 2006-07-18 devnull cl->info.uncsize = u16(p);
910 28b49df3 2006-07-18 devnull if(cl->info.size > cl->info.uncsize)
911 28b49df3 2006-07-18 devnull return 0;
912 28b49df3 2006-07-18 devnull p += U16Size;
913 28b49df3 2006-07-18 devnull scorecp(cl->info.score, p);
914 28b49df3 2006-07-18 devnull p += VtScoreSize;
915 28b49df3 2006-07-18 devnull cl->encoding = *p;
916 28b49df3 2006-07-18 devnull p++;
917 28b49df3 2006-07-18 devnull cl->creator = u32(p);
918 28b49df3 2006-07-18 devnull p += U32Size;
919 28b49df3 2006-07-18 devnull cl->time = u32(p);
920 28b49df3 2006-07-18 devnull p += U32Size;
921 28b49df3 2006-07-18 devnull
922 28b49df3 2006-07-18 devnull switch(cl->encoding){
923 28b49df3 2006-07-18 devnull case ClumpENone:
924 28b49df3 2006-07-18 devnull if(cl->info.size != cl->info.uncsize)
925 28b49df3 2006-07-18 devnull return 0;
926 28b49df3 2006-07-18 devnull scoremem(score, p, cl->info.size);
927 28b49df3 2006-07-18 devnull if(scorecmp(score, cl->info.score) != 0)
928 28b49df3 2006-07-18 devnull return 0;
929 28b49df3 2006-07-18 devnull break;
930 28b49df3 2006-07-18 devnull case ClumpECompress:
931 28b49df3 2006-07-18 devnull if(cl->info.size >= cl->info.uncsize)
932 28b49df3 2006-07-18 devnull return 0;
933 28b49df3 2006-07-18 devnull unwhackinit(&uw);
934 28b49df3 2006-07-18 devnull n = unwhack(&uw, ubuf, cl->info.uncsize, p, cl->info.size);
935 28b49df3 2006-07-18 devnull if(n != cl->info.uncsize)
936 28b49df3 2006-07-18 devnull return 0;
937 28b49df3 2006-07-18 devnull scoremem(score, ubuf, cl->info.uncsize);
938 28b49df3 2006-07-18 devnull if(scorecmp(score, cl->info.score) != 0)
939 28b49df3 2006-07-18 devnull return 0;
940 28b49df3 2006-07-18 devnull break;
941 28b49df3 2006-07-18 devnull default:
942 28b49df3 2006-07-18 devnull return 0;
943 28b49df3 2006-07-18 devnull }
944 28b49df3 2006-07-18 devnull p += cl->info.size;
945 fa325e9b 2020-01-10 cross
946 28b49df3 2006-07-18 devnull /* it all worked out in the end */
947 28b49df3 2006-07-18 devnull *pmagic = magic;
948 28b49df3 2006-07-18 devnull return p - bp;
949 28b49df3 2006-07-18 devnull }
950 28b49df3 2006-07-18 devnull
951 28b49df3 2006-07-18 devnull /*
952 28b49df3 2006-07-18 devnull * All ClumpInfos seen in this arena.
953 28b49df3 2006-07-18 devnull * Kept in binary tree so we can look up by score.
954 28b49df3 2006-07-18 devnull */
955 28b49df3 2006-07-18 devnull typedef struct Cit Cit;
956 28b49df3 2006-07-18 devnull struct Cit
957 28b49df3 2006-07-18 devnull {
958 28b49df3 2006-07-18 devnull int left;
959 28b49df3 2006-07-18 devnull int right;
960 28b49df3 2006-07-18 devnull vlong corrupt;
961 28b49df3 2006-07-18 devnull ClumpInfo ci;
962 28b49df3 2006-07-18 devnull };
963 28b49df3 2006-07-18 devnull Cit *cibuf;
964 28b49df3 2006-07-18 devnull int ciroot;
965 28b49df3 2006-07-18 devnull int ncibuf, mcibuf;
966 28b49df3 2006-07-18 devnull
967 28b49df3 2006-07-18 devnull void
968 28b49df3 2006-07-18 devnull resetcibuf(void)
969 28b49df3 2006-07-18 devnull {
970 28b49df3 2006-07-18 devnull ncibuf = 0;
971 28b49df3 2006-07-18 devnull ciroot = -1;
972 28b49df3 2006-07-18 devnull }
973 28b49df3 2006-07-18 devnull
974 28b49df3 2006-07-18 devnull int*
975 28b49df3 2006-07-18 devnull ltreewalk(int *p, uchar *score)
976 28b49df3 2006-07-18 devnull {
977 28b49df3 2006-07-18 devnull int i;
978 fa325e9b 2020-01-10 cross
979 28b49df3 2006-07-18 devnull for(;;){
980 28b49df3 2006-07-18 devnull if(*p == -1)
981 28b49df3 2006-07-18 devnull return p;
982 28b49df3 2006-07-18 devnull i = scorecmp(cibuf[*p].ci.score, score);
983 28b49df3 2006-07-18 devnull if(i == 0)
984 28b49df3 2006-07-18 devnull return p;
985 28b49df3 2006-07-18 devnull if(i < 0)
986 28b49df3 2006-07-18 devnull p = &cibuf[*p].right;
987 28b49df3 2006-07-18 devnull else
988 28b49df3 2006-07-18 devnull p = &cibuf[*p].left;
989 28b49df3 2006-07-18 devnull }
990 28b49df3 2006-07-18 devnull }
991 28b49df3 2006-07-18 devnull
992 28b49df3 2006-07-18 devnull void
993 28b49df3 2006-07-18 devnull addcibuf(ClumpInfo *ci, vlong corrupt)
994 28b49df3 2006-07-18 devnull {
995 28b49df3 2006-07-18 devnull Cit *cit;
996 fa325e9b 2020-01-10 cross
997 28b49df3 2006-07-18 devnull if(ncibuf == mcibuf){
998 28b49df3 2006-07-18 devnull mcibuf += 131072;
999 28b49df3 2006-07-18 devnull cibuf = vtrealloc(cibuf, mcibuf*sizeof cibuf[0]);
1000 28b49df3 2006-07-18 devnull }
1001 28b49df3 2006-07-18 devnull cit = &cibuf[ncibuf];
1002 28b49df3 2006-07-18 devnull cit->ci = *ci;
1003 28b49df3 2006-07-18 devnull cit->left = -1;
1004 28b49df3 2006-07-18 devnull cit->right = -1;
1005 28b49df3 2006-07-18 devnull cit->corrupt = corrupt;
1006 28b49df3 2006-07-18 devnull if(!corrupt)
1007 28b49df3 2006-07-18 devnull *ltreewalk(&ciroot, ci->score) = ncibuf;
1008 28b49df3 2006-07-18 devnull ncibuf++;
1009 28b49df3 2006-07-18 devnull }
1010 28b49df3 2006-07-18 devnull
1011 28b49df3 2006-07-18 devnull void
1012 28b49df3 2006-07-18 devnull addcicorrupt(vlong len)
1013 28b49df3 2006-07-18 devnull {
1014 28b49df3 2006-07-18 devnull static ClumpInfo zci;
1015 fa325e9b 2020-01-10 cross
1016 28b49df3 2006-07-18 devnull addcibuf(&zci, len);
1017 28b49df3 2006-07-18 devnull }
1018 28b49df3 2006-07-18 devnull
1019 28b49df3 2006-07-18 devnull int
1020 28b49df3 2006-07-18 devnull haveclump(uchar *score)
1021 28b49df3 2006-07-18 devnull {
1022 28b49df3 2006-07-18 devnull int i;
1023 28b49df3 2006-07-18 devnull int p;
1024 fa325e9b 2020-01-10 cross
1025 28b49df3 2006-07-18 devnull p = ciroot;
1026 28b49df3 2006-07-18 devnull for(;;){
1027 28b49df3 2006-07-18 devnull if(p == -1)
1028 28b49df3 2006-07-18 devnull return 0;
1029 28b49df3 2006-07-18 devnull i = scorecmp(cibuf[p].ci.score, score);
1030 28b49df3 2006-07-18 devnull if(i == 0)
1031 28b49df3 2006-07-18 devnull return 1;
1032 28b49df3 2006-07-18 devnull if(i < 0)
1033 28b49df3 2006-07-18 devnull p = cibuf[p].right;
1034 28b49df3 2006-07-18 devnull else
1035 28b49df3 2006-07-18 devnull p = cibuf[p].left;
1036 28b49df3 2006-07-18 devnull }
1037 28b49df3 2006-07-18 devnull }
1038 28b49df3 2006-07-18 devnull
1039 28b49df3 2006-07-18 devnull int
1040 28b49df3 2006-07-18 devnull matchci(ClumpInfo *ci, uchar *p)
1041 28b49df3 2006-07-18 devnull {
1042 28b49df3 2006-07-18 devnull if(ci->type != vtfromdisktype(p[0]))
1043 28b49df3 2006-07-18 devnull return 0;
1044 28b49df3 2006-07-18 devnull if(ci->size != u16(p+1))
1045 28b49df3 2006-07-18 devnull return 0;
1046 28b49df3 2006-07-18 devnull if(ci->uncsize != u16(p+3))
1047 28b49df3 2006-07-18 devnull return 0;
1048 28b49df3 2006-07-18 devnull if(scorecmp(ci->score, p+5) != 0)
1049 28b49df3 2006-07-18 devnull return 0;
1050 28b49df3 2006-07-18 devnull return 1;
1051 28b49df3 2006-07-18 devnull }
1052 28b49df3 2006-07-18 devnull
1053 28b49df3 2006-07-18 devnull int
1054 28b49df3 2006-07-18 devnull sealedarena(uchar *p, int blocksize)
1055 28b49df3 2006-07-18 devnull {
1056 28b49df3 2006-07-18 devnull int v, n;
1057 fa325e9b 2020-01-10 cross
1058 28b49df3 2006-07-18 devnull v = u32(p+4);
1059 28b49df3 2006-07-18 devnull switch(v){
1060 28b49df3 2006-07-18 devnull default:
1061 28b49df3 2006-07-18 devnull return 0;
1062 28b49df3 2006-07-18 devnull case ArenaVersion4:
1063 28b49df3 2006-07-18 devnull n = ArenaSize4;
1064 28b49df3 2006-07-18 devnull break;
1065 28b49df3 2006-07-18 devnull case ArenaVersion5:
1066 28b49df3 2006-07-18 devnull n = ArenaSize5;
1067 28b49df3 2006-07-18 devnull break;
1068 28b49df3 2006-07-18 devnull }
1069 28b49df3 2006-07-18 devnull if(p[n-1] != 1){
1070 28b49df3 2006-07-18 devnull print("arena tail says not sealed\n");
1071 28b49df3 2006-07-18 devnull return 0;
1072 28b49df3 2006-07-18 devnull }
1073 28b49df3 2006-07-18 devnull if(memcmp(p+n, zero, blocksize-VtScoreSize-n) != 0){
1074 28b49df3 2006-07-18 devnull print("arena tail followed by non-zero data\n");
1075 28b49df3 2006-07-18 devnull return 0;
1076 28b49df3 2006-07-18 devnull }
1077 28b49df3 2006-07-18 devnull if(memcmp(p+blocksize-VtScoreSize, zero, VtScoreSize) == 0){
1078 28b49df3 2006-07-18 devnull print("arena score zero\n");
1079 28b49df3 2006-07-18 devnull return 0;
1080 28b49df3 2006-07-18 devnull }
1081 28b49df3 2006-07-18 devnull return 1;
1082 28b49df3 2006-07-18 devnull }
1083 28b49df3 2006-07-18 devnull
1084 28b49df3 2006-07-18 devnull int
1085 28b49df3 2006-07-18 devnull okayname(char *name, int n)
1086 28b49df3 2006-07-18 devnull {
1087 28b49df3 2006-07-18 devnull char buf[20];
1088 fa325e9b 2020-01-10 cross
1089 28b49df3 2006-07-18 devnull if(nameok(name) < 0)
1090 28b49df3 2006-07-18 devnull return 0;
1091 28b49df3 2006-07-18 devnull sprint(buf, "%d", n);
1092 c482feff 2007-05-03 devnull if(n == 0)
1093 c482feff 2007-05-03 devnull buf[0] = 0;
1094 fa325e9b 2020-01-10 cross if(strlen(name) < strlen(buf)
1095 28b49df3 2006-07-18 devnull || strcmp(name+strlen(name)-strlen(buf), buf) != 0)
1096 28b49df3 2006-07-18 devnull return 0;
1097 28b49df3 2006-07-18 devnull return 1;
1098 28b49df3 2006-07-18 devnull }
1099 28b49df3 2006-07-18 devnull
1100 28b49df3 2006-07-18 devnull int
1101 28b49df3 2006-07-18 devnull clumpinfocmp(ClumpInfo *a, ClumpInfo *b)
1102 28b49df3 2006-07-18 devnull {
1103 28b49df3 2006-07-18 devnull if(a->type != b->type)
1104 28b49df3 2006-07-18 devnull return a->type - b->type;
1105 28b49df3 2006-07-18 devnull if(a->size != b->size)
1106 28b49df3 2006-07-18 devnull return a->size - b->size;
1107 28b49df3 2006-07-18 devnull if(a->uncsize != b->uncsize)
1108 28b49df3 2006-07-18 devnull return a->uncsize - b->uncsize;
1109 28b49df3 2006-07-18 devnull return scorecmp(a->score, b->score);
1110 28b49df3 2006-07-18 devnull }
1111 28b49df3 2006-07-18 devnull
1112 28b49df3 2006-07-18 devnull ClumpInfo*
1113 28b49df3 2006-07-18 devnull loadci(vlong offset, Arena *arena, int nci)
1114 28b49df3 2006-07-18 devnull {
1115 28b49df3 2006-07-18 devnull int i, j, per;
1116 28b49df3 2006-07-18 devnull uchar *p, *sp;
1117 28b49df3 2006-07-18 devnull ClumpInfo *bci, *ci;
1118 fa325e9b 2020-01-10 cross
1119 28b49df3 2006-07-18 devnull per = arena->blocksize/ClumpInfoSize;
1120 28b49df3 2006-07-18 devnull bci = vtmalloc(nci*sizeof bci[0]);
1121 28b49df3 2006-07-18 devnull ci = bci;
1122 28b49df3 2006-07-18 devnull offset += arena->size - arena->blocksize;
1123 28b49df3 2006-07-18 devnull p = sp = nil;
1124 28b49df3 2006-07-18 devnull for(i=0; i<nci; i+=per){
1125 28b49df3 2006-07-18 devnull if(p == sp){
1126 28b49df3 2006-07-18 devnull sp = pagein(offset-4*M, 4*M);
1127 28b49df3 2006-07-18 devnull p = sp+4*M;
1128 28b49df3 2006-07-18 devnull }
1129 28b49df3 2006-07-18 devnull p -= arena->blocksize;
1130 28b49df3 2006-07-18 devnull offset -= arena->blocksize;
1131 28b49df3 2006-07-18 devnull for(j=0; j<per && i+j<nci; j++)
1132 28b49df3 2006-07-18 devnull unpackclumpinfo(ci++, p+j*ClumpInfoSize);
1133 28b49df3 2006-07-18 devnull }
1134 28b49df3 2006-07-18 devnull return bci;
1135 28b49df3 2006-07-18 devnull }
1136 28b49df3 2006-07-18 devnull
1137 28b49df3 2006-07-18 devnull vlong
1138 28b49df3 2006-07-18 devnull writeci(vlong offset, Arena *arena, ClumpInfo *ci, int nci)
1139 28b49df3 2006-07-18 devnull {
1140 28b49df3 2006-07-18 devnull int i, j, per;
1141 28b49df3 2006-07-18 devnull uchar *p, *sp;
1142 fa325e9b 2020-01-10 cross
1143 28b49df3 2006-07-18 devnull per = arena->blocksize/ClumpInfoSize;
1144 28b49df3 2006-07-18 devnull offset += arena->size - arena->blocksize;
1145 28b49df3 2006-07-18 devnull p = sp = nil;
1146 28b49df3 2006-07-18 devnull for(i=0; i<nci; i+=per){
1147 28b49df3 2006-07-18 devnull if(p == sp){
1148 28b49df3 2006-07-18 devnull sp = pagein(offset-4*M, 4*M);
1149 28b49df3 2006-07-18 devnull p = sp+4*M;
1150 28b49df3 2006-07-18 devnull }
1151 28b49df3 2006-07-18 devnull p -= arena->blocksize;
1152 28b49df3 2006-07-18 devnull offset -= arena->blocksize;
1153 28b49df3 2006-07-18 devnull memset(p, 0, arena->blocksize);
1154 28b49df3 2006-07-18 devnull for(j=0; j<per && i+j<nci; j++)
1155 28b49df3 2006-07-18 devnull packclumpinfo(ci++, p+j*ClumpInfoSize);
1156 28b49df3 2006-07-18 devnull }
1157 28b49df3 2006-07-18 devnull pageout();
1158 28b49df3 2006-07-18 devnull return offset;
1159 28b49df3 2006-07-18 devnull }
1160 28b49df3 2006-07-18 devnull
1161 28b49df3 2006-07-18 devnull void
1162 28b49df3 2006-07-18 devnull loadarenabasics(vlong offset0, int anum, ArenaHead *head, Arena *arena)
1163 28b49df3 2006-07-18 devnull {
1164 28b49df3 2006-07-18 devnull char dname[ANameSize];
1165 28b49df3 2006-07-18 devnull static char lastbase[ANameSize];
1166 28b49df3 2006-07-18 devnull uchar *p;
1167 28b49df3 2006-07-18 devnull Arena oarena;
1168 28b49df3 2006-07-18 devnull ArenaHead ohead;
1169 28b49df3 2006-07-18 devnull
1170 28b49df3 2006-07-18 devnull /*
1171 28b49df3 2006-07-18 devnull * Fmtarenas makes all arenas the same size
1172 28b49df3 2006-07-18 devnull * except the last, which may be smaller.
1173 28b49df3 2006-07-18 devnull * It uses the same block size for arenas as for
1174 28b49df3 2006-07-18 devnull * the arena partition blocks.
1175 28b49df3 2006-07-18 devnull */
1176 28b49df3 2006-07-18 devnull arena->size = arenasize;
1177 28b49df3 2006-07-18 devnull if(offset0+arena->size > partend)
1178 28b49df3 2006-07-18 devnull arena->size = partend - offset0;
1179 28b49df3 2006-07-18 devnull head->size = arena->size;
1180 fa325e9b 2020-01-10 cross
1181 28b49df3 2006-07-18 devnull arena->blocksize = ap.blocksize;
1182 28b49df3 2006-07-18 devnull head->blocksize = arena->blocksize;
1183 fa325e9b 2020-01-10 cross
1184 fa325e9b 2020-01-10 cross /*
1185 28b49df3 2006-07-18 devnull * Look for clump magic and name in head/tail blocks.
1186 28b49df3 2006-07-18 devnull * All the other info we will reconstruct just in case.
1187 28b49df3 2006-07-18 devnull */
1188 28b49df3 2006-07-18 devnull p = pagein(offset0, arena->blocksize);
1189 28b49df3 2006-07-18 devnull memset(&ohead, 0, sizeof ohead);
1190 28b49df3 2006-07-18 devnull if(unpackarenahead(&ohead, p) >= 0){
1191 28b49df3 2006-07-18 devnull head->version = ohead.version;
1192 28b49df3 2006-07-18 devnull head->clumpmagic = ohead.clumpmagic;
1193 28b49df3 2006-07-18 devnull if(okayname(ohead.name, anum))
1194 28b49df3 2006-07-18 devnull strcpy(head->name, ohead.name);
1195 28b49df3 2006-07-18 devnull }
1196 28b49df3 2006-07-18 devnull
1197 fa325e9b 2020-01-10 cross p = pagein(offset0+arena->size-arena->blocksize,
1198 28b49df3 2006-07-18 devnull arena->blocksize);
1199 28b49df3 2006-07-18 devnull memset(&oarena, 0, sizeof oarena);
1200 28b49df3 2006-07-18 devnull if(unpackarena(&oarena, p) >= 0){
1201 28b49df3 2006-07-18 devnull arena->version = oarena.version;
1202 28b49df3 2006-07-18 devnull arena->clumpmagic = oarena.clumpmagic;
1203 28b49df3 2006-07-18 devnull if(okayname(oarena.name, anum))
1204 28b49df3 2006-07-18 devnull strcpy(arena->name, oarena.name);
1205 28b49df3 2006-07-18 devnull arena->diskstats.clumps = oarena.diskstats.clumps;
1206 28b49df3 2006-07-18 devnull print("old arena: sealed=%d\n", oarena.diskstats.sealed);
1207 28b49df3 2006-07-18 devnull arena->diskstats.sealed = oarena.diskstats.sealed;
1208 28b49df3 2006-07-18 devnull }
1209 28b49df3 2006-07-18 devnull
1210 28b49df3 2006-07-18 devnull /* Head trumps arena. */
1211 28b49df3 2006-07-18 devnull if(head->version){
1212 28b49df3 2006-07-18 devnull arena->version = head->version;
1213 28b49df3 2006-07-18 devnull arena->clumpmagic = head->clumpmagic;
1214 28b49df3 2006-07-18 devnull }
1215 28b49df3 2006-07-18 devnull if(arena->version == 0)
1216 28b49df3 2006-07-18 devnull arena->version = ArenaVersion5;
1217 c482feff 2007-05-03 devnull if(basename){
1218 c482feff 2007-05-03 devnull if(anum == -1)
1219 c482feff 2007-05-03 devnull snprint(arena->name, ANameSize, "%s", basename);
1220 c482feff 2007-05-03 devnull else
1221 c482feff 2007-05-03 devnull snprint(arena->name, ANameSize, "%s%d", basename, anum);
1222 c482feff 2007-05-03 devnull }else if(lastbase[0])
1223 28b49df3 2006-07-18 devnull snprint(arena->name, ANameSize, "%s%d", lastbase, anum);
1224 28b49df3 2006-07-18 devnull else if(head->name[0])
1225 28b49df3 2006-07-18 devnull strcpy(arena->name, head->name);
1226 28b49df3 2006-07-18 devnull else if(arena->name[0] == 0)
1227 28b49df3 2006-07-18 devnull sysfatal("cannot determine base name for arena; use -n");
1228 28b49df3 2006-07-18 devnull strcpy(lastbase, arena->name);
1229 28b49df3 2006-07-18 devnull sprint(dname, "%d", anum);
1230 28b49df3 2006-07-18 devnull lastbase[strlen(lastbase)-strlen(dname)] = 0;
1231 fa325e9b 2020-01-10 cross
1232 28b49df3 2006-07-18 devnull /* Was working in arena, now copy to head. */
1233 28b49df3 2006-07-18 devnull head->version = arena->version;
1234 28b49df3 2006-07-18 devnull memmove(head->name, arena->name, sizeof head->name);
1235 28b49df3 2006-07-18 devnull head->blocksize = arena->blocksize;
1236 28b49df3 2006-07-18 devnull head->size = arena->size;
1237 28b49df3 2006-07-18 devnull }
1238 28b49df3 2006-07-18 devnull
1239 28b49df3 2006-07-18 devnull void
1240 28b49df3 2006-07-18 devnull shahead(Shabuf *sb, vlong offset0, ArenaHead *head)
1241 28b49df3 2006-07-18 devnull {
1242 28b49df3 2006-07-18 devnull uchar headbuf[MaxDiskBlock];
1243 fa325e9b 2020-01-10 cross
1244 28b49df3 2006-07-18 devnull sb->offset = offset0;
1245 28b49df3 2006-07-18 devnull memset(headbuf, 0, sizeof headbuf);
1246 28b49df3 2006-07-18 devnull packarenahead(head, headbuf);
1247 28b49df3 2006-07-18 devnull sbupdate(sb, headbuf, offset0, head->blocksize);
1248 28b49df3 2006-07-18 devnull }
1249 28b49df3 2006-07-18 devnull
1250 28b49df3 2006-07-18 devnull u32int
1251 28b49df3 2006-07-18 devnull newclumpmagic(int version)
1252 28b49df3 2006-07-18 devnull {
1253 28b49df3 2006-07-18 devnull u32int m;
1254 fa325e9b 2020-01-10 cross
1255 28b49df3 2006-07-18 devnull if(version == ArenaVersion4)
1256 28b49df3 2006-07-18 devnull return _ClumpMagic;
1257 28b49df3 2006-07-18 devnull do{
1258 28b49df3 2006-07-18 devnull m = fastrand();
1259 28b49df3 2006-07-18 devnull }while(m==0 || m == _ClumpMagic);
1260 28b49df3 2006-07-18 devnull return m;
1261 28b49df3 2006-07-18 devnull }
1262 28b49df3 2006-07-18 devnull
1263 28b49df3 2006-07-18 devnull /*
1264 28b49df3 2006-07-18 devnull * Poke around in the arena to find the clump data
1265 28b49df3 2006-07-18 devnull * and compute the relevant statistics.
1266 28b49df3 2006-07-18 devnull */
1267 28b49df3 2006-07-18 devnull void
1268 28b49df3 2006-07-18 devnull guessarena(vlong offset0, int anum, ArenaHead *head, Arena *arena,
1269 28b49df3 2006-07-18 devnull uchar *oldscore, uchar *score)
1270 28b49df3 2006-07-18 devnull {
1271 28b49df3 2006-07-18 devnull uchar dbuf[MaxDiskBlock];
1272 28b49df3 2006-07-18 devnull int needtozero, clumps, nb1, nb2, minclumps;
1273 28b49df3 2006-07-18 devnull int inbad, n, ncib, printed, sealing, smart;
1274 28b49df3 2006-07-18 devnull u32int magic;
1275 28b49df3 2006-07-18 devnull uchar *sp, *ep, *p;
1276 28b49df3 2006-07-18 devnull vlong boffset, eoffset, lastclumpend, leaked;
1277 28b49df3 2006-07-18 devnull vlong offset, toffset, totalcorrupt, v;
1278 28b49df3 2006-07-18 devnull Clump cl;
1279 28b49df3 2006-07-18 devnull ClumpInfo *bci, *ci, *eci, *xci;
1280 28b49df3 2006-07-18 devnull Cit *bcit, *cit, *ecit;
1281 28b49df3 2006-07-18 devnull Shabuf oldsha, newsha;
1282 fa325e9b 2020-01-10 cross
1283 28b49df3 2006-07-18 devnull /*
1284 28b49df3 2006-07-18 devnull * We expect to find an arena, with data, between offset
1285 28b49df3 2006-07-18 devnull * and offset+arenasize. With any luck, the data starts at
1286 28b49df3 2006-07-18 devnull * offset+ap.blocksize. The blocks have variable size and
1287 28b49df3 2006-07-18 devnull * aren't padded at all, which doesn't give us any alignment
1288 28b49df3 2006-07-18 devnull * constraints. The blocks are compressed or high entropy,
1289 28b49df3 2006-07-18 devnull * but the headers are pretty low entropy (except the score):
1290 28b49df3 2006-07-18 devnull *
1291 28b49df3 2006-07-18 devnull * type[1] (range 0 thru 9, 13)
1292 28b49df3 2006-07-18 devnull * size[2]
1293 28b49df3 2006-07-18 devnull * uncsize[2] (<= size)
1294 28b49df3 2006-07-18 devnull *
1295 28b49df3 2006-07-18 devnull * so we can look for these. We check the scores as we go,
1296 28b49df3 2006-07-18 devnull * so we can't make any wrong turns. If we find ourselves
1297 28b49df3 2006-07-18 devnull * in a dead end, scan forward looking for a new start.
1298 28b49df3 2006-07-18 devnull */
1299 28b49df3 2006-07-18 devnull
1300 28b49df3 2006-07-18 devnull resetcibuf();
1301 28b49df3 2006-07-18 devnull memset(head, 0, sizeof *head);
1302 28b49df3 2006-07-18 devnull memset(arena, 0, sizeof *arena);
1303 28b49df3 2006-07-18 devnull memset(oldscore, 0, VtScoreSize);
1304 28b49df3 2006-07-18 devnull memset(score, 0, VtScoreSize);
1305 28b49df3 2006-07-18 devnull memset(&oldsha, 0, sizeof oldsha);
1306 28b49df3 2006-07-18 devnull memset(&newsha, 0, sizeof newsha);
1307 28b49df3 2006-07-18 devnull newsha.rollback = 1;
1308 28b49df3 2006-07-18 devnull
1309 28b49df3 2006-07-18 devnull if(0){
1310 28b49df3 2006-07-18 devnull sbdebug(&oldsha, "old.sha");
1311 28b49df3 2006-07-18 devnull sbdebug(&newsha, "new.sha");
1312 28b49df3 2006-07-18 devnull }
1313 28b49df3 2006-07-18 devnull
1314 28b49df3 2006-07-18 devnull loadarenabasics(offset0, anum, head, arena);
1315 28b49df3 2006-07-18 devnull
1316 28b49df3 2006-07-18 devnull /* start the clump hunt */
1317 fa325e9b 2020-01-10 cross
1318 28b49df3 2006-07-18 devnull clumps = 0;
1319 28b49df3 2006-07-18 devnull totalcorrupt = 0;
1320 28b49df3 2006-07-18 devnull sealing = 1;
1321 28b49df3 2006-07-18 devnull boffset = offset0 + arena->blocksize;
1322 28b49df3 2006-07-18 devnull offset = boffset;
1323 28b49df3 2006-07-18 devnull eoffset = offset0+arena->size - arena->blocksize;
1324 28b49df3 2006-07-18 devnull toffset = eoffset;
1325 28b49df3 2006-07-18 devnull sp = pagein(offset0, 4*M);
1326 28b49df3 2006-07-18 devnull
1327 28b49df3 2006-07-18 devnull if(arena->diskstats.sealed){
1328 28b49df3 2006-07-18 devnull oldsha.offset = offset0;
1329 28b49df3 2006-07-18 devnull sbupdate(&oldsha, sp, offset0, 4*M);
1330 28b49df3 2006-07-18 devnull }
1331 28b49df3 2006-07-18 devnull ep = sp+4*M;
1332 28b49df3 2006-07-18 devnull p = sp + (boffset - offset0);
1333 28b49df3 2006-07-18 devnull ncib = arena->blocksize / ClumpInfoSize; /* ci per block in index */
1334 28b49df3 2006-07-18 devnull lastclumpend = offset;
1335 28b49df3 2006-07-18 devnull nbad = 0;
1336 28b49df3 2006-07-18 devnull inbad = 0;
1337 28b49df3 2006-07-18 devnull needtozero = 0;
1338 28b49df3 2006-07-18 devnull minclumps = 0;
1339 28b49df3 2006-07-18 devnull while(offset < eoffset){
1340 28b49df3 2006-07-18 devnull /*
1341 28b49df3 2006-07-18 devnull * Shift buffer if we're running out of room.
1342 28b49df3 2006-07-18 devnull */
1343 28b49df3 2006-07-18 devnull if(p+70*K >= ep){
1344 28b49df3 2006-07-18 devnull /*
1345 28b49df3 2006-07-18 devnull * Start the post SHA1 buffer. By now we should know the
1346 28b49df3 2006-07-18 devnull * clumpmagic and arena version, so we can create a
1347 28b49df3 2006-07-18 devnull * correct head block to get things going.
1348 28b49df3 2006-07-18 devnull */
1349 28b49df3 2006-07-18 devnull if(sealing && fix && newsha.offset == 0){
1350 28b49df3 2006-07-18 devnull newsha.offset = offset0;
1351 28b49df3 2006-07-18 devnull if(arena->clumpmagic == 0){
1352 28b49df3 2006-07-18 devnull if(arena->version == 0)
1353 28b49df3 2006-07-18 devnull arena->version = ArenaVersion5;
1354 28b49df3 2006-07-18 devnull arena->clumpmagic = newclumpmagic(arena->version);
1355 28b49df3 2006-07-18 devnull }
1356 28b49df3 2006-07-18 devnull head->clumpmagic = arena->clumpmagic;
1357 28b49df3 2006-07-18 devnull shahead(&newsha, offset0, head);
1358 28b49df3 2006-07-18 devnull }
1359 28b49df3 2006-07-18 devnull n = 4*M-256*K;
1360 28b49df3 2006-07-18 devnull if(sealing && fix){
1361 28b49df3 2006-07-18 devnull sbdiskhash(&newsha, bufoffset);
1362 28b49df3 2006-07-18 devnull sbupdate(&newsha, buf, bufoffset, 4*M-256*K);
1363 28b49df3 2006-07-18 devnull }
1364 28b49df3 2006-07-18 devnull pagein(bufoffset+n, 4*M);
1365 28b49df3 2006-07-18 devnull p -= n;
1366 28b49df3 2006-07-18 devnull if(arena->diskstats.sealed)
1367 28b49df3 2006-07-18 devnull sbupdate(&oldsha, buf, bufoffset, 4*M);
1368 28b49df3 2006-07-18 devnull }
1369 28b49df3 2006-07-18 devnull
1370 28b49df3 2006-07-18 devnull /*
1371 28b49df3 2006-07-18 devnull * Check for a clump at p, which is at offset in the disk.
1372 28b49df3 2006-07-18 devnull * Duplicate clumps happen in corrupted disks
1373 28b49df3 2006-07-18 devnull * (the same pattern gets written many times in a row)
1374 28b49df3 2006-07-18 devnull * and should never happen during regular use.
1375 28b49df3 2006-07-18 devnull */
1376 6932098c 2007-04-21 devnull magic = 0;
1377 28b49df3 2006-07-18 devnull if((n = isclump(p, &cl, &magic)) > 0){
1378 28b49df3 2006-07-18 devnull /*
1379 28b49df3 2006-07-18 devnull * If we were in the middle of some corrupted data,
1380 28b49df3 2006-07-18 devnull * flush a warning about it and then add any clump
1381 28b49df3 2006-07-18 devnull * info blocks as necessary.
1382 28b49df3 2006-07-18 devnull */
1383 28b49df3 2006-07-18 devnull if(inbad){
1384 28b49df3 2006-07-18 devnull inbad = 0;
1385 28b49df3 2006-07-18 devnull v = offset-lastclumpend;
1386 28b49df3 2006-07-18 devnull if(needtozero){
1387 28b49df3 2006-07-18 devnull zerorange(lastclumpend, v);
1388 28b49df3 2006-07-18 devnull sbrollback(&newsha, lastclumpend);
1389 28b49df3 2006-07-18 devnull print("corrupt clump data - %#llux+%#llux (%,llud bytes)\n",
1390 28b49df3 2006-07-18 devnull lastclumpend, v, v);
1391 28b49df3 2006-07-18 devnull }
1392 28b49df3 2006-07-18 devnull addcicorrupt(v);
1393 28b49df3 2006-07-18 devnull totalcorrupt += v;
1394 28b49df3 2006-07-18 devnull nb1 = (minclumps+ncib-1)/ncib;
1395 28b49df3 2006-07-18 devnull minclumps += (v+ClumpSize+VtMaxLumpSize-1)/(ClumpSize+VtMaxLumpSize);
1396 28b49df3 2006-07-18 devnull nb2 = (minclumps+ncib-1)/ncib;
1397 28b49df3 2006-07-18 devnull eoffset -= (nb2-nb1)*arena->blocksize;
1398 28b49df3 2006-07-18 devnull }
1399 28b49df3 2006-07-18 devnull
1400 28b49df3 2006-07-18 devnull if(haveclump(cl.info.score))
1401 c482feff 2007-05-03 devnull print("warning: duplicate clump %d %V at %#llux+%#d\n", cl.info.type, cl.info.score, offset, n);
1402 28b49df3 2006-07-18 devnull
1403 28b49df3 2006-07-18 devnull /*
1404 28b49df3 2006-07-18 devnull * If clumps use different magic numbers, we don't care.
1405 28b49df3 2006-07-18 devnull * We'll just use the first one we find and make the others
1406 28b49df3 2006-07-18 devnull * follow suit.
1407 28b49df3 2006-07-18 devnull */
1408 28b49df3 2006-07-18 devnull if(arena->clumpmagic == 0){
1409 28b49df3 2006-07-18 devnull print("clump type %d size %d score %V magic %x\n",
1410 28b49df3 2006-07-18 devnull cl.info.type, cl.info.size, cl.info.score, magic);
1411 28b49df3 2006-07-18 devnull arena->clumpmagic = magic;
1412 28b49df3 2006-07-18 devnull if(magic == _ClumpMagic)
1413 28b49df3 2006-07-18 devnull arena->version = ArenaVersion4;
1414 28b49df3 2006-07-18 devnull else
1415 28b49df3 2006-07-18 devnull arena->version = ArenaVersion5;
1416 28b49df3 2006-07-18 devnull }
1417 28b49df3 2006-07-18 devnull if(magic != arena->clumpmagic)
1418 28b49df3 2006-07-18 devnull p32(p, arena->clumpmagic);
1419 28b49df3 2006-07-18 devnull if(clumps == 0)
1420 28b49df3 2006-07-18 devnull arena->ctime = cl.time;
1421 28b49df3 2006-07-18 devnull
1422 28b49df3 2006-07-18 devnull /*
1423 28b49df3 2006-07-18 devnull * Record the clump, update arena stats,
1424 28b49df3 2006-07-18 devnull * grow clump info blocks if needed.
1425 28b49df3 2006-07-18 devnull */
1426 28b49df3 2006-07-18 devnull if(verbose > 1)
1427 fa325e9b 2020-01-10 cross print("\tclump %d: %d %V at %#llux+%#ux (%d)\n",
1428 28b49df3 2006-07-18 devnull clumps, cl.info.type, cl.info.score, offset, n, n);
1429 28b49df3 2006-07-18 devnull addcibuf(&cl.info, 0);
1430 28b49df3 2006-07-18 devnull if(minclumps%ncib == 0)
1431 28b49df3 2006-07-18 devnull eoffset -= arena->blocksize;
1432 28b49df3 2006-07-18 devnull minclumps++;
1433 28b49df3 2006-07-18 devnull clumps++;
1434 28b49df3 2006-07-18 devnull if(cl.encoding != ClumpENone)
1435 28b49df3 2006-07-18 devnull arena->diskstats.cclumps++;
1436 28b49df3 2006-07-18 devnull arena->diskstats.uncsize += cl.info.uncsize;
1437 28b49df3 2006-07-18 devnull arena->wtime = cl.time;
1438 fa325e9b 2020-01-10 cross
1439 28b49df3 2006-07-18 devnull /*
1440 28b49df3 2006-07-18 devnull * Move to next clump.
1441 28b49df3 2006-07-18 devnull */
1442 28b49df3 2006-07-18 devnull offset += n;
1443 28b49df3 2006-07-18 devnull p += n;
1444 28b49df3 2006-07-18 devnull lastclumpend = offset;
1445 28b49df3 2006-07-18 devnull }else{
1446 28b49df3 2006-07-18 devnull /*
1447 28b49df3 2006-07-18 devnull * Overwrite malformed clump data with zeros later.
1448 28b49df3 2006-07-18 devnull * For now, just record whether it needs to be overwritten.
1449 28b49df3 2006-07-18 devnull * Bad regions must be of size at least ClumpSize.
1450 28b49df3 2006-07-18 devnull * Postponing the overwriting keeps us from writing past
1451 28b49df3 2006-07-18 devnull * the end of the arena data (which might be directory data)
1452 28b49df3 2006-07-18 devnull * with zeros.
1453 28b49df3 2006-07-18 devnull */
1454 28b49df3 2006-07-18 devnull if(!inbad){
1455 28b49df3 2006-07-18 devnull inbad = 1;
1456 28b49df3 2006-07-18 devnull needtozero = 0;
1457 28b49df3 2006-07-18 devnull if(memcmp(p, zero, ClumpSize) != 0)
1458 28b49df3 2006-07-18 devnull needtozero = 1;
1459 28b49df3 2006-07-18 devnull p += ClumpSize;
1460 28b49df3 2006-07-18 devnull offset += ClumpSize;
1461 28b49df3 2006-07-18 devnull nbad++;
1462 28b49df3 2006-07-18 devnull }else{
1463 28b49df3 2006-07-18 devnull if(*p != 0)
1464 28b49df3 2006-07-18 devnull needtozero = 1;
1465 28b49df3 2006-07-18 devnull p++;
1466 28b49df3 2006-07-18 devnull offset++;
1467 28b49df3 2006-07-18 devnull }
1468 28b49df3 2006-07-18 devnull }
1469 28b49df3 2006-07-18 devnull }
1470 28b49df3 2006-07-18 devnull pageout();
1471 28b49df3 2006-07-18 devnull
1472 28b49df3 2006-07-18 devnull if(verbose)
1473 fa325e9b 2020-01-10 cross print("readable clumps: %d; min. directory entries: %d\n",
1474 28b49df3 2006-07-18 devnull clumps, minclumps);
1475 28b49df3 2006-07-18 devnull arena->diskstats.used = lastclumpend - boffset;
1476 28b49df3 2006-07-18 devnull leaked = eoffset - lastclumpend;
1477 28b49df3 2006-07-18 devnull if(verbose)
1478 28b49df3 2006-07-18 devnull print("used from %#llux to %#llux = %,lld (%,lld unused)\n",
1479 28b49df3 2006-07-18 devnull boffset, lastclumpend, arena->diskstats.used, leaked);
1480 28b49df3 2006-07-18 devnull
1481 28b49df3 2006-07-18 devnull /*
1482 28b49df3 2006-07-18 devnull * Finish the SHA1 of the old data.
1483 28b49df3 2006-07-18 devnull */
1484 28b49df3 2006-07-18 devnull if(arena->diskstats.sealed){
1485 28b49df3 2006-07-18 devnull sbdiskhash(&oldsha, toffset);
1486 28b49df3 2006-07-18 devnull readdisk(dbuf, toffset, arena->blocksize);
1487 28b49df3 2006-07-18 devnull scorecp(dbuf+arena->blocksize-VtScoreSize, zero);
1488 28b49df3 2006-07-18 devnull sbupdate(&oldsha, dbuf, toffset, arena->blocksize);
1489 28b49df3 2006-07-18 devnull sbscore(&oldsha, oldscore);
1490 28b49df3 2006-07-18 devnull }
1491 fa325e9b 2020-01-10 cross
1492 28b49df3 2006-07-18 devnull /*
1493 28b49df3 2006-07-18 devnull * If we still don't know the clump magic, the arena
1494 fa325e9b 2020-01-10 cross * must be empty. It still needs a value, so make
1495 28b49df3 2006-07-18 devnull * something up.
1496 28b49df3 2006-07-18 devnull */
1497 28b49df3 2006-07-18 devnull if(arena->version == 0)
1498 28b49df3 2006-07-18 devnull arena->version = ArenaVersion5;
1499 28b49df3 2006-07-18 devnull if(arena->clumpmagic == 0){
1500 28b49df3 2006-07-18 devnull if(arena->version == ArenaVersion4)
1501 28b49df3 2006-07-18 devnull arena->clumpmagic = _ClumpMagic;
1502 28b49df3 2006-07-18 devnull else{
1503 28b49df3 2006-07-18 devnull do
1504 28b49df3 2006-07-18 devnull arena->clumpmagic = fastrand();
1505 28b49df3 2006-07-18 devnull while(arena->clumpmagic==_ClumpMagic
1506 28b49df3 2006-07-18 devnull ||arena->clumpmagic==0);
1507 28b49df3 2006-07-18 devnull }
1508 28b49df3 2006-07-18 devnull head->clumpmagic = arena->clumpmagic;
1509 28b49df3 2006-07-18 devnull }
1510 28b49df3 2006-07-18 devnull
1511 28b49df3 2006-07-18 devnull /*
1512 28b49df3 2006-07-18 devnull * Guess at number of clumpinfo blocks to load.
1513 28b49df3 2006-07-18 devnull * If we guess high, it's no big deal. If we guess low,
1514 28b49df3 2006-07-18 devnull * we'll be forced into rewriting the whole directory.
1515 28b49df3 2006-07-18 devnull * Still not such a big deal.
1516 28b49df3 2006-07-18 devnull */
1517 28b49df3 2006-07-18 devnull if(clumps == 0 || arena->diskstats.used == totalcorrupt)
1518 28b49df3 2006-07-18 devnull goto Nocib;
1519 28b49df3 2006-07-18 devnull if(clumps < arena->diskstats.clumps)
1520 28b49df3 2006-07-18 devnull clumps = arena->diskstats.clumps;
1521 28b49df3 2006-07-18 devnull if(clumps < ncibuf)
1522 28b49df3 2006-07-18 devnull clumps = ncibuf;
1523 28b49df3 2006-07-18 devnull clumps += totalcorrupt/
1524 28b49df3 2006-07-18 devnull ((arena->diskstats.used - totalcorrupt)/clumps);
1525 28b49df3 2006-07-18 devnull clumps += totalcorrupt/2000;
1526 28b49df3 2006-07-18 devnull if(clumps < minclumps)
1527 28b49df3 2006-07-18 devnull clumps = minclumps;
1528 28b49df3 2006-07-18 devnull clumps += ncib-1;
1529 28b49df3 2006-07-18 devnull clumps -= clumps%ncib;
1530 28b49df3 2006-07-18 devnull
1531 28b49df3 2006-07-18 devnull /*
1532 28b49df3 2006-07-18 devnull * Can't write into the actual data.
1533 28b49df3 2006-07-18 devnull */
1534 28b49df3 2006-07-18 devnull v = offset0 + arena->size - arena->blocksize;
1535 28b49df3 2006-07-18 devnull v -= (clumps+ncib-1)/ncib * arena->blocksize;
1536 28b49df3 2006-07-18 devnull if(v < lastclumpend){
1537 28b49df3 2006-07-18 devnull v = offset0 + arena->size - arena->blocksize;
1538 28b49df3 2006-07-18 devnull clumps = (v-lastclumpend)/arena->blocksize * ncib;
1539 28b49df3 2006-07-18 devnull }
1540 fa325e9b 2020-01-10 cross
1541 28b49df3 2006-07-18 devnull if(clumps < minclumps)
1542 28b49df3 2006-07-18 devnull print("cannot happen?\n");
1543 28b49df3 2006-07-18 devnull
1544 28b49df3 2006-07-18 devnull /*
1545 28b49df3 2006-07-18 devnull * Check clumpinfo blocks against directory we created.
1546 28b49df3 2006-07-18 devnull * The tricky part is handling the corrupt sections of arena.
1547 28b49df3 2006-07-18 devnull * If possible, we remark just the affected directory entries
1548 28b49df3 2006-07-18 devnull * rather than slide everything down.
1549 fa325e9b 2020-01-10 cross *
1550 28b49df3 2006-07-18 devnull * Allocate clumps+1 blocks and check that we don't need
1551 28b49df3 2006-07-18 devnull * the last one at the end.
1552 28b49df3 2006-07-18 devnull */
1553 28b49df3 2006-07-18 devnull bci = loadci(offset0, arena, clumps+1);
1554 28b49df3 2006-07-18 devnull eci = bci+clumps+1;
1555 28b49df3 2006-07-18 devnull bcit = cibuf;
1556 28b49df3 2006-07-18 devnull ecit = cibuf+ncibuf;
1557 fa325e9b 2020-01-10 cross
1558 45ac814c 2007-10-29 rsc smart = 0; /* Somehow the smart code doesn't do corrupt clumps right. */
1559 28b49df3 2006-07-18 devnull Again:
1560 28b49df3 2006-07-18 devnull nbad = 0;
1561 28b49df3 2006-07-18 devnull ci = bci;
1562 28b49df3 2006-07-18 devnull for(cit=bcit; cit<ecit && ci<eci; cit++){
1563 28b49df3 2006-07-18 devnull if(cit->corrupt){
1564 28b49df3 2006-07-18 devnull vlong n, m;
1565 28b49df3 2006-07-18 devnull if(smart){
1566 28b49df3 2006-07-18 devnull /*
1567 28b49df3 2006-07-18 devnull * If we can, just mark existing entries as corrupt.
1568 28b49df3 2006-07-18 devnull */
1569 28b49df3 2006-07-18 devnull n = cit->corrupt;
1570 28b49df3 2006-07-18 devnull for(xci=ci; n>0 && xci<eci; xci++)
1571 28b49df3 2006-07-18 devnull n -= ClumpSize+xci->size;
1572 28b49df3 2006-07-18 devnull if(n > 0 || xci >= eci)
1573 28b49df3 2006-07-18 devnull goto Dumb;
1574 28b49df3 2006-07-18 devnull printed = 0;
1575 28b49df3 2006-07-18 devnull for(; ci<xci; ci++){
1576 28b49df3 2006-07-18 devnull if(verbose && ci->type != VtCorruptType){
1577 28b49df3 2006-07-18 devnull if(!printed){
1578 28b49df3 2006-07-18 devnull print("marking directory %d-%d as corrupt\n",
1579 28b49df3 2006-07-18 devnull (int)(ci-bci), (int)(xci-bci));
1580 28b49df3 2006-07-18 devnull printed = 1;
1581 28b49df3 2006-07-18 devnull }
1582 28b49df3 2006-07-18 devnull print("\ttype=%d size=%d uncsize=%d score=%V\n",
1583 28b49df3 2006-07-18 devnull ci->type, ci->size, ci->uncsize, ci->score);
1584 28b49df3 2006-07-18 devnull }
1585 28b49df3 2006-07-18 devnull ci->type = VtCorruptType;
1586 28b49df3 2006-07-18 devnull }
1587 28b49df3 2006-07-18 devnull }else{
1588 28b49df3 2006-07-18 devnull Dumb:
1589 28b49df3 2006-07-18 devnull print("\trewriting clump directory\n");
1590 28b49df3 2006-07-18 devnull /*
1591 28b49df3 2006-07-18 devnull * Otherwise, blaze a new trail.
1592 28b49df3 2006-07-18 devnull */
1593 28b49df3 2006-07-18 devnull n = cit->corrupt;
1594 28b49df3 2006-07-18 devnull while(n > 0 && ci < eci){
1595 28b49df3 2006-07-18 devnull if(n < ClumpSize)
1596 28b49df3 2006-07-18 devnull sysfatal("bad math in clump corrupt");
1597 28b49df3 2006-07-18 devnull if(n <= VtMaxLumpSize+ClumpSize)
1598 28b49df3 2006-07-18 devnull m = n;
1599 28b49df3 2006-07-18 devnull else{
1600 28b49df3 2006-07-18 devnull m = VtMaxLumpSize+ClumpSize;
1601 28b49df3 2006-07-18 devnull if(n-m < ClumpSize)
1602 28b49df3 2006-07-18 devnull m -= ClumpSize;
1603 28b49df3 2006-07-18 devnull }
1604 28b49df3 2006-07-18 devnull ci->type = VtCorruptType;
1605 28b49df3 2006-07-18 devnull ci->size = m-ClumpSize;
1606 28b49df3 2006-07-18 devnull ci->uncsize = m-ClumpSize;
1607 28b49df3 2006-07-18 devnull memset(ci->score, 0, VtScoreSize);
1608 28b49df3 2006-07-18 devnull ci++;
1609 28b49df3 2006-07-18 devnull n -= m;
1610 28b49df3 2006-07-18 devnull }
1611 28b49df3 2006-07-18 devnull }
1612 28b49df3 2006-07-18 devnull continue;
1613 28b49df3 2006-07-18 devnull }
1614 28b49df3 2006-07-18 devnull if(clumpinfocmp(&cit->ci, ci) != 0){
1615 28b49df3 2006-07-18 devnull if(verbose && (smart || verbose>1)){
1616 28b49df3 2006-07-18 devnull print("clumpinfo %d\n", (int)(ci-bci));
1617 fa325e9b 2020-01-10 cross print("\twant: %d %d %d %V\n",
1618 28b49df3 2006-07-18 devnull cit->ci.type, cit->ci.size,
1619 28b49df3 2006-07-18 devnull cit->ci.uncsize, cit->ci.score);
1620 fa325e9b 2020-01-10 cross print("\thave: %d %d %d %V\n",
1621 fa325e9b 2020-01-10 cross ci->type, ci->size,
1622 28b49df3 2006-07-18 devnull ci->uncsize, ci->score);
1623 28b49df3 2006-07-18 devnull }
1624 28b49df3 2006-07-18 devnull *ci = cit->ci;
1625 28b49df3 2006-07-18 devnull nbad++;
1626 28b49df3 2006-07-18 devnull }
1627 28b49df3 2006-07-18 devnull ci++;
1628 28b49df3 2006-07-18 devnull }
1629 28b49df3 2006-07-18 devnull if(ci >= eci || cit < ecit){
1630 28b49df3 2006-07-18 devnull print("ran out of space editing existing directory; rewriting\n");
1631 28b49df3 2006-07-18 devnull print("# eci %ld ci %ld ecit %ld cit %ld\n", eci-bci, ci-bci, ecit-bcit, cit-bcit);
1632 28b49df3 2006-07-18 devnull assert(smart); /* can't happen second time thru */
1633 28b49df3 2006-07-18 devnull smart = 0;
1634 28b49df3 2006-07-18 devnull goto Again;
1635 28b49df3 2006-07-18 devnull }
1636 fa325e9b 2020-01-10 cross
1637 28b49df3 2006-07-18 devnull assert(ci <= eci);
1638 28b49df3 2006-07-18 devnull arena->diskstats.clumps = ci-bci;
1639 28b49df3 2006-07-18 devnull eoffset = writeci(offset0, arena, bci, ci-bci);
1640 28b49df3 2006-07-18 devnull if(sealing && fix)
1641 28b49df3 2006-07-18 devnull sbrollback(&newsha, v);
1642 28b49df3 2006-07-18 devnull print("eoffset=%lld lastclumpend=%lld diff=%lld unseal=%d\n", eoffset, lastclumpend, eoffset-lastclumpend, unseal);
1643 28b49df3 2006-07-18 devnull if(lastclumpend > eoffset)
1644 28b49df3 2006-07-18 devnull print("arena directory overwrote blocks! cannot happen!\n");
1645 28b49df3 2006-07-18 devnull free(bci);
1646 28b49df3 2006-07-18 devnull if(smart && nbad)
1647 28b49df3 2006-07-18 devnull print("arena directory has %d bad or missing entries\n", nbad);
1648 28b49df3 2006-07-18 devnull Nocib:
1649 28b49df3 2006-07-18 devnull if(eoffset - lastclumpend > 64*1024 && (!arena->diskstats.sealed || unseal)){
1650 28b49df3 2006-07-18 devnull if(arena->diskstats.sealed)
1651 28b49df3 2006-07-18 devnull print("unsealing arena\n");
1652 28b49df3 2006-07-18 devnull sealing = 0;
1653 28b49df3 2006-07-18 devnull memset(oldscore, 0, VtScoreSize);
1654 28b49df3 2006-07-18 devnull }
1655 28b49df3 2006-07-18 devnull
1656 28b49df3 2006-07-18 devnull /*
1657 28b49df3 2006-07-18 devnull * Finish the SHA1 of the new data - only meaningful
1658 28b49df3 2006-07-18 devnull * if we've been writing to disk (`fix').
1659 28b49df3 2006-07-18 devnull */
1660 28b49df3 2006-07-18 devnull arena->diskstats.sealed = sealing;
1661 28b49df3 2006-07-18 devnull arena->memstats = arena->diskstats;
1662 28b49df3 2006-07-18 devnull if(sealing && fix){
1663 28b49df3 2006-07-18 devnull uchar tbuf[MaxDiskBlock];
1664 fa325e9b 2020-01-10 cross
1665 28b49df3 2006-07-18 devnull sbdiskhash(&newsha, toffset);
1666 28b49df3 2006-07-18 devnull memset(tbuf, 0, sizeof tbuf);
1667 28b49df3 2006-07-18 devnull packarena(arena, tbuf);
1668 28b49df3 2006-07-18 devnull sbupdate(&newsha, tbuf, toffset, arena->blocksize);
1669 28b49df3 2006-07-18 devnull sbscore(&newsha, score);
1670 28b49df3 2006-07-18 devnull }
1671 28b49df3 2006-07-18 devnull }
1672 28b49df3 2006-07-18 devnull
1673 28b49df3 2006-07-18 devnull void
1674 28b49df3 2006-07-18 devnull dumparena(vlong offset, int anum, Arena *arena)
1675 28b49df3 2006-07-18 devnull {
1676 28b49df3 2006-07-18 devnull char buf[1000];
1677 28b49df3 2006-07-18 devnull vlong o, e;
1678 28b49df3 2006-07-18 devnull int fd, n;
1679 fa325e9b 2020-01-10 cross
1680 28b49df3 2006-07-18 devnull snprint(buf, sizeof buf, "%s.%d", dumpbase, anum);
1681 28b49df3 2006-07-18 devnull if((fd = create(buf, OWRITE, 0666)) < 0){
1682 28b49df3 2006-07-18 devnull fprint(2, "create %s: %r\n", buf);
1683 28b49df3 2006-07-18 devnull return;
1684 28b49df3 2006-07-18 devnull }
1685 28b49df3 2006-07-18 devnull e = offset+arena->size;
1686 28b49df3 2006-07-18 devnull for(o=offset; o<e; o+=n){
1687 28b49df3 2006-07-18 devnull n = 4*M;
1688 28b49df3 2006-07-18 devnull if(o+n > e)
1689 28b49df3 2006-07-18 devnull n = e-o;
1690 28b49df3 2006-07-18 devnull if(pwrite(fd, pagein(o, n), n, o-offset) != n){
1691 28b49df3 2006-07-18 devnull fprint(2, "write %s at %#llux: %r\n", buf, o-offset);
1692 28b49df3 2006-07-18 devnull return;
1693 28b49df3 2006-07-18 devnull }
1694 28b49df3 2006-07-18 devnull }
1695 28b49df3 2006-07-18 devnull }
1696 28b49df3 2006-07-18 devnull
1697 28b49df3 2006-07-18 devnull void
1698 28b49df3 2006-07-18 devnull checkarena(vlong offset, int anum)
1699 28b49df3 2006-07-18 devnull {
1700 28b49df3 2006-07-18 devnull uchar dbuf[MaxDiskBlock];
1701 28b49df3 2006-07-18 devnull uchar *p, oldscore[VtScoreSize], score[VtScoreSize];
1702 28b49df3 2006-07-18 devnull Arena arena, oarena;
1703 28b49df3 2006-07-18 devnull ArenaHead head;
1704 28b49df3 2006-07-18 devnull Info *fmt, *fmta;
1705 28b49df3 2006-07-18 devnull int sz;
1706 fa325e9b 2020-01-10 cross
1707 28b49df3 2006-07-18 devnull print("# arena %d: offset %#llux\n", anum, offset);
1708 28b49df3 2006-07-18 devnull
1709 28b49df3 2006-07-18 devnull if(offset >= partend){
1710 28b49df3 2006-07-18 devnull print("arena offset out of bounds\n");
1711 28b49df3 2006-07-18 devnull return;
1712 28b49df3 2006-07-18 devnull }
1713 28b49df3 2006-07-18 devnull
1714 28b49df3 2006-07-18 devnull guessarena(offset, anum, &head, &arena, oldscore, score);
1715 28b49df3 2006-07-18 devnull
1716 28b49df3 2006-07-18 devnull if(verbose){
1717 28b49df3 2006-07-18 devnull print("#\tversion=%d name=%s blocksize=%d size=%z",
1718 28b49df3 2006-07-18 devnull head.version, head.name, head.blocksize, head.size);
1719 28b49df3 2006-07-18 devnull if(head.clumpmagic)
1720 28b49df3 2006-07-18 devnull print(" clumpmagic=%#.8ux", head.clumpmagic);
1721 28b49df3 2006-07-18 devnull print("\n#\tclumps=%d cclumps=%d used=%,lld uncsize=%,lld\n",
1722 28b49df3 2006-07-18 devnull arena.diskstats.clumps, arena.diskstats.cclumps,
1723 28b49df3 2006-07-18 devnull arena.diskstats.used, arena.diskstats.uncsize);
1724 28b49df3 2006-07-18 devnull print("#\tctime=%t\n", arena.ctime);
1725 28b49df3 2006-07-18 devnull print("#\twtime=%t\n", arena.wtime);
1726 28b49df3 2006-07-18 devnull if(arena.diskstats.sealed)
1727 28b49df3 2006-07-18 devnull print("#\tsealed score=%V\n", score);
1728 28b49df3 2006-07-18 devnull }
1729 28b49df3 2006-07-18 devnull
1730 28b49df3 2006-07-18 devnull if(dumpbase){
1731 28b49df3 2006-07-18 devnull dumparena(offset, anum, &arena);
1732 28b49df3 2006-07-18 devnull return;
1733 28b49df3 2006-07-18 devnull }
1734 28b49df3 2006-07-18 devnull
1735 28b49df3 2006-07-18 devnull memset(dbuf, 0, sizeof dbuf);
1736 28b49df3 2006-07-18 devnull packarenahead(&head, dbuf);
1737 28b49df3 2006-07-18 devnull p = pagein(offset, arena.blocksize);
1738 28b49df3 2006-07-18 devnull if(memcmp(dbuf, p, arena.blocksize) != 0){
1739 28b49df3 2006-07-18 devnull print("on-disk arena header incorrect\n");
1740 fa325e9b 2020-01-10 cross showdiffs(dbuf, p, arena.blocksize,
1741 28b49df3 2006-07-18 devnull arena.version==ArenaVersion4 ? headinfo4 : headinfo5);
1742 28b49df3 2006-07-18 devnull }
1743 28b49df3 2006-07-18 devnull memmove(p, dbuf, arena.blocksize);
1744 fa325e9b 2020-01-10 cross
1745 28b49df3 2006-07-18 devnull memset(dbuf, 0, sizeof dbuf);
1746 28b49df3 2006-07-18 devnull packarena(&arena, dbuf);
1747 28b49df3 2006-07-18 devnull if(arena.diskstats.sealed)
1748 28b49df3 2006-07-18 devnull scorecp(dbuf+arena.blocksize-VtScoreSize, score);
1749 28b49df3 2006-07-18 devnull p = pagein(offset+arena.size-arena.blocksize, arena.blocksize);
1750 28b49df3 2006-07-18 devnull memset(&oarena, 0, sizeof oarena);
1751 28b49df3 2006-07-18 devnull unpackarena(&oarena, p);
1752 28b49df3 2006-07-18 devnull if(arena.version == ArenaVersion4){
1753 28b49df3 2006-07-18 devnull sz = ArenaSize4;
1754 28b49df3 2006-07-18 devnull fmt = tailinfo4;
1755 28b49df3 2006-07-18 devnull fmta = tailinfo4a;
1756 28b49df3 2006-07-18 devnull }else{
1757 28b49df3 2006-07-18 devnull sz = ArenaSize5;
1758 28b49df3 2006-07-18 devnull fmt = tailinfo5;
1759 28b49df3 2006-07-18 devnull fmta = tailinfo5a;
1760 28b49df3 2006-07-18 devnull }
1761 28b49df3 2006-07-18 devnull if(p[sz] == 1){
1762 28b49df3 2006-07-18 devnull fmt = fmta;
1763 28b49df3 2006-07-18 devnull if(oarena.diskstats.sealed){
1764 28b49df3 2006-07-18 devnull /*
1765 28b49df3 2006-07-18 devnull * some arenas were sealed with the extension
1766 28b49df3 2006-07-18 devnull * before we adopted the convention that if it didn't
1767 28b49df3 2006-07-18 devnull * add new information it gets dropped.
1768 28b49df3 2006-07-18 devnull */
1769 28b49df3 2006-07-18 devnull _packarena(&arena, dbuf, 1);
1770 28b49df3 2006-07-18 devnull }
1771 28b49df3 2006-07-18 devnull }
1772 28b49df3 2006-07-18 devnull if(memcmp(dbuf, p, arena.blocksize-VtScoreSize) != 0){
1773 28b49df3 2006-07-18 devnull print("on-disk arena tail incorrect\n");
1774 28b49df3 2006-07-18 devnull showdiffs(dbuf, p, arena.blocksize-VtScoreSize, fmt);
1775 28b49df3 2006-07-18 devnull }
1776 28b49df3 2006-07-18 devnull if(arena.diskstats.sealed){
1777 28b49df3 2006-07-18 devnull if(oarena.diskstats.sealed)
1778 28b49df3 2006-07-18 devnull if(scorecmp(p+arena.blocksize-VtScoreSize, oldscore) != 0){
1779 28b49df3 2006-07-18 devnull print("on-disk arena seal score incorrect\n");
1780 28b49df3 2006-07-18 devnull print("\tcorrect=%V\n", oldscore);
1781 28b49df3 2006-07-18 devnull print("\t disk=%V\n", p+arena.blocksize-VtScoreSize);
1782 28b49df3 2006-07-18 devnull }
1783 28b49df3 2006-07-18 devnull if(fix && scorecmp(p+arena.blocksize-VtScoreSize, score) != 0){
1784 fa325e9b 2020-01-10 cross print("%ssealing arena%s: %V\n",
1785 28b49df3 2006-07-18 devnull oarena.diskstats.sealed ? "re" : "",
1786 fa325e9b 2020-01-10 cross scorecmp(oldscore, score) == 0 ?
1787 28b49df3 2006-07-18 devnull "" : " after changes", score);
1788 28b49df3 2006-07-18 devnull }
1789 28b49df3 2006-07-18 devnull }
1790 28b49df3 2006-07-18 devnull memmove(p, dbuf, arena.blocksize);
1791 fa325e9b 2020-01-10 cross
1792 28b49df3 2006-07-18 devnull pageout();
1793 28b49df3 2006-07-18 devnull }
1794 28b49df3 2006-07-18 devnull
1795 28b49df3 2006-07-18 devnull AMapN*
1796 28b49df3 2006-07-18 devnull buildamap(void)
1797 28b49df3 2006-07-18 devnull {
1798 28b49df3 2006-07-18 devnull uchar *p;
1799 28b49df3 2006-07-18 devnull vlong o;
1800 28b49df3 2006-07-18 devnull ArenaHead h;
1801 28b49df3 2006-07-18 devnull AMapN *an;
1802 28b49df3 2006-07-18 devnull AMap *m;
1803 fa325e9b 2020-01-10 cross
1804 28b49df3 2006-07-18 devnull an = vtmallocz(sizeof *an);
1805 28b49df3 2006-07-18 devnull for(o=ap.arenabase; o<partend; o+=arenasize){
1806 28b49df3 2006-07-18 devnull p = pagein(o, Block);
1807 28b49df3 2006-07-18 devnull if(unpackarenahead(&h, p) >= 0){
1808 28b49df3 2006-07-18 devnull an->map = vtrealloc(an->map, (an->n+1)*sizeof an->map[0]);
1809 28b49df3 2006-07-18 devnull m = &an->map[an->n++];
1810 28b49df3 2006-07-18 devnull m->start = o;
1811 28b49df3 2006-07-18 devnull m->stop = o+h.size;
1812 28b49df3 2006-07-18 devnull strcpy(m->name, h.name);
1813 28b49df3 2006-07-18 devnull }
1814 28b49df3 2006-07-18 devnull }
1815 fa325e9b 2020-01-10 cross return an;
1816 28b49df3 2006-07-18 devnull }
1817 28b49df3 2006-07-18 devnull
1818 28b49df3 2006-07-18 devnull void
1819 28b49df3 2006-07-18 devnull checkmap(void)
1820 28b49df3 2006-07-18 devnull {
1821 28b49df3 2006-07-18 devnull char *s;
1822 28b49df3 2006-07-18 devnull uchar *p;
1823 28b49df3 2006-07-18 devnull int i, len;
1824 28b49df3 2006-07-18 devnull AMapN *an;
1825 28b49df3 2006-07-18 devnull Fmt fmt;
1826 fa325e9b 2020-01-10 cross
1827 28b49df3 2006-07-18 devnull an = buildamap();
1828 28b49df3 2006-07-18 devnull fmtstrinit(&fmt);
1829 28b49df3 2006-07-18 devnull fmtprint(&fmt, "%ud\n", an->n);
1830 28b49df3 2006-07-18 devnull for(i=0; i<an->n; i++)
1831 28b49df3 2006-07-18 devnull fmtprint(&fmt, "%s\t%lld\t%lld\n",
1832 28b49df3 2006-07-18 devnull an->map[i].name, an->map[i].start, an->map[i].stop);
1833 28b49df3 2006-07-18 devnull s = fmtstrflush(&fmt);
1834 28b49df3 2006-07-18 devnull len = strlen(s);
1835 28b49df3 2006-07-18 devnull if(len > ap.tabsize){
1836 28b49df3 2006-07-18 devnull print("arena partition map too long: need %z bytes have %z\n",
1837 28b49df3 2006-07-18 devnull (vlong)len, (vlong)ap.tabsize);
1838 28b49df3 2006-07-18 devnull len = ap.tabsize;
1839 28b49df3 2006-07-18 devnull }
1840 fa325e9b 2020-01-10 cross
1841 28b49df3 2006-07-18 devnull if(ap.tabsize >= 4*M){ /* can't happen - max arenas is 2000 */
1842 28b49df3 2006-07-18 devnull print("arena partition map *way* too long\n");
1843 28b49df3 2006-07-18 devnull return;
1844 28b49df3 2006-07-18 devnull }
1845 28b49df3 2006-07-18 devnull
1846 28b49df3 2006-07-18 devnull p = pagein(ap.tabbase, ap.tabsize);
1847 28b49df3 2006-07-18 devnull if(memcmp(p, s, len) != 0){
1848 28b49df3 2006-07-18 devnull print("arena partition map incorrect; rewriting.\n");
1849 28b49df3 2006-07-18 devnull memmove(p, s, len);
1850 28b49df3 2006-07-18 devnull }
1851 28b49df3 2006-07-18 devnull pageout();
1852 28b49df3 2006-07-18 devnull }
1853 28b49df3 2006-07-18 devnull
1854 28b49df3 2006-07-18 devnull int mainstacksize = 512*1024;
1855 28b49df3 2006-07-18 devnull
1856 28b49df3 2006-07-18 devnull void
1857 28b49df3 2006-07-18 devnull threadmain(int argc, char **argv)
1858 28b49df3 2006-07-18 devnull {
1859 28b49df3 2006-07-18 devnull int mode;
1860 fa325e9b 2020-01-10 cross
1861 28b49df3 2006-07-18 devnull mode = OREAD;
1862 fa325e9b 2020-01-10 cross readonly = 1;
1863 28b49df3 2006-07-18 devnull ARGBEGIN{
1864 28b49df3 2006-07-18 devnull case 'U':
1865 28b49df3 2006-07-18 devnull unseal = 1;
1866 28b49df3 2006-07-18 devnull break;
1867 28b49df3 2006-07-18 devnull case 'a':
1868 28b49df3 2006-07-18 devnull arenasize = unittoull(EARGF(usage()));
1869 28b49df3 2006-07-18 devnull break;
1870 28b49df3 2006-07-18 devnull case 'b':
1871 28b49df3 2006-07-18 devnull ap.blocksize = unittoull(EARGF(usage()));
1872 28b49df3 2006-07-18 devnull break;
1873 28b49df3 2006-07-18 devnull case 'f':
1874 28b49df3 2006-07-18 devnull fix = 1;
1875 28b49df3 2006-07-18 devnull mode = ORDWR;
1876 28b49df3 2006-07-18 devnull readonly = 0;
1877 28b49df3 2006-07-18 devnull break;
1878 28b49df3 2006-07-18 devnull case 'n':
1879 28b49df3 2006-07-18 devnull basename = EARGF(usage());
1880 28b49df3 2006-07-18 devnull break;
1881 28b49df3 2006-07-18 devnull case 'v':
1882 28b49df3 2006-07-18 devnull verbose++;
1883 28b49df3 2006-07-18 devnull break;
1884 28b49df3 2006-07-18 devnull case 'x':
1885 28b49df3 2006-07-18 devnull dumpbase = EARGF(usage());
1886 28b49df3 2006-07-18 devnull break;
1887 28b49df3 2006-07-18 devnull default:
1888 28b49df3 2006-07-18 devnull usage();
1889 28b49df3 2006-07-18 devnull }ARGEND
1890 fa325e9b 2020-01-10 cross
1891 28b49df3 2006-07-18 devnull if(argc != 1 && argc != 2)
1892 28b49df3 2006-07-18 devnull usage();
1893 28b49df3 2006-07-18 devnull
1894 28b49df3 2006-07-18 devnull file = argv[0];
1895 fa325e9b 2020-01-10 cross
1896 28b49df3 2006-07-18 devnull ventifmtinstall();
1897 28b49df3 2006-07-18 devnull fmtinstall('z', zfmt);
1898 28b49df3 2006-07-18 devnull fmtinstall('t', tfmt);
1899 28b49df3 2006-07-18 devnull quotefmtinstall();
1900 fa325e9b 2020-01-10 cross
1901 28b49df3 2006-07-18 devnull part = initpart(file, mode|ODIRECT);
1902 28b49df3 2006-07-18 devnull if(part == nil)
1903 28b49df3 2006-07-18 devnull sysfatal("can't open %s: %r", file);
1904 28b49df3 2006-07-18 devnull partend = part->size;
1905 fa325e9b 2020-01-10 cross
1906 c482feff 2007-05-03 devnull if(isonearena()){
1907 c482feff 2007-05-03 devnull checkarena(0, -1);
1908 c482feff 2007-05-03 devnull threadexitsall(nil);
1909 c482feff 2007-05-03 devnull }
1910 28b49df3 2006-07-18 devnull checkarenas(argc > 1 ? argv[1] : nil);
1911 28b49df3 2006-07-18 devnull checkmap();
1912 28b49df3 2006-07-18 devnull threadexitsall(nil);
1913 28b49df3 2006-07-18 devnull }