file.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. /*
  2. * Manage tree of VtFiles stored in the block cache.
  3. *
  4. * The single point of truth for the info about the VtFiles themselves
  5. * is the block data. Because of this, there is no explicit locking of
  6. * VtFile structures, and indeed there may be more than one VtFile
  7. * structure for a given Venti file. They synchronize through the
  8. * block cache.
  9. *
  10. * This is a bit simpler than fossil because there are no epochs
  11. * or tags or anything else. Just mutable local blocks and immutable
  12. * Venti blocks.
  13. */
  14. #include <u.h>
  15. #include <libc.h>
  16. #include <venti.h>
  17. #define MaxBlock (1UL<<31)
  18. static char ENotDir[] = "walk in non-directory";
  19. static char ETooBig[] = "file too big";
  20. /* static char EBadAddr[] = "bad address"; */
  21. static char ELabelMismatch[] = "label mismatch";
  22. static int sizetodepth(uvlong s, int psize, int dsize);
  23. static VtBlock *fileload(VtFile *r, VtEntry *e);
  24. static int shrinkdepth(VtFile*, VtBlock*, VtEntry*, int);
  25. static int shrinksize(VtFile*, VtEntry*, uvlong);
  26. static int growdepth(VtFile*, VtBlock*, VtEntry*, int);
  27. #define ISLOCKED(r) ((r)->b != nil)
  28. #define DEPTH(t) ((t)&VtTypeDepthMask)
  29. static VtFile *
  30. vtfilealloc(VtCache *c, VtBlock *b, VtFile *p, u32int offset, int mode)
  31. {
  32. int epb;
  33. u32int size;
  34. VtEntry e;
  35. VtFile *r;
  36. assert(p==nil || ISLOCKED(p));
  37. if(p == nil){
  38. assert(offset == 0);
  39. epb = 1;
  40. }else
  41. epb = p->dsize / VtEntrySize;
  42. if(b->type != VtDirType){
  43. werrstr("bad block type %#uo", b->type);
  44. return nil;
  45. }
  46. /*
  47. * a non-active entry is the only thing that
  48. * can legitimately happen here. all the others
  49. * get prints.
  50. */
  51. if(vtentryunpack(&e, b->data, offset % epb) < 0){
  52. fprint(2, "vtentryunpack failed: %r (%.*H)\n", VtEntrySize, b->data+VtEntrySize*(offset%epb));
  53. return nil;
  54. }
  55. if(!(e.flags & VtEntryActive)){
  56. werrstr("entry not active");
  57. return nil;
  58. }
  59. if(DEPTH(e.type) < sizetodepth(e.size, e.psize, e.dsize)){
  60. fprint(2, "depth %ud size %llud psize %ud dsize %ud\n",
  61. DEPTH(e.type), e.size, e.psize, e.dsize);
  62. werrstr("bad depth");
  63. return nil;
  64. }
  65. size = vtcacheblocksize(c);
  66. if(e.dsize > size || e.psize > size){
  67. werrstr("block sizes %ud, %ud bigger than cache block size %ud",
  68. e.psize, e.dsize, size);
  69. return nil;
  70. }
  71. r = vtmallocz(sizeof(VtFile));
  72. r->c = c;
  73. r->mode = mode;
  74. r->dsize = e.dsize;
  75. r->psize = e.psize;
  76. r->gen = e.gen;
  77. r->dir = (e.type & VtTypeBaseMask) == VtDirType;
  78. r->ref = 1;
  79. r->parent = p;
  80. if(p){
  81. qlock(&p->lk);
  82. assert(mode == VtOREAD || p->mode == VtORDWR);
  83. p->ref++;
  84. qunlock(&p->lk);
  85. }else{
  86. assert(b->addr != NilBlock);
  87. r->local = 1;
  88. }
  89. memmove(r->score, b->score, VtScoreSize);
  90. r->offset = offset;
  91. r->epb = epb;
  92. return r;
  93. }
  94. VtFile *
  95. vtfileroot(VtCache *c, u32int addr, int mode)
  96. {
  97. VtFile *r;
  98. VtBlock *b;
  99. b = vtcachelocal(c, addr, VtDirType);
  100. if(b == nil)
  101. return nil;
  102. r = vtfilealloc(c, b, nil, 0, mode);
  103. vtblockput(b);
  104. return r;
  105. }
  106. VtFile*
  107. vtfileopenroot(VtCache *c, VtEntry *e)
  108. {
  109. VtBlock *b;
  110. VtFile *f;
  111. b = vtcacheallocblock(c, VtDirType);
  112. if(b == nil)
  113. return nil;
  114. vtentrypack(e, b->data, 0);
  115. f = vtfilealloc(c, b, nil, 0, VtORDWR);
  116. vtblockput(b);
  117. return f;
  118. }
  119. VtFile *
  120. vtfilecreateroot(VtCache *c, int psize, int dsize, int type)
  121. {
  122. VtEntry e;
  123. memset(&e, 0, sizeof e);
  124. e.flags = VtEntryActive;
  125. e.psize = psize;
  126. e.dsize = dsize;
  127. e.type = type;
  128. memmove(e.score, vtzeroscore, VtScoreSize);
  129. return vtfileopenroot(c, &e);
  130. }
  131. VtFile *
  132. vtfileopen(VtFile *r, u32int offset, int mode)
  133. {
  134. ulong bn;
  135. VtBlock *b;
  136. assert(ISLOCKED(r));
  137. if(!r->dir){
  138. werrstr(ENotDir);
  139. return nil;
  140. }
  141. bn = offset/(r->dsize/VtEntrySize);
  142. b = vtfileblock(r, bn, mode);
  143. if(b == nil)
  144. return nil;
  145. r = vtfilealloc(r->c, b, r, offset, mode);
  146. vtblockput(b);
  147. return r;
  148. }
  149. VtFile*
  150. vtfilecreate(VtFile *r, int psize, int dsize, int type)
  151. {
  152. return _vtfilecreate(r, -1, psize, dsize, type);
  153. }
  154. VtFile*
  155. _vtfilecreate(VtFile *r, int o, int psize, int dsize, int type)
  156. {
  157. int i;
  158. VtBlock *b;
  159. u32int bn, size;
  160. VtEntry e;
  161. int epb;
  162. VtFile *rr;
  163. u32int offset;
  164. assert(ISLOCKED(r));
  165. assert(psize <= VtMaxLumpSize);
  166. assert(dsize <= VtMaxLumpSize);
  167. assert(type == VtDirType || type == VtDataType);
  168. if(!r->dir){
  169. werrstr(ENotDir);
  170. return nil;
  171. }
  172. epb = r->dsize/VtEntrySize;
  173. size = vtfilegetdirsize(r);
  174. /*
  175. * look at a random block to see if we can find an empty entry
  176. */
  177. if(o == -1){
  178. offset = lnrand(size+1);
  179. offset -= offset % epb;
  180. }else
  181. offset = o;
  182. /* try the given block and then try the last block */
  183. for(;;){
  184. bn = offset/epb;
  185. b = vtfileblock(r, bn, VtORDWR);
  186. if(b == nil)
  187. return nil;
  188. for(i=offset%r->epb; i<epb; i++){
  189. if(vtentryunpack(&e, b->data, i) < 0)
  190. continue;
  191. if((e.flags&VtEntryActive) == 0 && e.gen != ~0)
  192. goto Found;
  193. }
  194. vtblockput(b);
  195. if(offset == size){
  196. fprint(2, "vtfilecreate: cannot happen\n");
  197. werrstr("vtfilecreate: cannot happen");
  198. return nil;
  199. }
  200. offset = size;
  201. }
  202. Found:
  203. /* found an entry - gen already set */
  204. e.psize = psize;
  205. e.dsize = dsize;
  206. e.flags = VtEntryActive;
  207. e.type = type;
  208. e.size = 0;
  209. memmove(e.score, vtzeroscore, VtScoreSize);
  210. vtentrypack(&e, b->data, i);
  211. offset = bn*epb + i;
  212. if(offset+1 > size){
  213. if(vtfilesetdirsize(r, offset+1) < 0){
  214. vtblockput(b);
  215. return nil;
  216. }
  217. }
  218. rr = vtfilealloc(r->c, b, r, offset, VtORDWR);
  219. vtblockput(b);
  220. return rr;
  221. }
  222. static int
  223. vtfilekill(VtFile *r, int doremove)
  224. {
  225. VtEntry e;
  226. VtBlock *b;
  227. assert(ISLOCKED(r));
  228. b = fileload(r, &e);
  229. if(b == nil)
  230. return -1;
  231. if(doremove==0 && e.size == 0){
  232. /* already truncated */
  233. vtblockput(b);
  234. return 0;
  235. }
  236. if(doremove){
  237. if(e.gen != ~0)
  238. e.gen++;
  239. e.dsize = 0;
  240. e.psize = 0;
  241. e.flags = 0;
  242. }else
  243. e.flags &= ~VtEntryLocal;
  244. e.type = 0;
  245. e.size = 0;
  246. memmove(e.score, vtzeroscore, VtScoreSize);
  247. vtentrypack(&e, b->data, r->offset % r->epb);
  248. vtblockput(b);
  249. if(doremove){
  250. vtfileunlock(r);
  251. vtfileclose(r);
  252. }
  253. return 0;
  254. }
  255. int
  256. vtfileremove(VtFile *r)
  257. {
  258. return vtfilekill(r, 1);
  259. }
  260. int
  261. vtfiletruncate(VtFile *r)
  262. {
  263. return vtfilekill(r, 0);
  264. }
  265. uvlong
  266. vtfilegetsize(VtFile *r)
  267. {
  268. VtEntry e;
  269. VtBlock *b;
  270. assert(ISLOCKED(r));
  271. b = fileload(r, &e);
  272. if(b == nil)
  273. return ~(uvlong)0;
  274. vtblockput(b);
  275. return e.size;
  276. }
  277. static int
  278. shrinksize(VtFile *r, VtEntry *e, uvlong size)
  279. {
  280. int i, depth, type, isdir, ppb;
  281. uvlong ptrsz;
  282. uchar score[VtScoreSize];
  283. VtBlock *b;
  284. b = vtcacheglobal(r->c, e->score, e->type);
  285. if(b == nil)
  286. return -1;
  287. ptrsz = e->dsize;
  288. ppb = e->psize/VtScoreSize;
  289. type = e->type;
  290. depth = DEPTH(type);
  291. for(i=0; i+1<depth; i++)
  292. ptrsz *= ppb;
  293. isdir = r->dir;
  294. while(depth > 0){
  295. if(b->addr == NilBlock){
  296. /* not worth copying the block just so we can zero some of it */
  297. vtblockput(b);
  298. return -1;
  299. }
  300. /*
  301. * invariant: each pointer in the tree rooted at b accounts for ptrsz bytes
  302. */
  303. /* zero the pointers to unnecessary blocks */
  304. i = (size+ptrsz-1)/ptrsz;
  305. for(; i<ppb; i++)
  306. memmove(b->data+i*VtScoreSize, vtzeroscore, VtScoreSize);
  307. /* recurse (go around again) on the partially necessary block */
  308. i = size/ptrsz;
  309. size = size%ptrsz;
  310. if(size == 0){
  311. vtblockput(b);
  312. return 0;
  313. }
  314. ptrsz /= ppb;
  315. type--;
  316. memmove(score, b->data+i*VtScoreSize, VtScoreSize);
  317. vtblockput(b);
  318. b = vtcacheglobal(r->c, score, type);
  319. if(b == nil)
  320. return -1;
  321. }
  322. if(b->addr == NilBlock){
  323. vtblockput(b);
  324. return -1;
  325. }
  326. /*
  327. * No one ever truncates BtDir blocks.
  328. */
  329. if(depth==0 && !isdir && e->dsize > size)
  330. memset(b->data+size, 0, e->dsize-size);
  331. vtblockput(b);
  332. return 0;
  333. }
  334. int
  335. vtfilesetsize(VtFile *r, u64int size)
  336. {
  337. int depth, edepth;
  338. VtEntry e;
  339. VtBlock *b;
  340. assert(ISLOCKED(r));
  341. if(size == 0)
  342. return vtfiletruncate(r);
  343. if(size > VtMaxFileSize || size > ((uvlong)MaxBlock)*r->dsize){
  344. werrstr(ETooBig);
  345. return -1;
  346. }
  347. b = fileload(r, &e);
  348. if(b == nil)
  349. return -1;
  350. /* quick out */
  351. if(e.size == size){
  352. vtblockput(b);
  353. return 0;
  354. }
  355. depth = sizetodepth(size, e.psize, e.dsize);
  356. edepth = DEPTH(e.type);
  357. if(depth < edepth){
  358. if(shrinkdepth(r, b, &e, depth) < 0){
  359. vtblockput(b);
  360. return -1;
  361. }
  362. }else if(depth > edepth){
  363. if(growdepth(r, b, &e, depth) < 0){
  364. vtblockput(b);
  365. return -1;
  366. }
  367. }
  368. if(size < e.size)
  369. shrinksize(r, &e, size);
  370. e.size = size;
  371. vtentrypack(&e, b->data, r->offset % r->epb);
  372. vtblockput(b);
  373. return 0;
  374. }
  375. int
  376. vtfilesetdirsize(VtFile *r, u32int ds)
  377. {
  378. uvlong size;
  379. int epb;
  380. assert(ISLOCKED(r));
  381. epb = r->dsize/VtEntrySize;
  382. size = (uvlong)r->dsize*(ds/epb);
  383. size += VtEntrySize*(ds%epb);
  384. return vtfilesetsize(r, size);
  385. }
  386. u32int
  387. vtfilegetdirsize(VtFile *r)
  388. {
  389. ulong ds;
  390. uvlong size;
  391. int epb;
  392. assert(ISLOCKED(r));
  393. epb = r->dsize/VtEntrySize;
  394. size = vtfilegetsize(r);
  395. ds = epb*(size/r->dsize);
  396. ds += (size%r->dsize)/VtEntrySize;
  397. return ds;
  398. }
  399. int
  400. vtfilegetentry(VtFile *r, VtEntry *e)
  401. {
  402. VtBlock *b;
  403. assert(ISLOCKED(r));
  404. b = fileload(r, e);
  405. if(b == nil)
  406. return -1;
  407. vtblockput(b);
  408. return 0;
  409. }
  410. int
  411. vtfilesetentry(VtFile *r, VtEntry *e)
  412. {
  413. VtBlock *b;
  414. VtEntry ee;
  415. assert(ISLOCKED(r));
  416. b = fileload(r, &ee);
  417. if(b == nil)
  418. return -1;
  419. vtentrypack(e, b->data, r->offset % r->epb);
  420. vtblockput(b);
  421. return 0;
  422. }
  423. static VtBlock *
  424. blockwalk(VtBlock *p, int index, VtCache *c, int mode, VtEntry *e)
  425. {
  426. VtBlock *b;
  427. int type;
  428. uchar *score;
  429. VtEntry oe;
  430. switch(p->type){
  431. case VtDataType:
  432. assert(0);
  433. case VtDirType:
  434. type = e->type;
  435. score = e->score;
  436. break;
  437. default:
  438. type = p->type - 1;
  439. score = p->data+index*VtScoreSize;
  440. break;
  441. }
  442. /*print("walk from %V/%d ty %d to %V ty %d\n", p->score, index, p->type, score, type); */
  443. if(mode == VtOWRITE && vtglobaltolocal(score) == NilBlock){
  444. b = vtcacheallocblock(c, type);
  445. if(b)
  446. goto HaveCopy;
  447. }else
  448. b = vtcacheglobal(c, score, type);
  449. if(b == nil || mode == VtOREAD)
  450. return b;
  451. if(vtglobaltolocal(b->score) != NilBlock)
  452. return b;
  453. oe = *e;
  454. /*
  455. * Copy on write.
  456. */
  457. e->flags |= VtEntryLocal;
  458. b = vtblockcopy(b/*, e->tag, fs->ehi, fs->elo*/);
  459. if(b == nil)
  460. return nil;
  461. HaveCopy:
  462. if(p->type == VtDirType){
  463. memmove(e->score, b->score, VtScoreSize);
  464. vtentrypack(e, p->data, index);
  465. }else{
  466. memmove(p->data+index*VtScoreSize, b->score, VtScoreSize);
  467. }
  468. return b;
  469. }
  470. /*
  471. * Change the depth of the VtFile r.
  472. * The entry e for r is contained in block p.
  473. */
  474. static int
  475. growdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth)
  476. {
  477. VtBlock *b, *bb;
  478. VtEntry oe;
  479. assert(ISLOCKED(r));
  480. assert(depth <= VtPointerDepth);
  481. b = vtcacheglobal(r->c, e->score, e->type);
  482. if(b == nil)
  483. return -1;
  484. oe = *e;
  485. /*
  486. * Keep adding layers until we get to the right depth
  487. * or an error occurs.
  488. */
  489. while(DEPTH(e->type) < depth){
  490. bb = vtcacheallocblock(r->c, e->type+1);
  491. if(bb == nil)
  492. break;
  493. memmove(bb->data, b->score, VtScoreSize);
  494. memmove(e->score, bb->score, VtScoreSize);
  495. e->type++;
  496. e->flags |= VtEntryLocal;
  497. vtblockput(b);
  498. b = bb;
  499. }
  500. vtentrypack(e, p->data, r->offset % r->epb);
  501. vtblockput(b);
  502. if(DEPTH(e->type) == depth)
  503. return 0;
  504. return -1;
  505. }
  506. static int
  507. shrinkdepth(VtFile *r, VtBlock *p, VtEntry *e, int depth)
  508. {
  509. VtBlock *b, *nb, *ob, *rb;
  510. VtEntry oe;
  511. assert(ISLOCKED(r));
  512. assert(depth <= VtPointerDepth);
  513. rb = vtcacheglobal(r->c, e->score, e->type);
  514. if(rb == nil)
  515. return -1;
  516. /*
  517. * Walk down to the new root block.
  518. * We may stop early, but something is better than nothing.
  519. */
  520. oe = *e;
  521. ob = nil;
  522. b = rb;
  523. for(; DEPTH(e->type) > depth; e->type--){
  524. nb = vtcacheglobal(r->c, b->data, e->type-1);
  525. if(nb == nil)
  526. break;
  527. if(ob!=nil && ob!=rb)
  528. vtblockput(ob);
  529. ob = b;
  530. b = nb;
  531. }
  532. if(b == rb){
  533. vtblockput(rb);
  534. return 0;
  535. }
  536. /*
  537. * Right now, e points at the root block rb, b is the new root block,
  538. * and ob points at b. To update:
  539. *
  540. * (i) change e to point at b
  541. * (ii) zero the pointer ob -> b
  542. * (iii) free the root block
  543. *
  544. * p (the block containing e) must be written before
  545. * anything else.
  546. */
  547. /* (i) */
  548. memmove(e->score, b->score, VtScoreSize);
  549. vtentrypack(e, p->data, r->offset % r->epb);
  550. /* (ii) */
  551. memmove(ob->data, vtzeroscore, VtScoreSize);
  552. /* (iii) */
  553. vtblockput(rb);
  554. if(ob!=nil && ob!=rb)
  555. vtblockput(ob);
  556. vtblockput(b);
  557. if(DEPTH(e->type) == depth)
  558. return 0;
  559. return -1;
  560. }
  561. static int
  562. mkindices(VtEntry *e, u32int bn, int *index)
  563. {
  564. int i, np;
  565. memset(index, 0, (VtPointerDepth+1)*sizeof(int));
  566. np = e->psize/VtScoreSize;
  567. for(i=0; bn > 0; i++){
  568. if(i >= VtPointerDepth){
  569. werrstr("bad address 0x%lux", (ulong)bn);
  570. return -1;
  571. }
  572. index[i] = bn % np;
  573. bn /= np;
  574. }
  575. return i;
  576. }
  577. VtBlock *
  578. vtfileblock(VtFile *r, u32int bn, int mode)
  579. {
  580. VtBlock *b, *bb;
  581. int index[VtPointerDepth+1];
  582. VtEntry e;
  583. int i;
  584. int m;
  585. assert(ISLOCKED(r));
  586. assert(bn != NilBlock);
  587. b = fileload(r, &e);
  588. if(b == nil)
  589. return nil;
  590. i = mkindices(&e, bn, index);
  591. if(i < 0)
  592. goto Err;
  593. if(i > DEPTH(e.type)){
  594. if(mode == VtOREAD){
  595. werrstr("bad address 0x%lux", (ulong)bn);
  596. goto Err;
  597. }
  598. index[i] = 0;
  599. if(growdepth(r, b, &e, i) < 0)
  600. goto Err;
  601. }
  602. assert(b->type == VtDirType);
  603. index[DEPTH(e.type)] = r->offset % r->epb;
  604. /* mode for intermediate block */
  605. m = mode;
  606. if(m == VtOWRITE)
  607. m = VtORDWR;
  608. for(i=DEPTH(e.type); i>=0; i--){
  609. bb = blockwalk(b, index[i], r->c, i==0 ? mode : m, &e);
  610. if(bb == nil)
  611. goto Err;
  612. vtblockput(b);
  613. b = bb;
  614. }
  615. b->pc = getcallerpc(&r);
  616. return b;
  617. Err:
  618. vtblockput(b);
  619. return nil;
  620. }
  621. int
  622. vtfileblockscore(VtFile *r, u32int bn, uchar score[VtScoreSize])
  623. {
  624. VtBlock *b, *bb;
  625. int index[VtPointerDepth+1];
  626. VtEntry e;
  627. int i;
  628. assert(ISLOCKED(r));
  629. assert(bn != NilBlock);
  630. b = fileload(r, &e);
  631. if(b == nil)
  632. return -1;
  633. if(DEPTH(e.type) == 0){
  634. memmove(score, e.score, VtScoreSize);
  635. vtblockput(b);
  636. return 0;
  637. }
  638. i = mkindices(&e, bn, index);
  639. if(i < 0){
  640. vtblockput(b);
  641. return -1;
  642. }
  643. if(i > DEPTH(e.type)){
  644. memmove(score, vtzeroscore, VtScoreSize);
  645. vtblockput(b);
  646. return 0;
  647. }
  648. index[DEPTH(e.type)] = r->offset % r->epb;
  649. for(i=DEPTH(e.type); i>=1; i--){
  650. bb = blockwalk(b, index[i], r->c, VtOREAD, &e);
  651. if(bb == nil)
  652. goto Err;
  653. vtblockput(b);
  654. b = bb;
  655. if(memcmp(b->score, vtzeroscore, VtScoreSize) == 0)
  656. break;
  657. }
  658. memmove(score, b->data+index[0]*VtScoreSize, VtScoreSize);
  659. vtblockput(b);
  660. return 0;
  661. Err:
  662. vtblockput(b);
  663. return -1;
  664. }
  665. void
  666. vtfileincref(VtFile *r)
  667. {
  668. qlock(&r->lk);
  669. r->ref++;
  670. qunlock(&r->lk);
  671. }
  672. void
  673. vtfileclose(VtFile *r)
  674. {
  675. if(r == nil)
  676. return;
  677. qlock(&r->lk);
  678. r->ref--;
  679. if(r->ref){
  680. qunlock(&r->lk);
  681. return;
  682. }
  683. assert(r->ref == 0);
  684. qunlock(&r->lk);
  685. if(r->parent)
  686. vtfileclose(r->parent);
  687. memset(r, ~0, sizeof(*r));
  688. vtfree(r);
  689. }
  690. /*
  691. * Retrieve the block containing the entry for r.
  692. * If a snapshot has happened, we might need
  693. * to get a new copy of the block. We avoid this
  694. * in the common case by caching the score for
  695. * the block and the last epoch in which it was valid.
  696. *
  697. * We use r->mode to tell the difference between active
  698. * file system VtFiles (VtORDWR) and VtFiles for the
  699. * snapshot file system (VtOREAD).
  700. */
  701. static VtBlock*
  702. fileloadblock(VtFile *r, int mode)
  703. {
  704. char e[ERRMAX];
  705. u32int addr;
  706. VtBlock *b;
  707. switch(r->mode){
  708. default:
  709. assert(0);
  710. case VtORDWR:
  711. assert(r->mode == VtORDWR);
  712. if(r->local == 1){
  713. b = vtcacheglobal(r->c, r->score, VtDirType);
  714. if(b == nil)
  715. return nil;
  716. b->pc = getcallerpc(&r);
  717. return b;
  718. }
  719. assert(r->parent != nil);
  720. if(vtfilelock(r->parent, VtORDWR) < 0)
  721. return nil;
  722. b = vtfileblock(r->parent, r->offset/r->epb, VtORDWR);
  723. vtfileunlock(r->parent);
  724. if(b == nil)
  725. return nil;
  726. memmove(r->score, b->score, VtScoreSize);
  727. r->local = 1;
  728. return b;
  729. case VtOREAD:
  730. if(mode == VtORDWR){
  731. werrstr("read/write lock of read-only file");
  732. return nil;
  733. }
  734. addr = vtglobaltolocal(r->score);
  735. if(addr == NilBlock)
  736. return vtcacheglobal(r->c, r->score, VtDirType);
  737. b = vtcachelocal(r->c, addr, VtDirType);
  738. if(b)
  739. return b;
  740. /*
  741. * If it failed because the epochs don't match, the block has been
  742. * archived and reclaimed. Rewalk from the parent and get the
  743. * new pointer. This can't happen in the VtORDWR case
  744. * above because blocks in the current epoch don't get
  745. * reclaimed. The fact that we're VtOREAD means we're
  746. * a snapshot. (Or else the file system is read-only, but then
  747. * the archiver isn't going around deleting blocks.)
  748. */
  749. rerrstr(e, sizeof e);
  750. if(strcmp(e, ELabelMismatch) == 0){
  751. if(vtfilelock(r->parent, VtOREAD) < 0)
  752. return nil;
  753. b = vtfileblock(r->parent, r->offset/r->epb, VtOREAD);
  754. vtfileunlock(r->parent);
  755. if(b){
  756. fprint(2, "vtfilealloc: lost %V found %V\n",
  757. r->score, b->score);
  758. memmove(r->score, b->score, VtScoreSize);
  759. return b;
  760. }
  761. }
  762. return nil;
  763. }
  764. }
  765. int
  766. vtfilelock(VtFile *r, int mode)
  767. {
  768. VtBlock *b;
  769. if(mode == -1)
  770. mode = r->mode;
  771. b = fileloadblock(r, mode);
  772. if(b == nil)
  773. return -1;
  774. /*
  775. * The fact that we are holding b serves as the
  776. * lock entitling us to write to r->b.
  777. */
  778. assert(r->b == nil);
  779. r->b = b;
  780. b->pc = getcallerpc(&r);
  781. return 0;
  782. }
  783. /*
  784. * Lock two (usually sibling) VtFiles. This needs special care
  785. * because the Entries for both vtFiles might be in the same block.
  786. * We also try to lock blocks in left-to-right order within the tree.
  787. */
  788. int
  789. vtfilelock2(VtFile *r, VtFile *rr, int mode)
  790. {
  791. VtBlock *b, *bb;
  792. if(rr == nil)
  793. return vtfilelock(r, mode);
  794. if(mode == -1)
  795. mode = r->mode;
  796. if(r->parent==rr->parent && r->offset/r->epb == rr->offset/rr->epb){
  797. b = fileloadblock(r, mode);
  798. if(b == nil)
  799. return -1;
  800. vtblockduplock(b);
  801. bb = b;
  802. }else if(r->parent==rr->parent || r->offset > rr->offset){
  803. bb = fileloadblock(rr, mode);
  804. b = fileloadblock(r, mode);
  805. }else{
  806. b = fileloadblock(r, mode);
  807. bb = fileloadblock(rr, mode);
  808. }
  809. if(b == nil || bb == nil){
  810. if(b)
  811. vtblockput(b);
  812. if(bb)
  813. vtblockput(bb);
  814. return -1;
  815. }
  816. /*
  817. * The fact that we are holding b and bb serves
  818. * as the lock entitling us to write to r->b and rr->b.
  819. */
  820. r->b = b;
  821. rr->b = bb;
  822. b->pc = getcallerpc(&r);
  823. bb->pc = getcallerpc(&r);
  824. return 0;
  825. }
  826. void
  827. vtfileunlock(VtFile *r)
  828. {
  829. VtBlock *b;
  830. if(r->b == nil){
  831. fprint(2, "vtfileunlock: already unlocked\n");
  832. abort();
  833. }
  834. b = r->b;
  835. r->b = nil;
  836. vtblockput(b);
  837. }
  838. static VtBlock*
  839. fileload(VtFile *r, VtEntry *e)
  840. {
  841. VtBlock *b;
  842. assert(ISLOCKED(r));
  843. b = r->b;
  844. if(vtentryunpack(e, b->data, r->offset % r->epb) < 0)
  845. return nil;
  846. vtblockduplock(b);
  847. return b;
  848. }
  849. static int
  850. sizetodepth(uvlong s, int psize, int dsize)
  851. {
  852. int np;
  853. int d;
  854. /* determine pointer depth */
  855. np = psize/VtScoreSize;
  856. s = (s + dsize - 1)/dsize;
  857. for(d = 0; s > 1; d++)
  858. s = (s + np - 1)/np;
  859. return d;
  860. }
  861. long
  862. vtfileread(VtFile *f, void *data, long count, vlong offset)
  863. {
  864. int frag;
  865. VtBlock *b;
  866. VtEntry e;
  867. assert(ISLOCKED(f));
  868. vtfilegetentry(f, &e);
  869. if(count == 0)
  870. return 0;
  871. if(count < 0 || offset < 0){
  872. werrstr("vtfileread: bad offset or count");
  873. return -1;
  874. }
  875. if(offset >= e.size)
  876. return 0;
  877. if(offset+count > e.size)
  878. count = e.size - offset;
  879. frag = offset % e.dsize;
  880. if(frag+count > e.dsize)
  881. count = e.dsize - frag;
  882. b = vtfileblock(f, offset/e.dsize, VtOREAD);
  883. if(b == nil)
  884. return -1;
  885. memmove(data, b->data+frag, count);
  886. vtblockput(b);
  887. return count;
  888. }
  889. static long
  890. filewrite1(VtFile *f, void *data, long count, vlong offset)
  891. {
  892. int frag, m;
  893. VtBlock *b;
  894. VtEntry e;
  895. vtfilegetentry(f, &e);
  896. if(count < 0 || offset < 0){
  897. werrstr("vtfilewrite: bad offset or count");
  898. return -1;
  899. }
  900. frag = offset % e.dsize;
  901. if(frag+count > e.dsize)
  902. count = e.dsize - frag;
  903. m = VtORDWR;
  904. if(frag == 0 && count == e.dsize)
  905. m = VtOWRITE;
  906. b = vtfileblock(f, offset/e.dsize, m);
  907. if(b == nil)
  908. return -1;
  909. memmove(b->data+frag, data, count);
  910. if(m == VtOWRITE && frag+count < e.dsize)
  911. memset(b->data+frag+count, 0, e.dsize-frag-count);
  912. if(offset+count > e.size){
  913. vtfilegetentry(f, &e);
  914. e.size = offset+count;
  915. vtfilesetentry(f, &e);
  916. }
  917. vtblockput(b);
  918. return count;
  919. }
  920. long
  921. vtfilewrite(VtFile *f, void *data, long count, vlong offset)
  922. {
  923. long tot, m;
  924. assert(ISLOCKED(f));
  925. tot = 0;
  926. m = 0;
  927. while(tot < count){
  928. m = filewrite1(f, (char*)data+tot, count-tot, offset+tot);
  929. if(m <= 0)
  930. break;
  931. tot += m;
  932. }
  933. if(tot==0)
  934. return m;
  935. return tot;
  936. }
  937. static int
  938. flushblock(VtCache *c, VtBlock *bb, uchar score[VtScoreSize], int ppb, int epb,
  939. int type)
  940. {
  941. u32int addr;
  942. VtBlock *b;
  943. VtEntry e;
  944. int i;
  945. addr = vtglobaltolocal(score);
  946. if(addr == NilBlock)
  947. return 0;
  948. if(bb){
  949. b = bb;
  950. if(memcmp(b->score, score, VtScoreSize) != 0)
  951. abort();
  952. }else
  953. if((b = vtcachelocal(c, addr, type)) == nil)
  954. return -1;
  955. switch(type){
  956. case VtDataType:
  957. break;
  958. case VtDirType:
  959. for(i=0; i<epb; i++){
  960. if(vtentryunpack(&e, b->data, i) < 0)
  961. goto Err;
  962. if(!(e.flags&VtEntryActive))
  963. continue;
  964. if(flushblock(c, nil, e.score, e.psize/VtScoreSize, e.dsize/VtEntrySize,
  965. e.type) < 0)
  966. goto Err;
  967. vtentrypack(&e, b->data, i);
  968. }
  969. break;
  970. default: /* VtPointerTypeX */
  971. for(i=0; i<ppb; i++){
  972. if(flushblock(c, nil, b->data+VtScoreSize*i, ppb, epb, type-1) < 0)
  973. goto Err;
  974. }
  975. break;
  976. }
  977. if(vtblockwrite(b) < 0)
  978. goto Err;
  979. memmove(score, b->score, VtScoreSize);
  980. if(b != bb)
  981. vtblockput(b);
  982. return 0;
  983. Err:
  984. if(b != bb)
  985. vtblockput(b);
  986. return -1;
  987. }
  988. int
  989. vtfileflush(VtFile *f)
  990. {
  991. int ret;
  992. VtBlock *b;
  993. VtEntry e;
  994. assert(ISLOCKED(f));
  995. b = fileload(f, &e);
  996. if(!(e.flags&VtEntryLocal)){
  997. vtblockput(b);
  998. return 0;
  999. }
  1000. ret = flushblock(f->c, nil, e.score, e.psize/VtScoreSize, e.dsize/VtEntrySize,
  1001. e.type);
  1002. if(ret < 0){
  1003. vtblockput(b);
  1004. return -1;
  1005. }
  1006. vtentrypack(&e, b->data, f->offset % f->epb);
  1007. vtblockput(b);
  1008. return 0;
  1009. }
  1010. int
  1011. vtfileflushbefore(VtFile *r, u64int offset)
  1012. {
  1013. VtBlock *b, *bb;
  1014. VtEntry e;
  1015. int i, base, depth, ppb, epb, doflush;
  1016. int index[VtPointerDepth+1], j, ret;
  1017. VtBlock *bi[VtPointerDepth+2];
  1018. uchar *score;
  1019. assert(ISLOCKED(r));
  1020. if(offset == 0)
  1021. return 0;
  1022. b = fileload(r, &e);
  1023. if(b == nil)
  1024. return -1;
  1025. /*
  1026. * compute path through tree for the last written byte and the next one.
  1027. */
  1028. ret = -1;
  1029. memset(bi, 0, sizeof bi);
  1030. depth = DEPTH(e.type);
  1031. bi[depth+1] = b;
  1032. i = mkindices(&e, (offset-1)/e.dsize, index);
  1033. if(i < 0)
  1034. goto Err;
  1035. if(i > depth)
  1036. goto Err;
  1037. ppb = e.psize / VtScoreSize;
  1038. epb = e.dsize / VtEntrySize;
  1039. /*
  1040. * load the blocks along the last written byte
  1041. */
  1042. index[depth] = r->offset % r->epb;
  1043. for(i=depth; i>=0; i--){
  1044. bb = blockwalk(b, index[i], r->c, VtORDWR, &e);
  1045. if(bb == nil)
  1046. goto Err;
  1047. bi[i] = bb;
  1048. b = bb;
  1049. }
  1050. ret = 0;
  1051. /*
  1052. * walk up the path from leaf to root, flushing anything that
  1053. * has been finished.
  1054. */
  1055. base = e.type&~VtTypeDepthMask;
  1056. for(i=0; i<=depth; i++){
  1057. doflush = 0;
  1058. if(i == 0){
  1059. /* leaf: data or dir block */
  1060. if(offset%e.dsize == 0)
  1061. doflush = 1;
  1062. }else{
  1063. /*
  1064. * interior node: pointer blocks.
  1065. * specifically, b = bi[i] is a block whose index[i-1]'th entry
  1066. * points at bi[i-1].
  1067. */
  1068. b = bi[i];
  1069. /*
  1070. * the index entries up to but not including index[i-1] point at
  1071. * finished blocks, so flush them for sure.
  1072. */
  1073. for(j=0; j<index[i-1]; j++)
  1074. if(flushblock(r->c, nil, b->data+j*VtScoreSize, ppb, epb, base+i-1) < 0)
  1075. goto Err;
  1076. /*
  1077. * if index[i-1] is the last entry in the block and is global
  1078. * (i.e. the kid is flushed), then we can flush this block.
  1079. */
  1080. if(j==ppb-1 && vtglobaltolocal(b->data+j*VtScoreSize)==NilBlock)
  1081. doflush = 1;
  1082. }
  1083. if(doflush){
  1084. if(i == depth)
  1085. score = e.score;
  1086. else
  1087. score = bi[i+1]->data+index[i]*VtScoreSize;
  1088. if(flushblock(r->c, bi[i], score, ppb, epb, base+i) < 0)
  1089. goto Err;
  1090. }
  1091. }
  1092. Err:
  1093. /* top: entry. do this always so that the score is up-to-date */
  1094. vtentrypack(&e, bi[depth+1]->data, index[depth]);
  1095. for(i=0; i<nelem(bi); i++)
  1096. if(bi[i])
  1097. vtblockput(bi[i]);
  1098. return ret;
  1099. }