source.c 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  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. #include "error.h"
  13. #include "9.h"
  14. static int sizeToDepth(uint64_t s, int psize, int dsize);
  15. static uint32_t tagGen(void);
  16. static Block *sourceLoad(Source *r, Entry *e);
  17. static int sourceShrinkDepth(Source*, Block*, Entry*, int);
  18. static int sourceShrinkSize(Source*, Entry*, uint64_t);
  19. static int sourceGrowDepth(Source*, Block*, Entry*, int);
  20. #define sourceIsLocked(r) ((r)->b != nil)
  21. static Source *
  22. sourceAlloc(Fs *fs, Block *b, Source *p, uint32_t offset, int mode,
  23. int issnapshot)
  24. {
  25. int epb;
  26. uint32_t epoch;
  27. char *pname = nil;
  28. Source *r;
  29. Entry e;
  30. assert(p==nil || sourceIsLocked(p));
  31. if(p == nil){
  32. assert(offset == 0);
  33. epb = 1;
  34. }else
  35. epb = p->dsize / VtEntrySize;
  36. if(b->l.type != BtDir)
  37. goto Bad;
  38. /*
  39. * a non-active entry is the only thing that
  40. * can legitimately happen here. all the others
  41. * get prints.
  42. */
  43. if(!entryUnpack(&e, b->data, offset % epb)){
  44. pname = sourceName(p);
  45. consPrint("%s: %s %V: sourceAlloc: entryUnpack failed\n",
  46. fs->name, pname, b->score);
  47. goto Bad;
  48. }
  49. if(!(e.flags & VtEntryActive)){
  50. pname = sourceName(p);
  51. if(0) consPrint("%s: %s %V: sourceAlloc: not active\n",
  52. fs->name, pname, e.score);
  53. goto Bad;
  54. }
  55. if(e.psize < 256 || e.dsize < 256){
  56. pname = sourceName(p);
  57. consPrint("%s: %s %V: sourceAlloc: psize %u or dsize %u < 256\n",
  58. fs->name, pname, e.score, e.psize, e.dsize);
  59. goto Bad;
  60. }
  61. if(e.depth < sizeToDepth(e.size, e.psize, e.dsize)){
  62. pname = sourceName(p);
  63. consPrint("%s: %s %V: sourceAlloc: depth %u size %llud "
  64. "psize %u dsize %u\n", fs->name, pname,
  65. e.score, e.depth, e.size, e.psize, e.dsize);
  66. goto Bad;
  67. }
  68. if((e.flags & VtEntryLocal) && e.tag == 0){
  69. pname = sourceName(p);
  70. consPrint("%s: %s %V: sourceAlloc: flags %#ux tag %#ux\n",
  71. fs->name, pname, e.score, e.flags, e.tag);
  72. goto Bad;
  73. }
  74. if(e.dsize > fs->blockSize || e.psize > fs->blockSize){
  75. pname = sourceName(p);
  76. consPrint("%s: %s %V: sourceAlloc: psize %u or dsize %u "
  77. "> blocksize %u\n", fs->name, pname, e.score,
  78. e.psize, e.dsize, fs->blockSize);
  79. goto Bad;
  80. }
  81. epoch = b->l.epoch;
  82. if(mode == OReadWrite){
  83. if(e.snap != 0){
  84. vtSetError(ESnapRO);
  85. return nil;
  86. }
  87. }else if(e.snap != 0){
  88. if(e.snap < fs->elo){
  89. vtSetError(ESnapOld);
  90. return nil;
  91. }
  92. if(e.snap >= fs->ehi)
  93. goto Bad;
  94. epoch = e.snap;
  95. }
  96. r = vtMemAllocZ(sizeof(Source));
  97. r->fs = fs;
  98. r->mode = mode;
  99. r->issnapshot = issnapshot;
  100. r->dsize = e.dsize;
  101. r->gen = e.gen;
  102. r->dir = (e.flags & VtEntryDir) != 0;
  103. r->lk = vtLockAlloc();
  104. r->ref = 1;
  105. r->parent = p;
  106. if(p){
  107. vtLock(p->lk);
  108. assert(mode == OReadOnly || p->mode == OReadWrite);
  109. p->ref++;
  110. vtUnlock(p->lk);
  111. }
  112. r->epoch = epoch;
  113. // consPrint("sourceAlloc: have %V be.%d fse.%d %s\n", b->score,
  114. // b->l.epoch, r->fs->ehi, mode == OReadWrite? "rw": "ro");
  115. memmove(r->score, b->score, VtScoreSize);
  116. r->scoreEpoch = b->l.epoch;
  117. r->offset = offset;
  118. r->epb = epb;
  119. r->tag = b->l.tag;
  120. // consPrint("%s: sourceAlloc: %p -> %V %d\n", r, r->score, r->offset);
  121. return r;
  122. Bad:
  123. free(pname);
  124. vtSetError(EBadEntry);
  125. return nil;
  126. }
  127. Source *
  128. sourceRoot(Fs *fs, uint32_t addr, int mode)
  129. {
  130. Source *r;
  131. Block *b;
  132. b = cacheLocalData(fs->cache, addr, BtDir, RootTag, mode, 0);
  133. if(b == nil)
  134. return nil;
  135. if(mode == OReadWrite && b->l.epoch != fs->ehi){
  136. consPrint("sourceRoot: fs->ehi = %u, b->l = %L\n",
  137. fs->ehi, &b->l);
  138. blockPut(b);
  139. vtSetError(EBadRoot);
  140. return nil;
  141. }
  142. r = sourceAlloc(fs, b, nil, 0, mode, 0);
  143. blockPut(b);
  144. return r;
  145. }
  146. Source *
  147. sourceOpen(Source *r, uint32_t offset, int mode, int issnapshot)
  148. {
  149. uint32_t bn;
  150. Block *b;
  151. assert(sourceIsLocked(r));
  152. if(r->mode == OReadWrite)
  153. assert(r->epoch == r->b->l.epoch);
  154. if(!r->dir){
  155. vtSetError(ENotDir);
  156. return nil;
  157. }
  158. bn = offset/(r->dsize/VtEntrySize);
  159. b = sourceBlock(r, bn, mode);
  160. if(b == nil)
  161. return nil;
  162. r = sourceAlloc(r->fs, b, r, offset, mode, issnapshot);
  163. blockPut(b);
  164. return r;
  165. }
  166. Source *
  167. sourceCreate(Source *r, int dsize, int dir, uint32_t offset)
  168. {
  169. int i, epb, psize;
  170. uint32_t bn, size;
  171. Block *b;
  172. Entry e;
  173. Source *rr;
  174. assert(sourceIsLocked(r));
  175. if(!r->dir){
  176. vtSetError(ENotDir);
  177. return nil;
  178. }
  179. epb = r->dsize/VtEntrySize;
  180. psize = (dsize/VtScoreSize)*VtScoreSize;
  181. size = sourceGetDirSize(r);
  182. if(offset == 0){
  183. /*
  184. * look at a random block to see if we can find an empty entry
  185. */
  186. offset = lnrand(size+1);
  187. offset -= offset % epb;
  188. }
  189. /* try the given block and then try the last block */
  190. for(;;){
  191. bn = offset/epb;
  192. b = sourceBlock(r, bn, OReadWrite);
  193. if(b == nil)
  194. return nil;
  195. for(i=offset%r->epb; i<epb; i++){
  196. entryUnpack(&e, b->data, i);
  197. if((e.flags&VtEntryActive) == 0 && e.gen != ~0)
  198. goto Found;
  199. }
  200. blockPut(b);
  201. if(offset == size){
  202. fprint(2, "sourceCreate: cannot happen\n");
  203. vtSetError("sourceCreate: cannot happen");
  204. return nil;
  205. }
  206. offset = size;
  207. }
  208. Found:
  209. /* found an entry - gen already set */
  210. e.psize = psize;
  211. e.dsize = dsize;
  212. assert(psize && dsize);
  213. e.flags = VtEntryActive;
  214. if(dir)
  215. e.flags |= VtEntryDir;
  216. e.depth = 0;
  217. e.size = 0;
  218. memmove(e.score, vtZeroScore, VtScoreSize);
  219. e.tag = 0;
  220. e.snap = 0;
  221. e.archive = 0;
  222. entryPack(&e, b->data, i);
  223. blockDirty(b);
  224. offset = bn*epb + i;
  225. if(offset+1 > size){
  226. if(!sourceSetDirSize(r, offset+1)){
  227. blockPut(b);
  228. return nil;
  229. }
  230. }
  231. rr = sourceAlloc(r->fs, b, r, offset, OReadWrite, 0);
  232. blockPut(b);
  233. return rr;
  234. }
  235. static int
  236. sourceKill(Source *r, int doremove)
  237. {
  238. Entry e;
  239. Block *b;
  240. uint32_t addr;
  241. uint32_t tag;
  242. int type;
  243. assert(sourceIsLocked(r));
  244. b = sourceLoad(r, &e);
  245. if(b == nil)
  246. return 0;
  247. assert(b->l.epoch == r->fs->ehi);
  248. if(doremove==0 && e.size == 0){
  249. /* already truncated */
  250. blockPut(b);
  251. return 1;
  252. }
  253. /* remember info on link we are removing */
  254. addr = globalToLocal(e.score);
  255. type = entryType(&e);
  256. tag = e.tag;
  257. if(doremove){
  258. if(e.gen != ~0)
  259. e.gen++;
  260. e.dsize = 0;
  261. e.psize = 0;
  262. e.flags = 0;
  263. }else{
  264. e.flags &= ~VtEntryLocal;
  265. }
  266. e.depth = 0;
  267. e.size = 0;
  268. e.tag = 0;
  269. memmove(e.score, vtZeroScore, VtScoreSize);
  270. entryPack(&e, b->data, r->offset % r->epb);
  271. blockDirty(b);
  272. if(addr != NilBlock)
  273. blockRemoveLink(b, addr, type, tag, 1);
  274. blockPut(b);
  275. if(doremove){
  276. sourceUnlock(r);
  277. sourceClose(r);
  278. }
  279. return 1;
  280. }
  281. int
  282. sourceRemove(Source *r)
  283. {
  284. return sourceKill(r, 1);
  285. }
  286. int
  287. sourceTruncate(Source *r)
  288. {
  289. return sourceKill(r, 0);
  290. }
  291. uint64_t
  292. sourceGetSize(Source *r)
  293. {
  294. Entry e;
  295. Block *b;
  296. assert(sourceIsLocked(r));
  297. b = sourceLoad(r, &e);
  298. if(b == nil)
  299. return 0;
  300. blockPut(b);
  301. return e.size;
  302. }
  303. static int
  304. sourceShrinkSize(Source *r, Entry *e, uint64_t size)
  305. {
  306. int i, type, ppb;
  307. uint64_t ptrsz;
  308. uint32_t addr;
  309. uint8_t score[VtScoreSize];
  310. Block *b;
  311. type = entryType(e);
  312. b = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
  313. if(b == nil)
  314. return 0;
  315. ptrsz = e->dsize;
  316. ppb = e->psize/VtScoreSize;
  317. for(i=0; i+1<e->depth; i++)
  318. ptrsz *= ppb;
  319. while(type&BtLevelMask){
  320. if(b->addr == NilBlock || b->l.epoch != r->fs->ehi){
  321. /* not worth copying the block just so we can zero some of it */
  322. blockPut(b);
  323. return 0;
  324. }
  325. /*
  326. * invariant: each pointer in the tree rooted at b accounts for ptrsz bytes
  327. */
  328. /* zero the pointers to unnecessary blocks */
  329. i = (size+ptrsz-1)/ptrsz;
  330. for(; i<ppb; i++){
  331. addr = globalToLocal(b->data+i*VtScoreSize);
  332. memmove(b->data+i*VtScoreSize, vtZeroScore, VtScoreSize);
  333. blockDirty(b);
  334. if(addr != NilBlock)
  335. blockRemoveLink(b, addr, type-1, e->tag, 1);
  336. }
  337. /* recurse (go around again) on the partially necessary block */
  338. i = size/ptrsz;
  339. size = size%ptrsz;
  340. if(size == 0){
  341. blockPut(b);
  342. return 1;
  343. }
  344. ptrsz /= ppb;
  345. type--;
  346. memmove(score, b->data+i*VtScoreSize, VtScoreSize);
  347. blockPut(b);
  348. b = cacheGlobal(r->fs->cache, score, type, e->tag, OReadWrite);
  349. if(b == nil)
  350. return 0;
  351. }
  352. if(b->addr == NilBlock || b->l.epoch != r->fs->ehi){
  353. blockPut(b);
  354. return 0;
  355. }
  356. /*
  357. * No one ever truncates BtDir blocks.
  358. */
  359. if(type == BtData && e->dsize > size){
  360. memset(b->data+size, 0, e->dsize-size);
  361. blockDirty(b);
  362. }
  363. blockPut(b);
  364. return 1;
  365. }
  366. int
  367. sourceSetSize(Source *r, uint64_t size)
  368. {
  369. int depth;
  370. Entry e;
  371. Block *b;
  372. assert(sourceIsLocked(r));
  373. if(size == 0)
  374. return sourceTruncate(r);
  375. if(size > VtMaxFileSize || size > ((uint64_t)MaxBlock)*r->dsize){
  376. vtSetError(ETooBig);
  377. return 0;
  378. }
  379. b = sourceLoad(r, &e);
  380. if(b == nil)
  381. return 0;
  382. /* quick out */
  383. if(e.size == size){
  384. blockPut(b);
  385. return 1;
  386. }
  387. depth = sizeToDepth(size, e.psize, e.dsize);
  388. if(depth < e.depth){
  389. if(!sourceShrinkDepth(r, b, &e, depth)){
  390. blockPut(b);
  391. return 0;
  392. }
  393. }else if(depth > e.depth){
  394. if(!sourceGrowDepth(r, b, &e, depth)){
  395. blockPut(b);
  396. return 0;
  397. }
  398. }
  399. if(size < e.size)
  400. sourceShrinkSize(r, &e, size);
  401. e.size = size;
  402. entryPack(&e, b->data, r->offset % r->epb);
  403. blockDirty(b);
  404. blockPut(b);
  405. return 1;
  406. }
  407. int
  408. sourceSetDirSize(Source *r, uint32_t ds)
  409. {
  410. uint64_t size;
  411. int epb;
  412. assert(sourceIsLocked(r));
  413. epb = r->dsize/VtEntrySize;
  414. size = (uint64_t)r->dsize*(ds/epb);
  415. size += VtEntrySize*(ds%epb);
  416. return sourceSetSize(r, size);
  417. }
  418. uint32_t
  419. sourceGetDirSize(Source *r)
  420. {
  421. uint32_t ds;
  422. uint64_t size;
  423. int epb;
  424. assert(sourceIsLocked(r));
  425. epb = r->dsize/VtEntrySize;
  426. size = sourceGetSize(r);
  427. ds = epb*(size/r->dsize);
  428. ds += (size%r->dsize)/VtEntrySize;
  429. return ds;
  430. }
  431. int
  432. sourceGetEntry(Source *r, Entry *e)
  433. {
  434. Block *b;
  435. assert(sourceIsLocked(r));
  436. b = sourceLoad(r, e);
  437. if(b == nil)
  438. return 0;
  439. blockPut(b);
  440. return 1;
  441. }
  442. /*
  443. * Must be careful with this. Doesn't record
  444. * dependencies, so don't introduce any!
  445. */
  446. int
  447. sourceSetEntry(Source *r, Entry *e)
  448. {
  449. Block *b;
  450. Entry oe;
  451. assert(sourceIsLocked(r));
  452. b = sourceLoad(r, &oe);
  453. if(b == nil)
  454. return 0;
  455. entryPack(e, b->data, r->offset%r->epb);
  456. blockDirty(b);
  457. blockPut(b);
  458. return 1;
  459. }
  460. static Block *
  461. blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
  462. {
  463. Block *b;
  464. Cache *c;
  465. uint32_t addr;
  466. int type;
  467. uint8_t oscore[VtScoreSize], score[VtScoreSize];
  468. Entry oe;
  469. c = fs->cache;
  470. if((p->l.type & BtLevelMask) == 0){
  471. assert(p->l.type == BtDir);
  472. type = entryType(e);
  473. b = cacheGlobal(c, e->score, type, e->tag, mode);
  474. }else{
  475. type = p->l.type - 1;
  476. b = cacheGlobal(c, p->data + index*VtScoreSize, type, e->tag, mode);
  477. }
  478. if(b)
  479. b->pc = getcallerpc(&p);
  480. if(b == nil || mode == OReadOnly)
  481. return b;
  482. if(p->l.epoch != fs->ehi){
  483. fprint(2, "blockWalk: parent not writable\n");
  484. abort();
  485. }
  486. if(b->l.epoch == fs->ehi)
  487. return b;
  488. oe = *e;
  489. /*
  490. * Copy on write.
  491. */
  492. if(e->tag == 0){
  493. assert(p->l.type == BtDir);
  494. e->tag = tagGen();
  495. e->flags |= VtEntryLocal;
  496. }
  497. addr = b->addr;
  498. b = blockCopy(b, e->tag, fs->ehi, fs->elo);
  499. if(b == nil)
  500. return nil;
  501. b->pc = getcallerpc(&p);
  502. assert(b->l.epoch == fs->ehi);
  503. blockDirty(b);
  504. memmove(score, b->score, VtScoreSize);
  505. if(p->l.type == BtDir){
  506. memmove(e->score, b->score, VtScoreSize);
  507. entryPack(e, p->data, index);
  508. blockDependency(p, b, index, nil, &oe);
  509. }else{
  510. memmove(oscore, p->data+index*VtScoreSize, VtScoreSize);
  511. memmove(p->data+index*VtScoreSize, b->score, VtScoreSize);
  512. blockDependency(p, b, index, oscore, nil);
  513. }
  514. blockDirty(p);
  515. if(addr != NilBlock)
  516. blockRemoveLink(p, addr, type, e->tag, 0);
  517. return b;
  518. }
  519. /*
  520. * Change the depth of the source r.
  521. * The entry e for r is contained in block p.
  522. */
  523. static int
  524. sourceGrowDepth(Source *r, Block *p, Entry *e, int depth)
  525. {
  526. Block *b, *bb;
  527. uint32_t tag;
  528. int type;
  529. Entry oe;
  530. assert(sourceIsLocked(r));
  531. assert(depth <= VtPointerDepth);
  532. type = entryType(e);
  533. b = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
  534. if(b == nil)
  535. return 0;
  536. tag = e->tag;
  537. if(tag == 0)
  538. tag = tagGen();
  539. oe = *e;
  540. /*
  541. * Keep adding layers until we get to the right depth
  542. * or an error occurs.
  543. */
  544. while(e->depth < depth){
  545. bb = cacheAllocBlock(r->fs->cache, type+1, tag, r->fs->ehi, r->fs->elo);
  546. if(bb == nil)
  547. break;
  548. //fprint(2, "alloc %lx grow %V\n", bb->addr, b->score);
  549. memmove(bb->data, b->score, VtScoreSize);
  550. memmove(e->score, bb->score, VtScoreSize);
  551. e->depth++;
  552. type++;
  553. e->tag = tag;
  554. e->flags |= VtEntryLocal;
  555. blockDependency(bb, b, 0, vtZeroScore, nil);
  556. blockPut(b);
  557. b = bb;
  558. blockDirty(b);
  559. }
  560. entryPack(e, p->data, r->offset % r->epb);
  561. blockDependency(p, b, r->offset % r->epb, nil, &oe);
  562. blockPut(b);
  563. blockDirty(p);
  564. return e->depth == depth;
  565. }
  566. static int
  567. sourceShrinkDepth(Source *r, Block *p, Entry *e, int depth)
  568. {
  569. Block *b, *nb, *ob, *rb;
  570. uint32_t tag;
  571. int type, d;
  572. Entry oe;
  573. assert(sourceIsLocked(r));
  574. assert(depth <= VtPointerDepth);
  575. type = entryType(e);
  576. rb = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite);
  577. if(rb == nil)
  578. return 0;
  579. tag = e->tag;
  580. if(tag == 0)
  581. tag = tagGen();
  582. /*
  583. * Walk down to the new root block.
  584. * We may stop early, but something is better than nothing.
  585. */
  586. oe = *e;
  587. ob = nil;
  588. b = rb;
  589. /* BUG: explain type++. i think it is a real bug */
  590. for(d=e->depth; d > depth; d--, type++){
  591. nb = cacheGlobal(r->fs->cache, b->data, type-1, tag, OReadWrite);
  592. if(nb == nil)
  593. break;
  594. if(ob!=nil && ob!=rb)
  595. blockPut(ob);
  596. ob = b;
  597. b = nb;
  598. }
  599. if(b == rb){
  600. blockPut(rb);
  601. return 0;
  602. }
  603. /*
  604. * Right now, e points at the root block rb, b is the new root block,
  605. * and ob points at b. To update:
  606. *
  607. * (i) change e to point at b
  608. * (ii) zero the pointer ob -> b
  609. * (iii) free the root block
  610. *
  611. * p (the block containing e) must be written before
  612. * anything else.
  613. */
  614. /* (i) */
  615. e->depth = d;
  616. /* might have been local and now global; reverse cannot happen */
  617. if(globalToLocal(b->score) == NilBlock)
  618. e->flags &= ~VtEntryLocal;
  619. memmove(e->score, b->score, VtScoreSize);
  620. entryPack(e, p->data, r->offset % r->epb);
  621. blockDependency(p, b, r->offset % r->epb, nil, &oe);
  622. blockDirty(p);
  623. /* (ii) */
  624. memmove(ob->data, vtZeroScore, VtScoreSize);
  625. blockDependency(ob, p, 0, b->score, nil);
  626. blockDirty(ob);
  627. /* (iii) */
  628. if(rb->addr != NilBlock)
  629. blockRemoveLink(p, rb->addr, rb->l.type, rb->l.tag, 1);
  630. blockPut(rb);
  631. if(ob!=nil && ob!=rb)
  632. blockPut(ob);
  633. blockPut(b);
  634. return d == depth;
  635. }
  636. /*
  637. * Normally we return the block at the given number.
  638. * If early is set, we stop earlier in the tree. Setting early
  639. * to 1 gives us the block that contains the pointer to bn.
  640. */
  641. Block *
  642. _sourceBlock(Source *r, uint32_t bn, int mode, int early, uint32_t tag)
  643. {
  644. Block *b, *bb;
  645. int index[VtPointerDepth+1];
  646. Entry e;
  647. int i, np;
  648. int m;
  649. assert(sourceIsLocked(r));
  650. assert(bn != NilBlock);
  651. /* mode for intermediate block */
  652. m = mode;
  653. if(m == OOverWrite)
  654. m = OReadWrite;
  655. b = sourceLoad(r, &e);
  656. if(b == nil)
  657. return nil;
  658. if(r->issnapshot && (e.flags & VtEntryNoArchive)){
  659. blockPut(b);
  660. vtSetError(ENotArchived);
  661. return nil;
  662. }
  663. if(tag){
  664. if(e.tag == 0)
  665. e.tag = tag;
  666. else if(e.tag != tag){
  667. fprint(2, "tag mismatch\n");
  668. vtSetError("tag mismatch");
  669. goto Err;
  670. }
  671. }
  672. np = e.psize/VtScoreSize;
  673. memset(index, 0, sizeof(index));
  674. for(i=0; bn > 0; i++){
  675. if(i >= VtPointerDepth){
  676. vtSetError(EBadAddr);
  677. goto Err;
  678. }
  679. index[i] = bn % np;
  680. bn /= np;
  681. }
  682. if(i > e.depth){
  683. if(mode == OReadOnly){
  684. vtSetError(EBadAddr);
  685. goto Err;
  686. }
  687. if(!sourceGrowDepth(r, b, &e, i))
  688. goto Err;
  689. }
  690. index[e.depth] = r->offset % r->epb;
  691. for(i=e.depth; i>=early; i--){
  692. bb = blockWalk(b, index[i], m, r->fs, &e);
  693. if(bb == nil)
  694. goto Err;
  695. blockPut(b);
  696. b = bb;
  697. }
  698. b->pc = getcallerpc(&r);
  699. return b;
  700. Err:
  701. blockPut(b);
  702. return nil;
  703. }
  704. Block*
  705. sourceBlock(Source *r, uint32_t bn, int mode)
  706. {
  707. Block *b;
  708. b = _sourceBlock(r, bn, mode, 0, 0);
  709. if(b)
  710. b->pc = getcallerpc(&r);
  711. return b;
  712. }
  713. void
  714. sourceClose(Source *r)
  715. {
  716. if(r == nil)
  717. return;
  718. vtLock(r->lk);
  719. r->ref--;
  720. if(r->ref){
  721. vtUnlock(r->lk);
  722. return;
  723. }
  724. assert(r->ref == 0);
  725. vtUnlock(r->lk);
  726. if(r->parent)
  727. sourceClose(r->parent);
  728. vtLockFree(r->lk);
  729. memset(r, ~0, sizeof(*r));
  730. vtMemFree(r);
  731. }
  732. /*
  733. * Retrieve the block containing the entry for r.
  734. * If a snapshot has happened, we might need
  735. * to get a new copy of the block. We avoid this
  736. * in the common case by caching the score for
  737. * the block and the last epoch in which it was valid.
  738. *
  739. * We use r->mode to tell the difference between active
  740. * file system sources (OReadWrite) and sources for the
  741. * snapshot file system (OReadOnly).
  742. */
  743. static Block*
  744. sourceLoadBlock(Source *r, int mode)
  745. {
  746. uint32_t addr;
  747. Block *b;
  748. switch(r->mode){
  749. default:
  750. assert(0);
  751. case OReadWrite:
  752. assert(r->mode == OReadWrite);
  753. /*
  754. * This needn't be true -- we might bump the low epoch
  755. * to reclaim some old blocks, but since this score is
  756. * OReadWrite, the blocks must all still be open, so none
  757. * are reclaimed. Thus it's okay that the epoch is so low.
  758. * Proceed.
  759. assert(r->epoch >= r->fs->elo);
  760. */
  761. if(r->epoch == r->fs->ehi){
  762. b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
  763. if(b == nil)
  764. return nil;
  765. assert(r->epoch == b->l.epoch);
  766. return b;
  767. }
  768. assert(r->parent != nil);
  769. if(!sourceLock(r->parent, OReadWrite))
  770. return nil;
  771. b = sourceBlock(r->parent, r->offset/r->epb, OReadWrite);
  772. sourceUnlock(r->parent);
  773. if(b == nil)
  774. return nil;
  775. assert(b->l.epoch == r->fs->ehi);
  776. // fprint(2, "sourceLoadBlock %p %V => %V\n", r, r->score, b->score);
  777. memmove(r->score, b->score, VtScoreSize);
  778. r->scoreEpoch = b->l.epoch;
  779. r->tag = b->l.tag;
  780. r->epoch = r->fs->ehi;
  781. return b;
  782. case OReadOnly:
  783. addr = globalToLocal(r->score);
  784. if(addr == NilBlock)
  785. return cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, mode);
  786. b = cacheLocalData(r->fs->cache, addr, BtDir, r->tag, mode, r->scoreEpoch);
  787. if(b)
  788. return b;
  789. /*
  790. * If it failed because the epochs don't match, the block has been
  791. * archived and reclaimed. Rewalk from the parent and get the
  792. * new pointer. This can't happen in the OReadWrite case
  793. * above because blocks in the current epoch don't get
  794. * reclaimed. The fact that we're OReadOnly means we're
  795. * a snapshot. (Or else the file system is read-only, but then
  796. * the archiver isn't going around deleting blocks.)
  797. */
  798. if(strcmp(vtGetError(), ELabelMismatch) == 0){
  799. if(!sourceLock(r->parent, OReadOnly))
  800. return nil;
  801. b = sourceBlock(r->parent, r->offset/r->epb, OReadOnly);
  802. sourceUnlock(r->parent);
  803. if(b){
  804. fprint(2, "sourceAlloc: lost %V found %V\n",
  805. r->score, b->score);
  806. memmove(r->score, b->score, VtScoreSize);
  807. r->scoreEpoch = b->l.epoch;
  808. return b;
  809. }
  810. }
  811. return nil;
  812. }
  813. }
  814. int
  815. sourceLock(Source *r, int mode)
  816. {
  817. Block *b;
  818. if(mode == -1)
  819. mode = r->mode;
  820. b = sourceLoadBlock(r, mode);
  821. if(b == nil)
  822. return 0;
  823. /*
  824. * The fact that we are holding b serves as the
  825. * lock entitling us to write to r->b.
  826. */
  827. assert(r->b == nil);
  828. r->b = b;
  829. if(r->mode == OReadWrite)
  830. assert(r->epoch == r->b->l.epoch);
  831. return 1;
  832. }
  833. /*
  834. * Lock two (usually sibling) sources. This needs special care
  835. * because the Entries for both sources might be in the same block.
  836. * We also try to lock blocks in left-to-right order within the tree.
  837. */
  838. int
  839. sourceLock2(Source *r, Source *rr, int mode)
  840. {
  841. Block *b, *bb;
  842. if(rr == nil)
  843. return sourceLock(r, mode);
  844. if(mode == -1)
  845. mode = r->mode;
  846. if(r->parent==rr->parent && r->offset/r->epb == rr->offset/rr->epb){
  847. b = sourceLoadBlock(r, mode);
  848. if(b == nil)
  849. return 0;
  850. if(memcmp(r->score, rr->score, VtScoreSize) != 0){
  851. memmove(rr->score, b->score, VtScoreSize);
  852. rr->scoreEpoch = b->l.epoch;
  853. rr->tag = b->l.tag;
  854. rr->epoch = rr->fs->ehi;
  855. }
  856. blockDupLock(b);
  857. bb = b;
  858. }else if(r->parent==rr->parent || r->offset > rr->offset){
  859. bb = sourceLoadBlock(rr, mode);
  860. b = sourceLoadBlock(r, mode);
  861. }else{
  862. b = sourceLoadBlock(r, mode);
  863. bb = sourceLoadBlock(rr, mode);
  864. }
  865. if(b == nil || bb == nil){
  866. if(b)
  867. blockPut(b);
  868. if(bb)
  869. blockPut(bb);
  870. return 0;
  871. }
  872. /*
  873. * The fact that we are holding b and bb serves
  874. * as the lock entitling us to write to r->b and rr->b.
  875. */
  876. r->b = b;
  877. rr->b = bb;
  878. return 1;
  879. }
  880. void
  881. sourceUnlock(Source *r)
  882. {
  883. Block *b;
  884. if(r->b == nil){
  885. fprint(2, "sourceUnlock: already unlocked\n");
  886. abort();
  887. }
  888. b = r->b;
  889. r->b = nil;
  890. blockPut(b);
  891. }
  892. static Block*
  893. sourceLoad(Source *r, Entry *e)
  894. {
  895. Block *b;
  896. assert(sourceIsLocked(r));
  897. b = r->b;
  898. if(!entryUnpack(e, b->data, r->offset % r->epb))
  899. return nil;
  900. if(e->gen != r->gen){
  901. vtSetError(ERemoved);
  902. return nil;
  903. }
  904. blockDupLock(b);
  905. return b;
  906. }
  907. static int
  908. sizeToDepth(uint64_t s, int psize, int dsize)
  909. {
  910. int np;
  911. int d;
  912. /* determine pointer depth */
  913. np = psize/VtScoreSize;
  914. s = (s + dsize - 1)/dsize;
  915. for(d = 0; s > 1; d++)
  916. s = (s + np - 1)/np;
  917. return d;
  918. }
  919. static uint32_t
  920. tagGen(void)
  921. {
  922. uint32_t tag;
  923. for(;;){
  924. tag = lrand();
  925. if(tag >= UserTag)
  926. break;
  927. }
  928. return tag;
  929. }
  930. char *
  931. sourceName(Source *s)
  932. {
  933. return fileName(s->file);
  934. /*
  935. if (s!=nil)
  936. return fileName(s->file);
  937. else
  938. return fileName(nil);*/
  939. }