plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

lump.c (4967B)


      1 #include "stdinc.h"
      2 #include "dat.h"
      3 #include "fns.h"
      4 
      5 int			bootstrap = 0;
      6 int			syncwrites = 0;
      7 int			queuewrites = 0;
      8 int			writestodevnull = 0;
      9 int			verifywrites = 0;
     10 
     11 static Packet		*readilump(Lump *u, IAddr *ia, u8int *score);
     12 
     13 /*
     14  * Some of this logic is duplicated in hdisk.c
     15  */
     16 Packet*
     17 readlump(u8int *score, int type, u32int size, int *cached)
     18 {
     19 	Lump *u;
     20 	Packet *p;
     21 	IAddr ia;
     22 	u32int n;
     23 
     24 	trace(TraceLump, "readlump enter");
     25 /*
     26 	qlock(&stats.lock);
     27 	stats.lumpreads++;
     28 	qunlock(&stats.lock);
     29 */
     30 	if(scorecmp(score, zeroscore) == 0)
     31 		return packetalloc();
     32 	u = lookuplump(score, type);
     33 	if(u->data != nil){
     34 		trace(TraceLump, "readlump lookuplump hit");
     35 		if(cached)
     36 			*cached = 1;
     37 		n = packetsize(u->data);
     38 		if(n > size){
     39 			seterr(EOk, "read too small: asked for %d need at least %d", size, n);
     40 			putlump(u);
     41 
     42 			return nil;
     43 		}
     44 		p = packetdup(u->data, 0, n);
     45 		putlump(u);
     46 		return p;
     47 	}
     48 
     49 	if(cached)
     50 		*cached = 0;
     51 
     52 	if(lookupscore(score, type, &ia) < 0){
     53 		/* ZZZ place to check for someone trying to guess scores */
     54 		seterr(EOk, "no block with score %V/%d exists", score, type);
     55 
     56 		putlump(u);
     57 		return nil;
     58 	}
     59 	if(ia.size > size){
     60 		seterr(EOk, "read too small 1: asked for %d need at least %d", size, ia.size);
     61 
     62 		putlump(u);
     63 		return nil;
     64 	}
     65 
     66 	trace(TraceLump, "readlump readilump");
     67 	p = readilump(u, &ia, score);
     68 	putlump(u);
     69 
     70 	trace(TraceLump, "readlump exit");
     71 	return p;
     72 }
     73 
     74 /*
     75  * save away a lump, and return it's score.
     76  * doesn't store duplicates, but checks that the data is really the same.
     77  */
     78 int
     79 writelump(Packet *p, u8int *score, int type, u32int creator, uint ms)
     80 {
     81 	Lump *u;
     82 	int ok;
     83 
     84 /*
     85 	qlock(&stats.lock);
     86 	stats.lumpwrites++;
     87 	qunlock(&stats.lock);
     88 */
     89 
     90 	packetsha1(p, score);
     91 	if(packetsize(p) == 0 || writestodevnull==1){
     92 		packetfree(p);
     93 		return 0;
     94 	}
     95 
     96 	u = lookuplump(score, type);
     97 	if(u->data != nil){
     98 		ok = 0;
     99 		if(packetcmp(p, u->data) != 0){
    100 			uchar nscore[VtScoreSize];
    101 
    102 			packetsha1(u->data, nscore);
    103 			if(scorecmp(u->score, score) != 0)
    104 				seterr(EStrange, "lookuplump returned bad score %V not %V", u->score, score);
    105 			else if(scorecmp(u->score, nscore) != 0)
    106 				seterr(EStrange, "lookuplump returned bad data %V not %V", nscore, u->score);
    107 			else
    108 				seterr(EStrange, "score collision %V", score);
    109 			ok = -1;
    110 		}
    111 		packetfree(p);
    112 		putlump(u);
    113 		return ok;
    114 	}
    115 
    116 	if(writestodevnull==2){
    117 		packetfree(p);
    118 		return 0;
    119 	}
    120 
    121 	if(queuewrites)
    122 		return queuewrite(u, p, creator, ms);
    123 
    124 	ok = writeqlump(u, p, creator, ms);
    125 
    126 	putlump(u);
    127 	return ok;
    128 }
    129 
    130 int
    131 writeqlump(Lump *u, Packet *p, int creator, uint ms)
    132 {
    133 	ZBlock *flat;
    134 	Packet *old;
    135 	IAddr ia;
    136 	int ok;
    137 
    138 	if(lookupscore(u->score, u->type, &ia) == 0){
    139 		if(verifywrites == 0){
    140 			/* assume the data is here! */
    141 			packetfree(p);
    142 			ms = msec() - ms;
    143 			addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
    144 			return 0;
    145 		}
    146 
    147 		/*
    148 		 * if the read fails,
    149 		 * assume it was corrupted data and store the block again
    150 		 */
    151 		old = readilump(u, &ia, u->score);
    152 		if(old != nil){
    153 			ok = 0;
    154 			if(packetcmp(p, old) != 0){
    155 				uchar nscore[VtScoreSize];
    156 
    157 				packetsha1(old, nscore);
    158 				if(scorecmp(u->score, nscore) != 0)
    159 					seterr(EStrange, "readilump returned bad data %V not %V", nscore, u->score);
    160 				else
    161 					seterr(EStrange, "score collision %V", u->score);
    162 				ok = -1;
    163 			}
    164 			packetfree(p);
    165 			packetfree(old);
    166 
    167 			ms = msec() - ms;
    168 			addstat2(StatRpcWriteOld, 1, StatRpcWriteOldTime, ms);
    169 			return ok;
    170 		}
    171 		logerr(EAdmin, "writelump: read %V failed, rewriting: %r\n", u->score);
    172 	}
    173 
    174 	flat = packet2zblock(p, packetsize(p));
    175 	ok = storeclump(mainindex, flat, u->score, u->type, creator, &ia);
    176 	freezblock(flat);
    177 	if(ok == 0)
    178 		insertlump(u, p);
    179 	else
    180 		packetfree(p);
    181 
    182 	if(syncwrites){
    183 		flushdcache();
    184 		flushicache();
    185 		flushdcache();
    186 	}
    187 
    188 	ms = msec() - ms;
    189 	addstat2(StatRpcWriteNew, 1, StatRpcWriteNewTime, ms);
    190 	return ok;
    191 }
    192 
    193 static Packet*
    194 readilump(Lump *u, IAddr *ia, u8int *score)
    195 {
    196 	Arena *arena;
    197 	ZBlock *zb;
    198 	Packet *p, *pp;
    199 	Clump cl;
    200 	u64int aa;
    201 	u8int sc[VtScoreSize];
    202 
    203 	trace(TraceLump, "readilump enter");
    204 	arena = amapitoa(mainindex, ia->addr, &aa);
    205 	if(arena == nil){
    206 		trace(TraceLump, "readilump amapitoa failed");
    207 		return nil;
    208 	}
    209 
    210 	trace(TraceLump, "readilump loadclump");
    211 	zb = loadclump(arena, aa, ia->blocks, &cl, sc, paranoid);
    212 	if(zb == nil){
    213 		trace(TraceLump, "readilump loadclump failed");
    214 		return nil;
    215 	}
    216 
    217 	if(ia->size != cl.info.uncsize){
    218 		seterr(EInconsist, "index and clump size mismatch");
    219 		freezblock(zb);
    220 		return nil;
    221 	}
    222 	if(ia->type != cl.info.type){
    223 		seterr(EInconsist, "index and clump type mismatch");
    224 		freezblock(zb);
    225 		return nil;
    226 	}
    227 	if(scorecmp(score, sc) != 0){
    228 		seterr(ECrash, "score mismatch");
    229 		freezblock(zb);
    230 		return nil;
    231 	}
    232 
    233 	trace(TraceLump, "readilump success");
    234 	p = zblock2packet(zb, cl.info.uncsize);
    235 	freezblock(zb);
    236 	pp = packetdup(p, 0, packetsize(p));
    237 	trace(TraceLump, "readilump insertlump");
    238 	insertlump(u, pp);
    239 	trace(TraceLump, "readilump exit");
    240 	return p;
    241 }