xref: /plan9/sys/src/cmd/venti/srv/lump.c (revision f9e1cf08d3be51592e03e639fc848a68dc31a55e)
1368c31abSDavid du Colombier #include "stdinc.h"
2368c31abSDavid du Colombier #include "dat.h"
3368c31abSDavid du Colombier #include "fns.h"
4368c31abSDavid du Colombier 
5368c31abSDavid du Colombier int			syncwrites = 0;
6368c31abSDavid du Colombier int			queuewrites = 0;
7368c31abSDavid du Colombier int			writestodevnull = 0;
8368c31abSDavid du Colombier int			verifywrites = 0;
9368c31abSDavid du Colombier 
10*f9e1cf08SDavid du Colombier static Packet		*readilump(Lump *u, IAddr *ia, u8int *score);
11368c31abSDavid du Colombier 
12368c31abSDavid du Colombier /*
13368c31abSDavid du Colombier  * Some of this logic is duplicated in hdisk.c
14368c31abSDavid du Colombier  */
15368c31abSDavid du Colombier Packet*
readlump(u8int * score,int type,u32int size,int * cached)16368c31abSDavid du Colombier readlump(u8int *score, int type, u32int size, int *cached)
17368c31abSDavid du Colombier {
18368c31abSDavid du Colombier 	Lump *u;
19368c31abSDavid du Colombier 	Packet *p;
20368c31abSDavid du Colombier 	IAddr ia;
21368c31abSDavid du Colombier 	u32int n;
22368c31abSDavid du Colombier 
23368c31abSDavid du Colombier 	trace(TraceLump, "readlump enter");
24368c31abSDavid du Colombier /*
25368c31abSDavid du Colombier 	qlock(&stats.lock);
26368c31abSDavid du Colombier 	stats.lumpreads++;
27368c31abSDavid du Colombier 	qunlock(&stats.lock);
28368c31abSDavid du Colombier */
29368c31abSDavid du Colombier 	if(scorecmp(score, zeroscore) == 0)
30368c31abSDavid du Colombier 		return packetalloc();
31368c31abSDavid du Colombier 	u = lookuplump(score, type);
32368c31abSDavid du Colombier 	if(u->data != nil){
33368c31abSDavid du Colombier 		trace(TraceLump, "readlump lookuplump hit");
34368c31abSDavid du Colombier 		if(cached)
35368c31abSDavid du Colombier 			*cached = 1;
36368c31abSDavid du Colombier 		n = packetsize(u->data);
37368c31abSDavid du Colombier 		if(n > size){
38368c31abSDavid du Colombier 			seterr(EOk, "read too small: asked for %d need at least %d", size, n);
39368c31abSDavid du Colombier 			putlump(u);
40368c31abSDavid du Colombier 
41368c31abSDavid du Colombier 			return nil;
42368c31abSDavid du Colombier 		}
43368c31abSDavid du Colombier 		p = packetdup(u->data, 0, n);
44368c31abSDavid du Colombier 		putlump(u);
45368c31abSDavid du Colombier 		return p;
46368c31abSDavid du Colombier 	}
47368c31abSDavid du Colombier 
48368c31abSDavid du Colombier 	if(cached)
49368c31abSDavid du Colombier 		*cached = 0;
50368c31abSDavid du Colombier 
51*f9e1cf08SDavid du Colombier 	if(lookupscore(score, type, &ia) < 0){
52368c31abSDavid du Colombier 		/* ZZZ place to check for someone trying to guess scores */
53368c31abSDavid du Colombier 		seterr(EOk, "no block with score %V/%d exists", score, type);
54368c31abSDavid du Colombier 
55368c31abSDavid du Colombier 		putlump(u);
56368c31abSDavid du Colombier 		return nil;
57368c31abSDavid du Colombier 	}
58368c31abSDavid du Colombier 	if(ia.size > size){
59368c31abSDavid du Colombier 		seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
60368c31abSDavid du Colombier 
61368c31abSDavid du Colombier 		putlump(u);
62368c31abSDavid du Colombier 		return nil;
63368c31abSDavid du Colombier 	}
64368c31abSDavid du Colombier 
65368c31abSDavid du Colombier 	trace(TraceLump, "readlump readilump");
66*f9e1cf08SDavid du Colombier 	p = readilump(u, &ia, score);
67368c31abSDavid du Colombier 	putlump(u);
68368c31abSDavid du Colombier 
69368c31abSDavid du Colombier 	trace(TraceLump, "readlump exit");
70368c31abSDavid du Colombier 	return p;
71368c31abSDavid du Colombier }
72368c31abSDavid du Colombier 
73368c31abSDavid du Colombier /*
74368c31abSDavid du Colombier  * save away a lump, and return it's score.
75368c31abSDavid du Colombier  * doesn't store duplicates, but checks that the data is really the same.
76368c31abSDavid du Colombier  */
77368c31abSDavid du Colombier int
writelump(Packet * p,u8int * score,int type,u32int creator,uint ms)78368c31abSDavid du Colombier writelump(Packet *p, u8int *score, int type, u32int creator, uint ms)
79368c31abSDavid du Colombier {
80368c31abSDavid du Colombier 	Lump *u;
81368c31abSDavid du Colombier 	int ok;
82368c31abSDavid du Colombier 
83368c31abSDavid du Colombier /*
84368c31abSDavid du Colombier 	qlock(&stats.lock);
85368c31abSDavid du Colombier 	stats.lumpwrites++;
86368c31abSDavid du Colombier 	qunlock(&stats.lock);
87368c31abSDavid du Colombier */
88368c31abSDavid du Colombier 
89368c31abSDavid du Colombier 	packetsha1(p, score);
90368c31abSDavid du Colombier 	if(packetsize(p) == 0 || writestodevnull==1){
91368c31abSDavid du Colombier 		packetfree(p);
92368c31abSDavid du Colombier 		return 0;
93368c31abSDavid du Colombier 	}
94368c31abSDavid du Colombier 
95368c31abSDavid du Colombier 	u = lookuplump(score, type);
96368c31abSDavid du Colombier 	if(u->data != nil){
97368c31abSDavid du Colombier 		ok = 0;
98368c31abSDavid du Colombier 		if(packetcmp(p, u->data) != 0){
99368c31abSDavid du Colombier 			uchar nscore[VtScoreSize];
100368c31abSDavid du Colombier 
101368c31abSDavid du Colombier 			packetsha1(u->data, nscore);
102368c31abSDavid du Colombier 			if(scorecmp(u->score, score) != 0)
103368c31abSDavid du Colombier 				seterr(EStrange, "lookuplump returned bad score %V not %V", u->score, score);
104368c31abSDavid du Colombier 			else if(scorecmp(u->score, nscore) != 0)
105368c31abSDavid du Colombier 				seterr(EStrange, "lookuplump returned bad data %V not %V", nscore, u->score);
106368c31abSDavid du Colombier 			else
107368c31abSDavid du Colombier 				seterr(EStrange, "score collision %V", score);
108368c31abSDavid du Colombier 			ok = -1;
109368c31abSDavid du Colombier 		}
110368c31abSDavid du Colombier 		packetfree(p);
111368c31abSDavid du Colombier 		putlump(u);
112368c31abSDavid du Colombier 		return ok;
113368c31abSDavid du Colombier 	}
114368c31abSDavid du Colombier 
115368c31abSDavid du Colombier 	if(writestodevnull==2){
116368c31abSDavid du Colombier 		packetfree(p);
117368c31abSDavid du Colombier 		return 0;
118368c31abSDavid du Colombier 	}
119368c31abSDavid du Colombier 
120368c31abSDavid du Colombier 	if(queuewrites)
121368c31abSDavid du Colombier 		return queuewrite(u, p, creator, ms);
122368c31abSDavid du Colombier 
123368c31abSDavid du Colombier 	ok = writeqlump(u, p, creator, ms);
124368c31abSDavid du Colombier 
125368c31abSDavid du Colombier 	putlump(u);
126368c31abSDavid du Colombier 	return ok;
127368c31abSDavid du Colombier }
128368c31abSDavid du Colombier 
129368c31abSDavid du Colombier int
writeqlump(Lump * u,Packet * p,int creator,uint ms)130368c31abSDavid du Colombier writeqlump(Lump *u, Packet *p, int creator, uint ms)
131368c31abSDavid du Colombier {
132368c31abSDavid du Colombier 	ZBlock *flat;
133368c31abSDavid du Colombier 	Packet *old;
134368c31abSDavid du Colombier 	IAddr ia;
135368c31abSDavid du Colombier 	int ok;
136368c31abSDavid du Colombier 
137*f9e1cf08SDavid du Colombier 	if(lookupscore(u->score, u->type, &ia) == 0){
138368c31abSDavid du Colombier 		if(verifywrites == 0){
139368c31abSDavid du Colombier 			/* assume the data is here! */
140368c31abSDavid du Colombier 			packetfree(p);
141368c31abSDavid du Colombier 			ms = msec() - ms;
142368c31abSDavid du Colombier 			addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
143368c31abSDavid du Colombier 			return 0;
144368c31abSDavid du Colombier 		}
145368c31abSDavid du Colombier 
146368c31abSDavid du Colombier 		/*
147368c31abSDavid du Colombier 		 * if the read fails,
148368c31abSDavid du Colombier 		 * assume it was corrupted data and store the block again
149368c31abSDavid du Colombier 		 */
150*f9e1cf08SDavid du Colombier 		old = readilump(u, &ia, u->score);
151368c31abSDavid du Colombier 		if(old != nil){
152368c31abSDavid du Colombier 			ok = 0;
153368c31abSDavid du Colombier 			if(packetcmp(p, old) != 0){
154368c31abSDavid du Colombier 				uchar nscore[VtScoreSize];
155368c31abSDavid du Colombier 
156368c31abSDavid du Colombier 				packetsha1(old, nscore);
157368c31abSDavid du Colombier 				if(scorecmp(u->score, nscore) != 0)
158368c31abSDavid du Colombier 					seterr(EStrange, "readilump returned bad data %V not %V", nscore, u->score);
159368c31abSDavid du Colombier 				else
160368c31abSDavid du Colombier 					seterr(EStrange, "score collision %V", u->score);
161368c31abSDavid du Colombier 				ok = -1;
162368c31abSDavid du Colombier 			}
163368c31abSDavid du Colombier 			packetfree(p);
164368c31abSDavid du Colombier 			packetfree(old);
165368c31abSDavid du Colombier 
166368c31abSDavid du Colombier 			ms = msec() - ms;
167368c31abSDavid du Colombier 			addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
168368c31abSDavid du Colombier 			return ok;
169368c31abSDavid du Colombier 		}
170368c31abSDavid du Colombier 		logerr(EAdmin, "writelump: read %V failed, rewriting: %r\n", u->score);
171368c31abSDavid du Colombier 	}
172368c31abSDavid du Colombier 
173368c31abSDavid du Colombier 	flat = packet2zblock(p, packetsize(p));
174368c31abSDavid du Colombier 	ok = storeclump(mainindex, flat, u->score, u->type, creator, &ia);
175368c31abSDavid du Colombier 	freezblock(flat);
176368c31abSDavid du Colombier 	if(ok == 0)
177368c31abSDavid du Colombier 		insertlump(u, p);
178368c31abSDavid du Colombier 	else
179368c31abSDavid du Colombier 		packetfree(p);
180368c31abSDavid du Colombier 
181368c31abSDavid du Colombier 	if(syncwrites){
182368c31abSDavid du Colombier 		flushdcache();
183368c31abSDavid du Colombier 		flushicache();
184368c31abSDavid du Colombier 		flushdcache();
185368c31abSDavid du Colombier 	}
186368c31abSDavid du Colombier 
187368c31abSDavid du Colombier 	ms = msec() - ms;
188368c31abSDavid du Colombier 	addstat2(StatRpcWriteNew, 1, StatRpcWriteNewTime, ms);
189368c31abSDavid du Colombier 	return ok;
190368c31abSDavid du Colombier }
191368c31abSDavid du Colombier 
192368c31abSDavid du Colombier static Packet*
readilump(Lump * u,IAddr * ia,u8int * score)193*f9e1cf08SDavid du Colombier readilump(Lump *u, IAddr *ia, u8int *score)
194368c31abSDavid du Colombier {
195368c31abSDavid du Colombier 	Arena *arena;
196368c31abSDavid du Colombier 	ZBlock *zb;
197368c31abSDavid du Colombier 	Packet *p, *pp;
198368c31abSDavid du Colombier 	Clump cl;
199*f9e1cf08SDavid du Colombier 	u64int aa;
200368c31abSDavid du Colombier 	u8int sc[VtScoreSize];
201368c31abSDavid du Colombier 
202368c31abSDavid du Colombier 	trace(TraceLump, "readilump enter");
203368c31abSDavid du Colombier 	arena = amapitoa(mainindex, ia->addr, &aa);
204368c31abSDavid du Colombier 	if(arena == nil){
205368c31abSDavid du Colombier 		trace(TraceLump, "readilump amapitoa failed");
206368c31abSDavid du Colombier 		return nil;
207368c31abSDavid du Colombier 	}
208368c31abSDavid du Colombier 
209368c31abSDavid du Colombier 	trace(TraceLump, "readilump loadclump");
210368c31abSDavid du Colombier 	zb = loadclump(arena, aa, ia->blocks, &cl, sc, paranoid);
211368c31abSDavid du Colombier 	if(zb == nil){
212368c31abSDavid du Colombier 		trace(TraceLump, "readilump loadclump failed");
213368c31abSDavid du Colombier 		return nil;
214368c31abSDavid du Colombier 	}
215368c31abSDavid du Colombier 
216368c31abSDavid du Colombier 	if(ia->size != cl.info.uncsize){
217368c31abSDavid du Colombier 		seterr(EInconsist, "index and clump size mismatch");
218368c31abSDavid du Colombier 		freezblock(zb);
219368c31abSDavid du Colombier 		return nil;
220368c31abSDavid du Colombier 	}
221368c31abSDavid du Colombier 	if(ia->type != cl.info.type){
222368c31abSDavid du Colombier 		seterr(EInconsist, "index and clump type mismatch");
223368c31abSDavid du Colombier 		freezblock(zb);
224368c31abSDavid du Colombier 		return nil;
225368c31abSDavid du Colombier 	}
226368c31abSDavid du Colombier 	if(scorecmp(score, sc) != 0){
227368c31abSDavid du Colombier 		seterr(ECrash, "score mismatch");
228368c31abSDavid du Colombier 		freezblock(zb);
229368c31abSDavid du Colombier 		return nil;
230368c31abSDavid du Colombier 	}
231368c31abSDavid du Colombier 
232368c31abSDavid du Colombier 	trace(TraceLump, "readilump success");
233368c31abSDavid du Colombier 	p = zblock2packet(zb, cl.info.uncsize);
234368c31abSDavid du Colombier 	freezblock(zb);
235368c31abSDavid du Colombier 	pp = packetdup(p, 0, packetsize(p));
236368c31abSDavid du Colombier 	trace(TraceLump, "readilump insertlump");
237368c31abSDavid du Colombier 	insertlump(u, pp);
238368c31abSDavid du Colombier 	trace(TraceLump, "readilump exit");
239368c31abSDavid du Colombier 	return p;
240368c31abSDavid du Colombier }
241