xref: /plan9-contrib/sys/src/cmd/venti/srv/cmparenas.c (revision 368c31ab13393dea083228fdd1c3445076f83a4b)
1*368c31abSDavid du Colombier #include "stdinc.h"
2*368c31abSDavid du Colombier #include "dat.h"
3*368c31abSDavid du Colombier #include "fns.h"
4*368c31abSDavid du Colombier 
5*368c31abSDavid du Colombier static int	verbose;
6*368c31abSDavid du Colombier static int	fd;
7*368c31abSDavid du Colombier static int	fd1;
8*368c31abSDavid du Colombier static uchar	*data;
9*368c31abSDavid du Colombier static uchar	*data1;
10*368c31abSDavid du Colombier static int	blocksize;
11*368c31abSDavid du Colombier static int	sleepms;
12*368c31abSDavid du Colombier 
13*368c31abSDavid du Colombier void
usage(void)14*368c31abSDavid du Colombier usage(void)
15*368c31abSDavid du Colombier {
16*368c31abSDavid du Colombier 	fprint(2, "usage: cmparenas [-b blocksize] [-s ms] [-v] arenapart1 arenapart2 [name...]]\n");
17*368c31abSDavid du Colombier 	threadexitsall(0);
18*368c31abSDavid du Colombier }
19*368c31abSDavid du Colombier 
20*368c31abSDavid du Colombier static int
preadblock(int fd,uchar * buf,int n,vlong off)21*368c31abSDavid du Colombier preadblock(int fd, uchar *buf, int n, vlong off)
22*368c31abSDavid du Colombier {
23*368c31abSDavid du Colombier 	int nr, m;
24*368c31abSDavid du Colombier 
25*368c31abSDavid du Colombier 	for(nr = 0; nr < n; nr += m){
26*368c31abSDavid du Colombier 		m = n - nr;
27*368c31abSDavid du Colombier 		m = pread(fd, &buf[nr], m, off+nr);
28*368c31abSDavid du Colombier 		if(m <= 0){
29*368c31abSDavid du Colombier 			if(m == 0)
30*368c31abSDavid du Colombier 				werrstr("early eof");
31*368c31abSDavid du Colombier 			return -1;
32*368c31abSDavid du Colombier 		}
33*368c31abSDavid du Colombier 	}
34*368c31abSDavid du Colombier 	return 0;
35*368c31abSDavid du Colombier }
36*368c31abSDavid du Colombier 
37*368c31abSDavid du Colombier static int
readblock(int fd,uchar * buf,int n)38*368c31abSDavid du Colombier readblock(int fd, uchar *buf, int n)
39*368c31abSDavid du Colombier {
40*368c31abSDavid du Colombier 	int nr, m;
41*368c31abSDavid du Colombier 
42*368c31abSDavid du Colombier 	for(nr = 0; nr < n; nr += m){
43*368c31abSDavid du Colombier 		m = n - nr;
44*368c31abSDavid du Colombier 		m = read(fd, &buf[nr], m);
45*368c31abSDavid du Colombier 		if(m <= 0){
46*368c31abSDavid du Colombier 			if(m == 0)
47*368c31abSDavid du Colombier 				werrstr("early eof");
48*368c31abSDavid du Colombier 			return -1;
49*368c31abSDavid du Colombier 		}
50*368c31abSDavid du Colombier 	}
51*368c31abSDavid du Colombier 	return 0;
52*368c31abSDavid du Colombier }
53*368c31abSDavid du Colombier 
54*368c31abSDavid du Colombier static int
printheader(char * name,ArenaHead * head,int fd)55*368c31abSDavid du Colombier printheader(char *name, ArenaHead *head, int fd)
56*368c31abSDavid du Colombier {
57*368c31abSDavid du Colombier 	Arena arena;
58*368c31abSDavid du Colombier 	vlong baseoff, lo, hi, off;
59*368c31abSDavid du Colombier 	int clumpmax;
60*368c31abSDavid du Colombier 
61*368c31abSDavid du Colombier 	off = seek(fd, 0, 1);
62*368c31abSDavid du Colombier 	seek(fd, off + head->size - head->blocksize, 0);
63*368c31abSDavid du Colombier 	if(readblock(fd, data, head->blocksize) < 0){
64*368c31abSDavid du Colombier 		fprint(2, "%s: reading arena tail: %r\n", name);
65*368c31abSDavid du Colombier 		return -1;
66*368c31abSDavid du Colombier 	}
67*368c31abSDavid du Colombier 	seek(fd, off, 0);
68*368c31abSDavid du Colombier 
69*368c31abSDavid du Colombier 	memset(&arena, 0, sizeof arena);
70*368c31abSDavid du Colombier 	if(unpackarena(&arena, data) < 0){
71*368c31abSDavid du Colombier 		fprint(2, "%s: unpack arena tail: %r\n", name);
72*368c31abSDavid du Colombier 		return -1;
73*368c31abSDavid du Colombier 	}
74*368c31abSDavid du Colombier 	arena.blocksize = head->blocksize;
75*368c31abSDavid du Colombier 	arena.base = off + head->blocksize;
76*368c31abSDavid du Colombier 	arena.clumpmax = arena.blocksize / ClumpInfoSize;
77*368c31abSDavid du Colombier 	arena.size = head->size - 2*head->blocksize;
78*368c31abSDavid du Colombier 
79*368c31abSDavid du Colombier 	fprint(2, "%s: base=%llx size=%llx blocksize=%x\n", name, off, head->size, head->blocksize);
80*368c31abSDavid du Colombier 
81*368c31abSDavid du Colombier 	baseoff = head->blocksize;
82*368c31abSDavid du Colombier 	fprint(2, "\t%llx-%llx: head\n", (vlong)0, baseoff);
83*368c31abSDavid du Colombier 	lo = baseoff;
84*368c31abSDavid du Colombier 	hi = baseoff + arena.diskstats.used;
85*368c31abSDavid du Colombier 	fprint(2, "\t%llx-%llx: data (%llx)\n", lo, hi, hi - lo);
86*368c31abSDavid du Colombier 	hi = head->size - head->blocksize;
87*368c31abSDavid du Colombier 	clumpmax = head->blocksize / ClumpInfoSize;
88*368c31abSDavid du Colombier 	if(clumpmax > 0)
89*368c31abSDavid du Colombier 		lo = hi - (u64int)arena.diskstats.clumps/clumpmax * head->blocksize;
90*368c31abSDavid du Colombier 	else
91*368c31abSDavid du Colombier 		lo = hi;
92*368c31abSDavid du Colombier 	fprint(2, "\t%llx-%llx: clumps (%llx)\n", lo, hi, hi - lo);
93*368c31abSDavid du Colombier 	fprint(2, "\t%llx-%llx: tail\n", hi, hi + head->blocksize);
94*368c31abSDavid du Colombier 
95*368c31abSDavid du Colombier 	fprint(2, "arena:\n");
96*368c31abSDavid du Colombier 	printarena(2, &arena);
97*368c31abSDavid du Colombier 	return 0;
98*368c31abSDavid du Colombier }
99*368c31abSDavid du Colombier 
100*368c31abSDavid du Colombier static void
cmparena(char * name,vlong len)101*368c31abSDavid du Colombier cmparena(char *name, vlong len)
102*368c31abSDavid du Colombier {
103*368c31abSDavid du Colombier 	ArenaHead head;
104*368c31abSDavid du Colombier 	DigestState s;
105*368c31abSDavid du Colombier 	u64int n, e;
106*368c31abSDavid du Colombier 	u32int bs;
107*368c31abSDavid du Colombier 	int i, j;
108*368c31abSDavid du Colombier 	char buf[20];
109*368c31abSDavid du Colombier 
110*368c31abSDavid du Colombier 	fprint(2, "cmp %s\n", name);
111*368c31abSDavid du Colombier 
112*368c31abSDavid du Colombier 	memset(&s, 0, sizeof s);
113*368c31abSDavid du Colombier 
114*368c31abSDavid du Colombier 	/*
115*368c31abSDavid du Colombier 	 * read a little bit, which will include the header
116*368c31abSDavid du Colombier 	 */
117*368c31abSDavid du Colombier 	if(readblock(fd, data, HeadSize) < 0){
118*368c31abSDavid du Colombier 		fprint(2, "%s: reading header: %r\n", name);
119*368c31abSDavid du Colombier 		return;
120*368c31abSDavid du Colombier 	}
121*368c31abSDavid du Colombier 	if(unpackarenahead(&head, data) < 0){
122*368c31abSDavid du Colombier 		fprint(2, "%s: corrupt arena header: %r\n", name);
123*368c31abSDavid du Colombier 		return;
124*368c31abSDavid du Colombier 	}
125*368c31abSDavid du Colombier 	if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
126*368c31abSDavid du Colombier 		fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
127*368c31abSDavid du Colombier 	if(len != 0 && len != head.size)
128*368c31abSDavid du Colombier 		fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
129*368c31abSDavid du Colombier 	if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
130*368c31abSDavid du Colombier 		fprint(2, "%s: warning: unexpected name %s\n", name, head.name);
131*368c31abSDavid du Colombier 
132*368c31abSDavid du Colombier 	if(readblock(fd1, data1, HeadSize) < 0){
133*368c31abSDavid du Colombier 		fprint(2, "%s: reading header: %r\n", name);
134*368c31abSDavid du Colombier 		return;
135*368c31abSDavid du Colombier 	}
136*368c31abSDavid du Colombier 	if(unpackarenahead(&head, data) < 0){
137*368c31abSDavid du Colombier 		fprint(2, "%s: corrupt arena header: %r\n", name);
138*368c31abSDavid du Colombier 		return;
139*368c31abSDavid du Colombier 	}
140*368c31abSDavid du Colombier 	if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
141*368c31abSDavid du Colombier 		fprint(2, "%s: warning: unknown arena version %d\n", name, head.version);
142*368c31abSDavid du Colombier 	if(len != 0 && len != head.size)
143*368c31abSDavid du Colombier 		fprint(2, "%s: warning: unexpected length %lld != %lld\n", name, head.size, len);
144*368c31abSDavid du Colombier 	if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
145*368c31abSDavid du Colombier 		fprint(2, "%s: warning: unexpected name %s\n", name, head.name);
146*368c31abSDavid du Colombier 
147*368c31abSDavid du Colombier 	seek(fd, -HeadSize, 1);
148*368c31abSDavid du Colombier 	seek(fd1, -HeadSize, 1);
149*368c31abSDavid du Colombier 
150*368c31abSDavid du Colombier 	if(printheader(name, &head, fd) < 0)
151*368c31abSDavid du Colombier 		return;
152*368c31abSDavid du Colombier 
153*368c31abSDavid du Colombier 	/*
154*368c31abSDavid du Colombier 	 * now we know how much to read
155*368c31abSDavid du Colombier 	 * read everything but the last block, which is special
156*368c31abSDavid du Colombier 	 */
157*368c31abSDavid du Colombier 	e = head.size;
158*368c31abSDavid du Colombier 	bs = blocksize;
159*368c31abSDavid du Colombier 	for(n = 0; n < e; n += bs){
160*368c31abSDavid du Colombier 		if(n + bs > e)
161*368c31abSDavid du Colombier 			bs = e - n;
162*368c31abSDavid du Colombier 		if(readblock(fd, data, bs) < 0){
163*368c31abSDavid du Colombier 			fprint(2, "%s: read data: %r\n", name);
164*368c31abSDavid du Colombier 			return;
165*368c31abSDavid du Colombier 		}
166*368c31abSDavid du Colombier 		if(readblock(fd1, data1, bs) < 0){
167*368c31abSDavid du Colombier 			fprint(2, "%s: read data: %r\n", name);
168*368c31abSDavid du Colombier 			return;
169*368c31abSDavid du Colombier 		}
170*368c31abSDavid du Colombier 		if(memcmp(data, data1, bs) != 0){
171*368c31abSDavid du Colombier 			print("mismatch at %llx\n", n);
172*368c31abSDavid du Colombier 			for(i=0; i<bs; i+=16){
173*368c31abSDavid du Colombier 				if(memcmp(data+i, data1+i, 16) != 0){
174*368c31abSDavid du Colombier 					snprint(buf, sizeof buf, "%llx", n+i);
175*368c31abSDavid du Colombier 					print("%s ", buf);
176*368c31abSDavid du Colombier 					for(j=0; j<16; j++){
177*368c31abSDavid du Colombier 						print(" %.2ux", data[i+j]);
178*368c31abSDavid du Colombier 						if(j == 7)
179*368c31abSDavid du Colombier 							print(" -");
180*368c31abSDavid du Colombier 					}
181*368c31abSDavid du Colombier 					print("\n");
182*368c31abSDavid du Colombier 					print("%*s ", (int)strlen(buf), "");
183*368c31abSDavid du Colombier 					for(j=0; j<16; j++){
184*368c31abSDavid du Colombier 						print(" %.2ux", data1[i+j]);
185*368c31abSDavid du Colombier 						if(j == 7)
186*368c31abSDavid du Colombier 							print(" -");
187*368c31abSDavid du Colombier 					}
188*368c31abSDavid du Colombier 					print("\n");
189*368c31abSDavid du Colombier 				}
190*368c31abSDavid du Colombier 			}
191*368c31abSDavid du Colombier 		}
192*368c31abSDavid du Colombier 	}
193*368c31abSDavid du Colombier }
194*368c31abSDavid du Colombier 
195*368c31abSDavid du Colombier static int
shouldcheck(char * name,char ** s,int n)196*368c31abSDavid du Colombier shouldcheck(char *name, char **s, int n)
197*368c31abSDavid du Colombier {
198*368c31abSDavid du Colombier 	int i;
199*368c31abSDavid du Colombier 
200*368c31abSDavid du Colombier 	if(n == 0)
201*368c31abSDavid du Colombier 		return 1;
202*368c31abSDavid du Colombier 
203*368c31abSDavid du Colombier 	for(i=0; i<n; i++){
204*368c31abSDavid du Colombier 		if(s[i] && strcmp(name, s[i]) == 0){
205*368c31abSDavid du Colombier 			s[i] = nil;
206*368c31abSDavid du Colombier 			return 1;
207*368c31abSDavid du Colombier 		}
208*368c31abSDavid du Colombier 	}
209*368c31abSDavid du Colombier 	return 0;
210*368c31abSDavid du Colombier }
211*368c31abSDavid du Colombier 
212*368c31abSDavid du Colombier char *
readap(int fd,ArenaPart * ap)213*368c31abSDavid du Colombier readap(int fd, ArenaPart *ap)
214*368c31abSDavid du Colombier {
215*368c31abSDavid du Colombier 	char *table;
216*368c31abSDavid du Colombier 
217*368c31abSDavid du Colombier 	if(preadblock(fd, data, 8192, PartBlank) < 0)
218*368c31abSDavid du Colombier 		sysfatal("read arena part header: %r");
219*368c31abSDavid du Colombier 	if(unpackarenapart(ap, data) < 0)
220*368c31abSDavid du Colombier 		sysfatal("corrupted arena part header: %r");
221*368c31abSDavid du Colombier 	fprint(2, "# arena part version=%d blocksize=%d arenabase=%d\n",
222*368c31abSDavid du Colombier 		ap->version, ap->blocksize, ap->arenabase);
223*368c31abSDavid du Colombier 	ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1);
224*368c31abSDavid du Colombier 	ap->tabsize = ap->arenabase - ap->tabbase;
225*368c31abSDavid du Colombier 	table = malloc(ap->tabsize+1);
226*368c31abSDavid du Colombier 	if(preadblock(fd, (uchar*)table, ap->tabsize, ap->tabbase) < 0)
227*368c31abSDavid du Colombier 		sysfatal("reading arena part directory: %r");
228*368c31abSDavid du Colombier 	table[ap->tabsize] = 0;
229*368c31abSDavid du Colombier 	return table;
230*368c31abSDavid du Colombier }
231*368c31abSDavid du Colombier 
232*368c31abSDavid du Colombier void
threadmain(int argc,char * argv[])233*368c31abSDavid du Colombier threadmain(int argc, char *argv[])
234*368c31abSDavid du Colombier {
235*368c31abSDavid du Colombier 	int i, nline;
236*368c31abSDavid du Colombier 	char *p, *q, *table, *table1, *f[10], line[256];
237*368c31abSDavid du Colombier 	vlong start, stop;
238*368c31abSDavid du Colombier 	ArenaPart ap;
239*368c31abSDavid du Colombier 	ArenaPart ap1;
240*368c31abSDavid du Colombier 
241*368c31abSDavid du Colombier 	ventifmtinstall();
242*368c31abSDavid du Colombier 	blocksize = MaxIoSize;
243*368c31abSDavid du Colombier 	ARGBEGIN{
244*368c31abSDavid du Colombier 	case 'b':
245*368c31abSDavid du Colombier 		blocksize = unittoull(EARGF(usage()));
246*368c31abSDavid du Colombier 		break;
247*368c31abSDavid du Colombier 	case 's':
248*368c31abSDavid du Colombier 		sleepms = atoi(EARGF(usage()));
249*368c31abSDavid du Colombier 		break;
250*368c31abSDavid du Colombier 	case 'v':
251*368c31abSDavid du Colombier 		verbose++;
252*368c31abSDavid du Colombier 		break;
253*368c31abSDavid du Colombier 	default:
254*368c31abSDavid du Colombier 		usage();
255*368c31abSDavid du Colombier 		break;
256*368c31abSDavid du Colombier 	}ARGEND
257*368c31abSDavid du Colombier 
258*368c31abSDavid du Colombier 	if(argc < 2)
259*368c31abSDavid du Colombier 		usage();
260*368c31abSDavid du Colombier 
261*368c31abSDavid du Colombier 	data = vtmalloc(blocksize);
262*368c31abSDavid du Colombier 	data1 = vtmalloc(blocksize);
263*368c31abSDavid du Colombier 	if((fd = open(argv[0], OREAD)) < 0)
264*368c31abSDavid du Colombier 		sysfatal("open %s: %r", argv[0]);
265*368c31abSDavid du Colombier 	if((fd1 = open(argv[1], OREAD)) < 0)
266*368c31abSDavid du Colombier 		sysfatal("open %s: %r", argv[0]);
267*368c31abSDavid du Colombier 
268*368c31abSDavid du Colombier 	table = readap(fd, &ap);
269*368c31abSDavid du Colombier 	table1 = readap(fd1, &ap1);
270*368c31abSDavid du Colombier 	if(strcmp(table, table1) != 0)
271*368c31abSDavid du Colombier 		sysfatal("arena partitions do not have identical tables");
272*368c31abSDavid du Colombier 
273*368c31abSDavid du Colombier 	nline = atoi(table);
274*368c31abSDavid du Colombier 	p = strchr(table, '\n');
275*368c31abSDavid du Colombier 	if(p)
276*368c31abSDavid du Colombier 		p++;
277*368c31abSDavid du Colombier 	for(i=0; i<nline; i++){
278*368c31abSDavid du Colombier 		if(p == nil){
279*368c31abSDavid du Colombier 			fprint(2, "warning: unexpected arena table end\n");
280*368c31abSDavid du Colombier 			break;
281*368c31abSDavid du Colombier 		}
282*368c31abSDavid du Colombier 		q = strchr(p, '\n');
283*368c31abSDavid du Colombier 		if(q)
284*368c31abSDavid du Colombier 			*q++ = 0;
285*368c31abSDavid du Colombier 		if(strlen(p) >= sizeof line){
286*368c31abSDavid du Colombier 			fprint(2, "warning: long arena table line: %s\n", p);
287*368c31abSDavid du Colombier 			p = q;
288*368c31abSDavid du Colombier 			continue;
289*368c31abSDavid du Colombier 		}
290*368c31abSDavid du Colombier 		strcpy(line, p);
291*368c31abSDavid du Colombier 		memset(f, 0, sizeof f);
292*368c31abSDavid du Colombier 		if(tokenize(line, f, nelem(f)) < 3){
293*368c31abSDavid du Colombier 			fprint(2, "warning: bad arena table line: %s\n", p);
294*368c31abSDavid du Colombier 			p = q;
295*368c31abSDavid du Colombier 			continue;
296*368c31abSDavid du Colombier 		}
297*368c31abSDavid du Colombier 		p = q;
298*368c31abSDavid du Colombier 		if(shouldcheck(f[0], argv+1, argc-1)){
299*368c31abSDavid du Colombier 			start = strtoull(f[1], 0, 0);
300*368c31abSDavid du Colombier 			stop = strtoull(f[2], 0, 0);
301*368c31abSDavid du Colombier 			if(stop <= start){
302*368c31abSDavid du Colombier 				fprint(2, "%s: bad start,stop %lld,%lld\n", f[0], stop, start);
303*368c31abSDavid du Colombier 				continue;
304*368c31abSDavid du Colombier 			}
305*368c31abSDavid du Colombier 			if(seek(fd, start, 0) < 0)
306*368c31abSDavid du Colombier 				fprint(2, "%s: seek to start: %r\n", f[0]);
307*368c31abSDavid du Colombier 			if(seek(fd1, start, 0) < 0)
308*368c31abSDavid du Colombier 				fprint(2, "%s: seek to start: %r\n", f[0]);
309*368c31abSDavid du Colombier 			cmparena(f[0], stop - start);
310*368c31abSDavid du Colombier 		}
311*368c31abSDavid du Colombier 	}
312*368c31abSDavid du Colombier 	for(i=2; i<argc; i++)
313*368c31abSDavid du Colombier 		if(argv[i] != 0)
314*368c31abSDavid du Colombier 			fprint(2, "%s: did not find arena\n", argv[i]);
315*368c31abSDavid du Colombier 
316*368c31abSDavid du Colombier 	threadexitsall(nil);
317*368c31abSDavid du Colombier }
318