ventifs.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * Present venti hash tree as file system for debugging.
  3. */
  4. #include <u.h>
  5. #include <libc.h>
  6. #include <venti.h>
  7. #include <vac.h>
  8. #include <fcall.h>
  9. #include <thread.h>
  10. #include <9p.h>
  11. VtFile *rootf;
  12. void
  13. responderrstr(Req *r)
  14. {
  15. char e[ERRMAX];
  16. rerrstr(e, sizeof e);
  17. respond(r, e);
  18. }
  19. void
  20. mkqide(Qid *q, VtEntry *e)
  21. {
  22. if(e->flags&VtEntryDir)
  23. q->type = QTDIR;
  24. else
  25. q->type = 0;
  26. q->path = *(uvlong*)e->score;
  27. q->vers = *(ulong*)(e->score+8);
  28. }
  29. void
  30. mkqid(Qid *q, VtFile *f)
  31. {
  32. VtEntry e;
  33. vtFileLock(f, VtOReadOnly);
  34. vtFileGetEntry(f, &e);
  35. vtFileUnlock(f);
  36. mkqide(q, &e);
  37. }
  38. void
  39. fsdestroyfid(Fid *fid)
  40. {
  41. if(fid->aux)
  42. vtFileClose(fid->aux);
  43. }
  44. void
  45. fsattach(Req *r)
  46. {
  47. r->fid->aux = rootf;
  48. vtFileIncRef(rootf);
  49. mkqid(&r->ofcall.qid, rootf);
  50. r->fid->qid = r->ofcall.qid;
  51. respond(r, nil);
  52. }
  53. void
  54. fsopen(Req *r)
  55. {
  56. if(r->ifcall.mode != OREAD){
  57. respond(r, "read-only file system");
  58. return;
  59. }
  60. r->ofcall.qid = r->fid->qid;
  61. respond(r, nil);
  62. }
  63. void
  64. fsreaddir(Req *r)
  65. {
  66. Dir d;
  67. int dsize, nn;
  68. char score[2*VtScoreSize+1];
  69. uchar edata[VtEntrySize], *p, *ep;
  70. u32int i, n, epb;
  71. u64int o;
  72. VtFile *f;
  73. VtEntry e;
  74. memset(&d, 0, sizeof d);
  75. d.name = "0123456789012345678901234567890123456789";
  76. d.uid = "venti";
  77. d.gid = "venti";
  78. d.muid = "";
  79. d.atime = time(0);
  80. d.mtime = time(0);
  81. d.mode = 0444;
  82. dsize = sizeD2M(&d);
  83. p = (uchar*)r->ofcall.data;
  84. ep = p+r->ifcall.count;
  85. f = r->fid->aux;
  86. vtFileLock(f, VtOReadOnly);
  87. vtFileGetEntry(f, &e);
  88. epb = e.dsize / VtEntrySize;
  89. n = vtFileGetDirSize(f);
  90. fprint(2, "dirsize %d\n", n);
  91. i = r->ifcall.offset / dsize;
  92. for(; i<n; i++){
  93. fprint(2, "%d...", i);
  94. if(p+dsize > ep)
  95. {
  96. fprint(2, "done %p %d %p\n", p, dsize, ep);
  97. break;
  98. }
  99. o = (i/epb)*e.dsize+(i%epb)*VtEntrySize;
  100. if(vtFileRead(f, edata, VtEntrySize, o) != VtEntrySize){
  101. vtFileUnlock(f);
  102. responderrstr(r);
  103. return;
  104. }
  105. if(!vtEntryUnpack(&e, edata, 0)){
  106. fprint(2, "entryunpack: %R\n");
  107. continue;
  108. }
  109. if(!(e.flags&VtEntryActive)){
  110. strcpy(score, "________________________________________");
  111. d.qid.type = 0;
  112. }else{
  113. snprint(score, sizeof score, "%V", e.score);
  114. mkqide(&d.qid, &e);
  115. }
  116. d.name = score;
  117. if(e.flags&VtEntryDir){
  118. d.mode = DMDIR|0555;
  119. d.qid.type = QTDIR;
  120. }else{
  121. d.mode = 0444;
  122. d.qid.type = 0;
  123. }
  124. d.length = e.size;
  125. nn = convD2M(&d, p, dsize);
  126. if(nn != dsize)
  127. fprint(2, "oops: dsize mismatch\n");
  128. p += dsize;
  129. }
  130. r->ofcall.count = p - (uchar*)r->ofcall.data;
  131. vtFileUnlock(f);
  132. respond(r, nil);
  133. }
  134. void
  135. fsread(Req *r)
  136. {
  137. long n;
  138. if(r->fid->qid.type&QTDIR){
  139. fsreaddir(r);
  140. return;
  141. }
  142. vtFileLock(r->fid->aux, VtOReadOnly);
  143. n = vtFileRead(r->fid->aux, r->ofcall.data, r->ifcall.count, r->ifcall.offset);
  144. vtFileUnlock(r->fid->aux);
  145. if(n < 0){
  146. responderrstr(r);
  147. return;
  148. }
  149. r->ofcall.count = n;
  150. respond(r, nil);
  151. }
  152. void
  153. fsstat(Req *r)
  154. {
  155. VtEntry e;
  156. vtFileLock(r->fid->aux, VtOReadOnly);
  157. if(!vtFileGetEntry(r->fid->aux, &e)){
  158. vtFileUnlock(r->fid->aux);
  159. responderrstr(r);
  160. return;
  161. }
  162. vtFileUnlock(r->fid->aux);
  163. memset(&r->d, 0, sizeof r->d);
  164. r->d.name = smprint("%V", e.score);
  165. r->d.qid = r->fid->qid;
  166. r->d.mode = 0444;
  167. if(r->d.qid.type&QTDIR)
  168. r->d.mode |= DMDIR|0111;
  169. r->d.uid = estrdup9p("venti");
  170. r->d.gid = estrdup9p("venti");
  171. r->d.muid = estrdup9p("");
  172. r->d.atime = time(0);
  173. r->d.mtime = time(0);
  174. r->d.length = e.size;
  175. respond(r, nil);
  176. }
  177. char*
  178. fswalk1(Fid *fid, char *name, void*)
  179. {
  180. uchar score[VtScoreSize], edata[VtEntrySize];
  181. u32int i, n, epb;
  182. u64int o;
  183. VtFile *f, *ff;
  184. VtEntry e;
  185. if(dec16(score, sizeof score, name, strlen(name)) != VtScoreSize)
  186. return "file not found";
  187. f = fid->aux;
  188. vtFileGetEntry(f, &e);
  189. epb = e.dsize / VtEntrySize;
  190. n = vtFileGetDirSize(f);
  191. o = 0;
  192. for(i=0; i<n; i++){
  193. o = (i/epb)*e.dsize+(i%epb)*VtEntrySize;
  194. if(vtFileRead(f, edata, VtEntrySize, o) != VtEntrySize)
  195. return "error in vtfileread";
  196. if(!vtEntryUnpack(&e, edata, 0))
  197. continue;
  198. if(!(e.flags&VtEntryActive))
  199. continue;
  200. if(memcmp(e.score, score, VtScoreSize) == 0)
  201. break;
  202. }
  203. if(i == n)
  204. return "entry not found";
  205. ff = vtFileOpen(f, i, VtOReadOnly);
  206. if(ff == nil)
  207. return "error in vtfileopen";
  208. vtFileClose(f);
  209. fid->aux = ff;
  210. mkqid(&fid->qid, ff);
  211. return nil;
  212. }
  213. char*
  214. fsclone(Fid *fid, Fid *newfid, void*)
  215. {
  216. newfid->aux = fid->aux;
  217. vtFileIncRef(fid->aux);
  218. return nil;
  219. }
  220. void
  221. fswalk(Req *r)
  222. {
  223. VtFile *f;
  224. f = r->fid->aux;
  225. vtFileLock(f, VtOReadOnly);
  226. walkandclone(r, fswalk1, fsclone, nil);
  227. vtFileUnlock(f);
  228. }
  229. Srv fs =
  230. {
  231. .destroyfid= fsdestroyfid,
  232. .attach= fsattach,
  233. .open= fsopen,
  234. .read= fsread,
  235. .stat= fsstat,
  236. .walk= fswalk
  237. };
  238. void
  239. usage(void)
  240. {
  241. fprint(2, "usage: ventifs score\n");
  242. exits("usage");
  243. }
  244. void
  245. main(int argc, char **argv)
  246. {
  247. VtSession *z;
  248. VtCache *c;
  249. VtBlock *b;
  250. VtRoot root;
  251. VtEntry e;
  252. int bsize;
  253. uchar score[VtScoreSize];
  254. bsize = 16384;
  255. ARGBEGIN{
  256. case 'D':
  257. chatty9p++;
  258. break;
  259. case 'b':
  260. bsize = atoi(EARGF(usage()));
  261. break;
  262. default:
  263. usage();
  264. }ARGEND
  265. if(argc != 1)
  266. usage();
  267. fmtinstall('V', vtScoreFmt);
  268. fmtinstall('R', vtErrFmt);
  269. vtAttach();
  270. if((z = vtDial(nil, 0)) == nil)
  271. vtFatal("vtDial: %r");
  272. if(!vtConnect(z, nil))
  273. vtFatal("vtConnect: %r");
  274. c = vtCacheAlloc(z, bsize, 50, VtOReadWrite);
  275. if(dec16(score, sizeof score, argv[0], strlen(argv[0])) != VtScoreSize)
  276. vtFatal("bad score: %R");
  277. b = vtCacheGlobal(c, score, VtRootType);
  278. if(b){
  279. if(!vtRootUnpack(&root, b->data))
  280. vtFatal("bad root: %R");
  281. memmove(score, root.score, VtScoreSize);
  282. vtBlockPut(b);
  283. }
  284. b = vtCacheGlobal(c, score, VtDirType);
  285. if(b == nil)
  286. sysfatal("vtCacheGlobal %V: %R", score);
  287. if(!vtEntryUnpack(&e, b->data, 0))
  288. sysfatal("%V: vtEntryUnpack failed", score);
  289. fprint(2, "entry: size %llud psize %d dsize %d\n",
  290. e.size, e.psize, e.dsize);
  291. vtBlockPut(b);
  292. if(!(e.flags&VtEntryDir)){
  293. b = vtCacheAllocBlock(c, VtDirType);
  294. vtEntryPack(&e, b->data, 0);
  295. memmove(e.score, b->score, VtScoreSize);
  296. e.flags |= VtEntryDir;
  297. e.size = VtEntrySize;
  298. e.depth = 0;
  299. vtBlockPut(b);
  300. }
  301. rootf = vtFileOpenRoot(c, &e);
  302. if(rootf == nil)
  303. vtFatal("vtFileOpenRoot: %R");
  304. postmountsrv(&fs, nil, "/n/kremvax", MBEFORE);
  305. }