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 }