URI:
       tlump.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tlump.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 }