wrarena.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "stdinc.h"
  10. #include "dat.h"
  11. #include "fns.h"
  12. QLock godot;
  13. char *host;
  14. int readonly = 1; /* for part.c */
  15. int mainstacksize = 256*1024;
  16. Channel *c;
  17. VtConn *z;
  18. int fast; /* and a bit unsafe; only for benchmarking */
  19. int haveaoffset;
  20. int maxwrites = -1;
  21. int verbose;
  22. typedef struct ZClump ZClump;
  23. struct ZClump
  24. {
  25. ZBlock *lump;
  26. Clump cl;
  27. uint64_t aa;
  28. };
  29. void
  30. usage(void)
  31. {
  32. fprint(2, "usage: wrarena [-h host] arenafile [offset]\n");
  33. threadexitsall("usage");
  34. }
  35. void
  36. vtsendthread(void *v)
  37. {
  38. ZClump zcl;
  39. USED(v);
  40. while(recv(c, &zcl) == 1){
  41. if(zcl.lump == nil)
  42. break;
  43. if(vtwrite(z, zcl.cl.info.score, zcl.cl.info.type, zcl.lump->data, zcl.cl.info.uncsize) < 0)
  44. sysfatal("failed writing clump %llu: %r", zcl.aa);
  45. if(verbose)
  46. print("%V\n", zcl.cl.info.score);
  47. freezblock(zcl.lump);
  48. }
  49. /*
  50. * All the send threads try to exit right when
  51. * threadmain is calling threadexitsall.
  52. * Either libthread or the Linux NPTL pthreads library
  53. * can't handle this condition (I suspect NPTL but have
  54. * not confirmed this) and we get a seg fault in exit.
  55. * I spent a day tracking this down with no success,
  56. * so we're going to work around it instead by just
  57. * sitting here and waiting for the threadexitsall to
  58. * take effect.
  59. */
  60. qlock(&godot);
  61. }
  62. static void
  63. rdarena(Arena *arena, uint64_t offset)
  64. {
  65. int i;
  66. uint64_t a, aa, e;
  67. uint8_t score[VtScoreSize];
  68. Clump cl;
  69. ClumpInfo ci;
  70. ZBlock *lump;
  71. ZClump zcl;
  72. fprint(2, "wrarena: copying %s to venti\n", arena->name);
  73. printarena(2, arena);
  74. a = arena->base;
  75. e = arena->base + arena->size;
  76. if(offset != ~(uint64_t)0) {
  77. if(offset >= e - a)
  78. sysfatal("bad offset %#llx >= %#llx", offset, e - a);
  79. aa = offset;
  80. } else
  81. aa = 0;
  82. i = 0;
  83. for(a = 0; maxwrites != 0 && i < arena->memstats.clumps;
  84. a += ClumpSize + ci.size){
  85. if(readclumpinfo(arena, i++, &ci) < 0)
  86. break;
  87. if(a < aa || ci.type == VtCorruptType){
  88. if(ci.type == VtCorruptType)
  89. fprint(2, "%s: corrupt clump read at %#llx: +%d\n",
  90. argv0, a, ClumpSize+ci.size);
  91. continue;
  92. }
  93. lump = loadclump(arena, a, 0, &cl, score, 0);
  94. if(lump == nil) {
  95. fprint(2, "clump %#llx failed to read: %r\n", a);
  96. continue;
  97. }
  98. if(!fast && cl.info.type != VtCorruptType) {
  99. scoremem(score, lump->data, cl.info.uncsize);
  100. if(scorecmp(cl.info.score, score) != 0) {
  101. fprint(2, "clump %#llx has mismatched score\n",
  102. a);
  103. break;
  104. }
  105. if(vttypevalid(cl.info.type) < 0) {
  106. fprint(2, "clump %#llx has bad type %d\n",
  107. a, cl.info.type);
  108. break;
  109. }
  110. }
  111. if(z && cl.info.type != VtCorruptType){
  112. zcl.cl = cl;
  113. zcl.lump = lump;
  114. zcl.aa = a;
  115. send(c, &zcl);
  116. }else
  117. freezblock(lump);
  118. if(maxwrites > 0)
  119. --maxwrites;
  120. }
  121. if(a > aa)
  122. aa = a;
  123. if(haveaoffset)
  124. print("end offset %#llx\n", aa);
  125. }
  126. void
  127. threadmain(int argc, char *argv[])
  128. {
  129. int i;
  130. char *file;
  131. Arena *arena;
  132. uint64_t offset, aoffset;
  133. Part *part;
  134. unsigned char buf[8192];
  135. ArenaHead head;
  136. ZClump zerocl;
  137. ventifmtinstall();
  138. qlock(&godot);
  139. aoffset = 0;
  140. ARGBEGIN{
  141. case 'f':
  142. fast = 1;
  143. ventidoublechecksha1 = 0;
  144. break;
  145. case 'h':
  146. host = EARGF(usage());
  147. break;
  148. case 'o':
  149. haveaoffset = 1;
  150. aoffset = strtoull(EARGF(usage()), 0, 0);
  151. break;
  152. case 'M':
  153. maxwrites = atoi(EARGF(usage()));
  154. break;
  155. case 'v':
  156. verbose = 1;
  157. break;
  158. default:
  159. usage();
  160. break;
  161. }ARGEND
  162. offset = ~(uint64_t)0;
  163. switch(argc) {
  164. default:
  165. usage();
  166. case 2:
  167. offset = strtoull(argv[1], 0, 0);
  168. /* fall through */
  169. case 1:
  170. file = argv[0];
  171. }
  172. fmtinstall('V', vtscorefmt);
  173. statsinit();
  174. part = initpart(file, OREAD);
  175. if(part == nil)
  176. sysfatal("can't open file %s: %r", file);
  177. if(readpart(part, aoffset, buf, sizeof buf) < 0)
  178. sysfatal("can't read file %s: %r", file);
  179. if(unpackarenahead(&head, buf) < 0)
  180. sysfatal("corrupted arena header: %r");
  181. if(aoffset+head.size > part->size)
  182. sysfatal("arena is truncated: want %llu bytes have %llu",
  183. head.size, part->size);
  184. partblocksize(part, head.blocksize);
  185. initdcache(8 * MaxDiskBlock);
  186. arena = initarena(part, aoffset, head.size, head.blocksize);
  187. if(arena == nil)
  188. sysfatal("initarena: %r");
  189. z = nil;
  190. if(host==nil || strcmp(host, "/dev/null") != 0){
  191. z = vtdial(host);
  192. if(z == nil)
  193. sysfatal("could not connect to server: %r");
  194. if(vtconnect(z) < 0)
  195. sysfatal("vtconnect: %r");
  196. }
  197. c = chancreate(sizeof(ZClump), 0);
  198. for(i=0; i<12; i++)
  199. vtproc(vtsendthread, nil);
  200. rdarena(arena, offset);
  201. if(vtsync(z) < 0)
  202. sysfatal("executing sync: %r");
  203. memset(&zerocl, 0, sizeof zerocl);
  204. for(i=0; i<12; i++)
  205. send(c, &zerocl);
  206. if(z){
  207. vthangup(z);
  208. }
  209. threadexitsall(0);
  210. }