lump.c 4.8 KB

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