file.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860
  1. #include "stdinc.h"
  2. #include "9.h" /* for consPrint */
  3. #include "dat.h"
  4. #include "fns.h"
  5. #include "error.h"
  6. /*
  7. * locking order is upwards. A thread can hold the lock for a File
  8. * and then acquire the lock of its parent
  9. */
  10. struct File {
  11. Fs *fs; /* immutable */
  12. /* meta data for file: protected by the lk in the parent */
  13. int ref; /* holds this data structure up */
  14. int partial; /* file was never really open */
  15. int removed; /* file has been removed */
  16. int dirty; /* dir is dirty with respect to meta data in block */
  17. u32int boff; /* block offset within msource for this file's meta data */
  18. DirEntry dir; /* meta data for this file, including component name */
  19. File *up; /* parent file (directory) */
  20. File *next; /* sibling */
  21. /* data for file */
  22. VtLock *lk; /* lock for the following */
  23. Source *source;
  24. Source *msource; /* for directories: meta data for children */
  25. File *down; /* children */
  26. int mode;
  27. int issnapshot;
  28. };
  29. static int fileMetaFlush2(File*, char*);
  30. static u32int fileMetaAlloc(File*, DirEntry*, u32int);
  31. static int fileRLock(File*);
  32. static void fileRUnlock(File*);
  33. static int fileLock(File*);
  34. static void fileUnlock(File*);
  35. static void fileMetaLock(File*);
  36. static void fileMetaUnlock(File*);
  37. static void fileRAccess(File*);
  38. static void fileWAccess(File*, char*);
  39. static File *
  40. fileAlloc(Fs *fs)
  41. {
  42. File *f;
  43. f = vtMemAllocZ(sizeof(File));
  44. f->lk = vtLockAlloc();
  45. f->ref = 1;
  46. f->fs = fs;
  47. f->boff = NilBlock;
  48. f->mode = fs->mode;
  49. return f;
  50. }
  51. static void
  52. fileFree(File *f)
  53. {
  54. sourceClose(f->source);
  55. vtLockFree(f->lk);
  56. sourceClose(f->msource);
  57. deCleanup(&f->dir);
  58. memset(f, ~0, sizeof(File));
  59. vtMemFree(f);
  60. }
  61. /*
  62. * the file is locked already
  63. * f->msource is unlocked
  64. */
  65. static File *
  66. dirLookup(File *f, char *elem)
  67. {
  68. int i;
  69. MetaBlock mb;
  70. MetaEntry me;
  71. Block *b;
  72. Source *meta;
  73. File *ff;
  74. u32int bo, nb;
  75. meta = f->msource;
  76. b = nil;
  77. if(!sourceLock(meta, -1))
  78. return nil;
  79. nb = (sourceGetSize(meta)+meta->dsize-1)/meta->dsize;
  80. for(bo=0; bo<nb; bo++){
  81. b = sourceBlock(meta, bo, OReadOnly);
  82. if(b == nil)
  83. goto Err;
  84. if(!mbUnpack(&mb, b->data, meta->dsize))
  85. goto Err;
  86. if(mbSearch(&mb, elem, &i, &me)){
  87. ff = fileAlloc(f->fs);
  88. if(!deUnpack(&ff->dir, &me)){
  89. fileFree(ff);
  90. goto Err;
  91. }
  92. sourceUnlock(meta);
  93. blockPut(b);
  94. ff->boff = bo;
  95. ff->mode = f->mode;
  96. ff->issnapshot = f->issnapshot;
  97. return ff;
  98. }
  99. blockPut(b);
  100. b = nil;
  101. }
  102. vtSetError(ENoFile);
  103. /* fall through */
  104. Err:
  105. sourceUnlock(meta);
  106. blockPut(b);
  107. return nil;
  108. }
  109. File *
  110. fileRoot(Source *r)
  111. {
  112. Block *b;
  113. Source *r0, *r1, *r2;
  114. MetaBlock mb;
  115. MetaEntry me;
  116. File *root, *mr;
  117. Fs *fs;
  118. b = nil;
  119. root = nil;
  120. mr = nil;
  121. r1 = nil;
  122. r2 = nil;
  123. fs = r->fs;
  124. if(!sourceLock(r, -1))
  125. return nil;
  126. r0 = sourceOpen(r, 0, fs->mode, 0);
  127. if(r0 == nil)
  128. goto Err;
  129. r1 = sourceOpen(r, 1, fs->mode, 0);
  130. if(r1 == nil)
  131. goto Err;
  132. r2 = sourceOpen(r, 2, fs->mode, 0);
  133. if(r2 == nil)
  134. goto Err;
  135. mr = fileAlloc(fs);
  136. mr->msource = r2;
  137. r2 = nil;
  138. root = fileAlloc(fs);
  139. root->boff = 0;
  140. root->up = mr;
  141. root->source = r0;
  142. r0->file = root; /* point back to source */
  143. r0 = nil;
  144. root->msource = r1;
  145. r1 = nil;
  146. mr->down = root;
  147. if(!sourceLock(mr->msource, -1))
  148. goto Err;
  149. b = sourceBlock(mr->msource, 0, OReadOnly);
  150. sourceUnlock(mr->msource);
  151. if(b == nil)
  152. goto Err;
  153. if(!mbUnpack(&mb, b->data, mr->msource->dsize))
  154. goto Err;
  155. meUnpack(&me, &mb, 0);
  156. if(!deUnpack(&root->dir, &me))
  157. goto Err;
  158. blockPut(b);
  159. sourceUnlock(r);
  160. fileRAccess(root);
  161. return root;
  162. Err:
  163. blockPut(b);
  164. if(r0)
  165. sourceClose(r0);
  166. if(r1)
  167. sourceClose(r1);
  168. if(r2)
  169. sourceClose(r2);
  170. if(mr)
  171. fileFree(mr);
  172. if(root)
  173. fileFree(root);
  174. sourceUnlock(r);
  175. return nil;
  176. }
  177. static Source *
  178. fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode,
  179. int issnapshot)
  180. {
  181. char *rname, *fname;
  182. Source *r;
  183. if(!sourceLock(f->source, mode))
  184. return nil;
  185. r = sourceOpen(f->source, offset, mode, issnapshot);
  186. sourceUnlock(f->source);
  187. if(r == nil)
  188. return nil;
  189. if(r->gen != gen){
  190. vtSetError(ERemoved);
  191. goto Err;
  192. }
  193. if(r->dir != dir && r->mode != -1){
  194. /* this hasn't been as useful as we hoped it would be. */
  195. rname = sourceName(r);
  196. fname = fileName(f);
  197. consPrint("%s: source %s for file %s: fileOpenSource: "
  198. "dir mismatch %d %d\n",
  199. f->source->fs->name, rname, fname, r->dir, dir);
  200. free(rname);
  201. free(fname);
  202. vtSetError(EBadMeta);
  203. goto Err;
  204. }
  205. return r;
  206. Err:
  207. sourceClose(r);
  208. return nil;
  209. }
  210. File *
  211. _fileWalk(File *f, char *elem, int partial)
  212. {
  213. File *ff;
  214. fileRAccess(f);
  215. if(elem[0] == 0){
  216. vtSetError(EBadPath);
  217. return nil;
  218. }
  219. if(!fileIsDir(f)){
  220. vtSetError(ENotDir);
  221. return nil;
  222. }
  223. if(strcmp(elem, ".") == 0){
  224. return fileIncRef(f);
  225. }
  226. if(strcmp(elem, "..") == 0){
  227. if(fileIsRoot(f))
  228. return fileIncRef(f);
  229. return fileIncRef(f->up);
  230. }
  231. if(!fileLock(f))
  232. return nil;
  233. for(ff = f->down; ff; ff=ff->next){
  234. if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
  235. ff->ref++;
  236. goto Exit;
  237. }
  238. }
  239. ff = dirLookup(f, elem);
  240. if(ff == nil)
  241. goto Err;
  242. if(ff->dir.mode & ModeSnapshot){
  243. ff->mode = OReadOnly;
  244. ff->issnapshot = 1;
  245. }
  246. if(partial){
  247. /*
  248. * Do nothing. We're opening this file only so we can clri it.
  249. * Usually the sources can't be opened, hence we won't even bother.
  250. * Be VERY careful with the returned file. If you hand it to a routine
  251. * expecting ff->source and/or ff->msource to be non-nil, we're
  252. * likely to dereference nil. FileClri should be the only routine
  253. * setting partial.
  254. */
  255. ff->partial = 1;
  256. }else if(ff->dir.mode & ModeDir){
  257. ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
  258. 1, ff->mode, ff->issnapshot);
  259. ff->msource = fileOpenSource(f, ff->dir.mentry, ff->dir.mgen,
  260. 0, ff->mode, ff->issnapshot);
  261. if(ff->source == nil || ff->msource == nil)
  262. goto Err;
  263. }else{
  264. ff->source = fileOpenSource(f, ff->dir.entry, ff->dir.gen,
  265. 0, ff->mode, ff->issnapshot);
  266. if(ff->source == nil)
  267. goto Err;
  268. }
  269. /* link in and up parent ref count */
  270. if (ff->source)
  271. ff->source->file = ff; /* point back */
  272. ff->next = f->down;
  273. f->down = ff;
  274. ff->up = f;
  275. fileIncRef(f);
  276. Exit:
  277. fileUnlock(f);
  278. return ff;
  279. Err:
  280. fileUnlock(f);
  281. if(ff != nil)
  282. fileDecRef(ff);
  283. return nil;
  284. }
  285. File *
  286. fileWalk(File *f, char *elem)
  287. {
  288. return _fileWalk(f, elem, 0);
  289. }
  290. File *
  291. _fileOpen(Fs *fs, char *path, int partial)
  292. {
  293. File *f, *ff;
  294. char *p, elem[VtMaxStringSize], *opath;
  295. int n;
  296. f = fs->file;
  297. fileIncRef(f);
  298. opath = path;
  299. while(*path != 0){
  300. for(p = path; *p && *p != '/'; p++)
  301. ;
  302. n = p - path;
  303. if(n > 0){
  304. if(n > VtMaxStringSize){
  305. vtSetError("%s: element too long", EBadPath);
  306. goto Err;
  307. }
  308. memmove(elem, path, n);
  309. elem[n] = 0;
  310. ff = _fileWalk(f, elem, partial && *p=='\0');
  311. if(ff == nil){
  312. vtSetError("%.*s: %R", utfnlen(opath, p-opath),
  313. opath);
  314. goto Err;
  315. }
  316. fileDecRef(f);
  317. f = ff;
  318. }
  319. if(*p == '/')
  320. p++;
  321. path = p;
  322. }
  323. return f;
  324. Err:
  325. fileDecRef(f);
  326. return nil;
  327. }
  328. File*
  329. fileOpen(Fs *fs, char *path)
  330. {
  331. return _fileOpen(fs, path, 0);
  332. }
  333. static void
  334. fileSetTmp(File *f, int istmp)
  335. {
  336. int i;
  337. Entry e;
  338. Source *r;
  339. for(i=0; i<2; i++){
  340. if(i==0)
  341. r = f->source;
  342. else
  343. r = f->msource;
  344. if(r == nil)
  345. continue;
  346. if(!sourceGetEntry(r, &e)){
  347. fprint(2, "sourceGetEntry failed (cannot happen): %r\n");
  348. continue;
  349. }
  350. if(istmp)
  351. e.flags |= VtEntryNoArchive;
  352. else
  353. e.flags &= ~VtEntryNoArchive;
  354. if(!sourceSetEntry(r, &e)){
  355. fprint(2, "sourceSetEntry failed (cannot happen): %r\n");
  356. continue;
  357. }
  358. }
  359. }
  360. File *
  361. fileCreate(File *f, char *elem, ulong mode, char *uid)
  362. {
  363. File *ff;
  364. DirEntry *dir;
  365. Source *pr, *r, *mr;
  366. int isdir;
  367. if(!fileLock(f))
  368. return nil;
  369. r = nil;
  370. mr = nil;
  371. for(ff = f->down; ff; ff=ff->next){
  372. if(strcmp(elem, ff->dir.elem) == 0 && !ff->removed){
  373. ff = nil;
  374. vtSetError(EExists);
  375. goto Err1;
  376. }
  377. }
  378. ff = dirLookup(f, elem);
  379. if(ff != nil){
  380. vtSetError(EExists);
  381. goto Err1;
  382. }
  383. pr = f->source;
  384. if(pr->mode != OReadWrite){
  385. vtSetError(EReadOnly);
  386. goto Err1;
  387. }
  388. if(!sourceLock2(f->source, f->msource, -1))
  389. goto Err1;
  390. ff = fileAlloc(f->fs);
  391. isdir = mode & ModeDir;
  392. r = sourceCreate(pr, pr->dsize, isdir, 0);
  393. if(r == nil)
  394. goto Err;
  395. if(isdir){
  396. mr = sourceCreate(pr, pr->dsize, 0, r->offset);
  397. if(mr == nil)
  398. goto Err;
  399. }
  400. dir = &ff->dir;
  401. dir->elem = vtStrDup(elem);
  402. dir->entry = r->offset;
  403. dir->gen = r->gen;
  404. if(isdir){
  405. dir->mentry = mr->offset;
  406. dir->mgen = mr->gen;
  407. }
  408. dir->size = 0;
  409. if(!fsNextQid(f->fs, &dir->qid))
  410. goto Err;
  411. dir->uid = vtStrDup(uid);
  412. dir->gid = vtStrDup(f->dir.gid);
  413. dir->mid = vtStrDup(uid);
  414. dir->mtime = time(0L);
  415. dir->mcount = 0;
  416. dir->ctime = dir->mtime;
  417. dir->atime = dir->mtime;
  418. dir->mode = mode;
  419. ff->boff = fileMetaAlloc(f, dir, 0);
  420. if(ff->boff == NilBlock)
  421. goto Err;
  422. sourceUnlock(f->source);
  423. sourceUnlock(f->msource);
  424. ff->source = r;
  425. r->file = ff; /* point back */
  426. ff->msource = mr;
  427. if(mode&ModeTemporary){
  428. if(!sourceLock2(r, mr, -1))
  429. goto Err1;
  430. fileSetTmp(ff, 1);
  431. sourceUnlock(r);
  432. if(mr)
  433. sourceUnlock(mr);
  434. }
  435. /* committed */
  436. /* link in and up parent ref count */
  437. ff->next = f->down;
  438. f->down = ff;
  439. ff->up = f;
  440. fileIncRef(f);
  441. fileWAccess(f, uid);
  442. fileUnlock(f);
  443. return ff;
  444. Err:
  445. sourceUnlock(f->source);
  446. sourceUnlock(f->msource);
  447. Err1:
  448. if(r){
  449. sourceLock(r, -1);
  450. sourceRemove(r);
  451. }
  452. if(mr){
  453. sourceLock(mr, -1);
  454. sourceRemove(mr);
  455. }
  456. if(ff)
  457. fileDecRef(ff);
  458. fileUnlock(f);
  459. return 0;
  460. }
  461. int
  462. fileRead(File *f, void *buf, int cnt, vlong offset)
  463. {
  464. Source *s;
  465. uvlong size;
  466. u32int bn;
  467. int off, dsize, n, nn;
  468. Block *b;
  469. uchar *p;
  470. if(0)fprint(2, "fileRead: %s %d, %lld\n", f->dir.elem, cnt, offset);
  471. if(!fileRLock(f))
  472. return -1;
  473. if(offset < 0){
  474. vtSetError(EBadOffset);
  475. goto Err1;
  476. }
  477. fileRAccess(f);
  478. if(!sourceLock(f->source, OReadOnly))
  479. goto Err1;
  480. s = f->source;
  481. dsize = s->dsize;
  482. size = sourceGetSize(s);
  483. if(offset >= size)
  484. offset = size;
  485. if(cnt > size-offset)
  486. cnt = size-offset;
  487. bn = offset/dsize;
  488. off = offset%dsize;
  489. p = buf;
  490. while(cnt > 0){
  491. b = sourceBlock(s, bn, OReadOnly);
  492. if(b == nil)
  493. goto Err;
  494. n = cnt;
  495. if(n > dsize-off)
  496. n = dsize-off;
  497. nn = dsize-off;
  498. if(nn > n)
  499. nn = n;
  500. memmove(p, b->data+off, nn);
  501. memset(p+nn, 0, nn-n);
  502. off = 0;
  503. bn++;
  504. cnt -= n;
  505. p += n;
  506. blockPut(b);
  507. }
  508. sourceUnlock(s);
  509. fileRUnlock(f);
  510. return p-(uchar*)buf;
  511. Err:
  512. sourceUnlock(s);
  513. Err1:
  514. fileRUnlock(f);
  515. return -1;
  516. }
  517. /*
  518. * Changes the file block bn to be the given block score.
  519. * Very sneaky. Only used by flfmt.
  520. */
  521. int
  522. fileMapBlock(File *f, ulong bn, uchar score[VtScoreSize], ulong tag)
  523. {
  524. Block *b;
  525. Entry e;
  526. Source *s;
  527. if(!fileLock(f))
  528. return 0;
  529. s = nil;
  530. if(f->dir.mode & ModeDir){
  531. vtSetError(ENotFile);
  532. goto Err;
  533. }
  534. if(f->source->mode != OReadWrite){
  535. vtSetError(EReadOnly);
  536. goto Err;
  537. }
  538. if(!sourceLock(f->source, -1))
  539. goto Err;
  540. s = f->source;
  541. b = _sourceBlock(s, bn, OReadWrite, 1, tag);
  542. if(b == nil)
  543. goto Err;
  544. if(!sourceGetEntry(s, &e))
  545. goto Err;
  546. if(b->l.type == BtDir){
  547. memmove(e.score, score, VtScoreSize);
  548. assert(e.tag == tag || e.tag == 0);
  549. e.tag = tag;
  550. e.flags |= VtEntryLocal;
  551. entryPack(&e, b->data, f->source->offset % f->source->epb);
  552. }else
  553. memmove(b->data + (bn%(e.psize/VtScoreSize))*VtScoreSize, score, VtScoreSize);
  554. blockDirty(b);
  555. blockPut(b);
  556. sourceUnlock(s);
  557. fileUnlock(f);
  558. return 1;
  559. Err:
  560. if(s)
  561. sourceUnlock(s);
  562. fileUnlock(f);
  563. return 0;
  564. }
  565. int
  566. fileSetSize(File *f, uvlong size)
  567. {
  568. int r;
  569. if(!fileLock(f))
  570. return 0;
  571. r = 0;
  572. if(f->dir.mode & ModeDir){
  573. vtSetError(ENotFile);
  574. goto Err;
  575. }
  576. if(f->source->mode != OReadWrite){
  577. vtSetError(EReadOnly);
  578. goto Err;
  579. }
  580. if(!sourceLock(f->source, -1))
  581. goto Err;
  582. r = sourceSetSize(f->source, size);
  583. sourceUnlock(f->source);
  584. Err:
  585. fileUnlock(f);
  586. return r;
  587. }
  588. int
  589. fileWrite(File *f, void *buf, int cnt, vlong offset, char *uid)
  590. {
  591. Source *s;
  592. ulong bn;
  593. int off, dsize, n;
  594. Block *b;
  595. uchar *p;
  596. vlong eof;
  597. if(0)fprint(2, "fileWrite: %s %d, %lld\n", f->dir.elem, cnt, offset);
  598. if(!fileLock(f))
  599. return -1;
  600. s = nil;
  601. if(f->dir.mode & ModeDir){
  602. vtSetError(ENotFile);
  603. goto Err;
  604. }
  605. if(f->source->mode != OReadWrite){
  606. vtSetError(EReadOnly);
  607. goto Err;
  608. }
  609. if(offset < 0){
  610. vtSetError(EBadOffset);
  611. goto Err;
  612. }
  613. fileWAccess(f, uid);
  614. if(!sourceLock(f->source, -1))
  615. goto Err;
  616. s = f->source;
  617. dsize = s->dsize;
  618. eof = sourceGetSize(s);
  619. if(f->dir.mode & ModeAppend)
  620. offset = eof;
  621. bn = offset/dsize;
  622. off = offset%dsize;
  623. p = buf;
  624. while(cnt > 0){
  625. n = cnt;
  626. if(n > dsize-off)
  627. n = dsize-off;
  628. b = sourceBlock(s, bn, n<dsize?OReadWrite:OOverWrite);
  629. if(b == nil){
  630. if(offset > eof)
  631. sourceSetSize(s, offset);
  632. goto Err;
  633. }
  634. memmove(b->data+off, p, n);
  635. off = 0;
  636. cnt -= n;
  637. p += n;
  638. offset += n;
  639. bn++;
  640. blockDirty(b);
  641. blockPut(b);
  642. }
  643. if(offset > eof && !sourceSetSize(s, offset))
  644. goto Err;
  645. sourceUnlock(s);
  646. fileUnlock(f);
  647. return p-(uchar*)buf;
  648. Err:
  649. if(s)
  650. sourceUnlock(s);
  651. fileUnlock(f);
  652. return -1;
  653. }
  654. int
  655. fileGetDir(File *f, DirEntry *dir)
  656. {
  657. if(!fileRLock(f))
  658. return 0;
  659. fileMetaLock(f);
  660. deCopy(dir, &f->dir);
  661. fileMetaUnlock(f);
  662. if(!fileIsDir(f)){
  663. if(!sourceLock(f->source, OReadOnly)){
  664. fileRUnlock(f);
  665. return 0;
  666. }
  667. dir->size = sourceGetSize(f->source);
  668. sourceUnlock(f->source);
  669. }
  670. fileRUnlock(f);
  671. return 1;
  672. }
  673. int
  674. fileTruncate(File *f, char *uid)
  675. {
  676. if(fileIsDir(f)){
  677. vtSetError(ENotFile);
  678. return 0;
  679. }
  680. if(!fileLock(f))
  681. return 0;
  682. if(f->source->mode != OReadWrite){
  683. vtSetError(EReadOnly);
  684. fileUnlock(f);
  685. return 0;
  686. }
  687. if(!sourceLock(f->source, -1)){
  688. fileUnlock(f);
  689. return 0;
  690. }
  691. if(!sourceTruncate(f->source)){
  692. sourceUnlock(f->source);
  693. fileUnlock(f);
  694. return 0;
  695. }
  696. sourceUnlock(f->source);
  697. fileUnlock(f);
  698. fileWAccess(f, uid);
  699. return 1;
  700. }
  701. int
  702. fileSetDir(File *f, DirEntry *dir, char *uid)
  703. {
  704. File *ff;
  705. char *oelem;
  706. u32int mask;
  707. u64int size;
  708. /* can not set permissions for the root */
  709. if(fileIsRoot(f)){
  710. vtSetError(ERoot);
  711. return 0;
  712. }
  713. if(!fileLock(f))
  714. return 0;
  715. if(f->source->mode != OReadWrite){
  716. vtSetError(EReadOnly);
  717. fileUnlock(f);
  718. return 0;
  719. }
  720. fileMetaLock(f);
  721. /* check new name does not already exist */
  722. if(strcmp(f->dir.elem, dir->elem) != 0){
  723. for(ff = f->up->down; ff; ff=ff->next){
  724. if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){
  725. vtSetError(EExists);
  726. goto Err;
  727. }
  728. }
  729. ff = dirLookup(f->up, dir->elem);
  730. if(ff != nil){
  731. fileDecRef(ff);
  732. vtSetError(EExists);
  733. goto Err;
  734. }
  735. }
  736. if(!sourceLock2(f->source, f->msource, -1))
  737. goto Err;
  738. if(!fileIsDir(f)){
  739. size = sourceGetSize(f->source);
  740. if(size != dir->size){
  741. if(!sourceSetSize(f->source, dir->size)){
  742. sourceUnlock(f->source);
  743. if(f->msource)
  744. sourceUnlock(f->msource);
  745. goto Err;
  746. }
  747. /* commited to changing it now */
  748. }
  749. }
  750. /* commited to changing it now */
  751. if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary))
  752. fileSetTmp(f, dir->mode&ModeTemporary);
  753. sourceUnlock(f->source);
  754. if(f->msource)
  755. sourceUnlock(f->msource);
  756. oelem = nil;
  757. if(strcmp(f->dir.elem, dir->elem) != 0){
  758. oelem = f->dir.elem;
  759. f->dir.elem = vtStrDup(dir->elem);
  760. }
  761. if(strcmp(f->dir.uid, dir->uid) != 0){
  762. vtMemFree(f->dir.uid);
  763. f->dir.uid = vtStrDup(dir->uid);
  764. }
  765. if(strcmp(f->dir.gid, dir->gid) != 0){
  766. vtMemFree(f->dir.gid);
  767. f->dir.gid = vtStrDup(dir->gid);
  768. }
  769. f->dir.mtime = dir->mtime;
  770. f->dir.atime = dir->atime;
  771. //fprint(2, "mode %x %x ", f->dir.mode, dir->mode);
  772. mask = ~(ModeDir|ModeSnapshot);
  773. f->dir.mode &= ~mask;
  774. f->dir.mode |= mask & dir->mode;
  775. f->dirty = 1;
  776. //fprint(2, "->%x\n", f->dir.mode);
  777. fileMetaFlush2(f, oelem);
  778. vtMemFree(oelem);
  779. fileMetaUnlock(f);
  780. fileUnlock(f);
  781. fileWAccess(f->up, uid);
  782. return 1;
  783. Err:
  784. fileMetaUnlock(f);
  785. fileUnlock(f);
  786. return 0;
  787. }
  788. int
  789. fileSetQidSpace(File *f, u64int offset, u64int max)
  790. {
  791. int ret;
  792. if(!fileLock(f))
  793. return 0;
  794. fileMetaLock(f);
  795. f->dir.qidSpace = 1;
  796. f->dir.qidOffset = offset;
  797. f->dir.qidMax = max;
  798. ret = fileMetaFlush2(f, nil)>=0;
  799. fileMetaUnlock(f);
  800. fileUnlock(f);
  801. return ret;
  802. }
  803. uvlong
  804. fileGetId(File *f)
  805. {
  806. /* immutable */
  807. return f->dir.qid;
  808. }
  809. ulong
  810. fileGetMcount(File *f)
  811. {
  812. ulong mcount;
  813. fileMetaLock(f);
  814. mcount = f->dir.mcount;
  815. fileMetaUnlock(f);
  816. return mcount;
  817. }
  818. ulong
  819. fileGetMode(File *f)
  820. {
  821. ulong mode;
  822. fileMetaLock(f);
  823. mode = f->dir.mode;
  824. fileMetaUnlock(f);
  825. return mode;
  826. }
  827. int
  828. fileIsDir(File *f)
  829. {
  830. /* immutable */
  831. return (f->dir.mode & ModeDir) != 0;
  832. }
  833. int
  834. fileIsAppend(File *f)
  835. {
  836. return (f->dir.mode & ModeAppend) != 0;
  837. }
  838. int
  839. fileIsExclusive(File *f)
  840. {
  841. return (f->dir.mode & ModeExclusive) != 0;
  842. }
  843. int
  844. fileIsTemporary(File *f)
  845. {
  846. return (f->dir.mode & ModeTemporary) != 0;
  847. }
  848. int
  849. fileIsRoot(File *f)
  850. {
  851. return f == f->fs->file;
  852. }
  853. int
  854. fileIsRoFs(File *f)
  855. {
  856. return f->fs->mode == OReadOnly;
  857. }
  858. int
  859. fileGetSize(File *f, uvlong *size)
  860. {
  861. if(!fileRLock(f))
  862. return 0;
  863. if(!sourceLock(f->source, OReadOnly)){
  864. fileRUnlock(f);
  865. return 0;
  866. }
  867. *size = sourceGetSize(f->source);
  868. sourceUnlock(f->source);
  869. fileRUnlock(f);
  870. return 1;
  871. }
  872. int
  873. fileMetaFlush(File *f, int rec)
  874. {
  875. File **kids, *p;
  876. int nkids;
  877. int i, rv;
  878. fileMetaLock(f);
  879. rv = fileMetaFlush2(f, nil);
  880. fileMetaUnlock(f);
  881. if(!rec || !fileIsDir(f))
  882. return rv;
  883. if(!fileLock(f))
  884. return rv;
  885. nkids = 0;
  886. for(p=f->down; p; p=p->next)
  887. nkids++;
  888. kids = vtMemAlloc(nkids*sizeof(File*));
  889. i = 0;
  890. for(p=f->down; p; p=p->next){
  891. kids[i++] = p;
  892. p->ref++;
  893. }
  894. fileUnlock(f);
  895. for(i=0; i<nkids; i++){
  896. rv |= fileMetaFlush(kids[i], 1);
  897. fileDecRef(kids[i]);
  898. }
  899. vtMemFree(kids);
  900. return rv;
  901. }
  902. /* assumes metaLock is held */
  903. static int
  904. fileMetaFlush2(File *f, char *oelem)
  905. {
  906. File *fp;
  907. Block *b, *bb;
  908. MetaBlock mb;
  909. MetaEntry me, me2;
  910. int i, n;
  911. u32int boff;
  912. if(!f->dirty)
  913. return 0;
  914. if(oelem == nil)
  915. oelem = f->dir.elem;
  916. //print("fileMetaFlush %s->%s\n", oelem, f->dir.elem);
  917. fp = f->up;
  918. if(!sourceLock(fp->msource, -1))
  919. return -1;
  920. /* can happen if source is clri'ed out from under us */
  921. if(f->boff == NilBlock)
  922. goto Err1;
  923. b = sourceBlock(fp->msource, f->boff, OReadWrite);
  924. if(b == nil)
  925. goto Err1;
  926. if(!mbUnpack(&mb, b->data, fp->msource->dsize))
  927. goto Err;
  928. if(!mbSearch(&mb, oelem, &i, &me))
  929. goto Err;
  930. n = deSize(&f->dir);
  931. if(0)fprint(2, "old size %d new size %d\n", me.size, n);
  932. if(mbResize(&mb, &me, n)){
  933. /* fits in the block */
  934. mbDelete(&mb, i);
  935. if(strcmp(f->dir.elem, oelem) != 0)
  936. mbSearch(&mb, f->dir.elem, &i, &me2);
  937. dePack(&f->dir, &me);
  938. mbInsert(&mb, i, &me);
  939. mbPack(&mb);
  940. blockDirty(b);
  941. blockPut(b);
  942. sourceUnlock(fp->msource);
  943. f->dirty = 0;
  944. return 1;
  945. }
  946. /*
  947. * moving entry to another block
  948. * it is feasible for the fs to crash leaving two copies
  949. * of the directory entry. This is just too much work to
  950. * fix. Given that entries are only allocated in a block that
  951. * is less than PercentageFull, most modifications of meta data
  952. * will fit within the block. i.e. this code should almost
  953. * never be executed.
  954. */
  955. boff = fileMetaAlloc(fp, &f->dir, f->boff+1);
  956. if(boff == NilBlock){
  957. /* mbResize might have modified block */
  958. mbPack(&mb);
  959. blockDirty(b);
  960. goto Err;
  961. }
  962. fprint(2, "fileMetaFlush moving entry from %ud -> %ud\n", f->boff, boff);
  963. f->boff = boff;
  964. /* make sure deletion goes to disk after new entry */
  965. bb = sourceBlock(fp->msource, f->boff, OReadWrite);
  966. mbDelete(&mb, i);
  967. mbPack(&mb);
  968. blockDependency(b, bb, -1, nil, nil);
  969. blockPut(bb);
  970. blockDirty(b);
  971. blockPut(b);
  972. sourceUnlock(fp->msource);
  973. f->dirty = 0;
  974. return 1;
  975. Err:
  976. blockPut(b);
  977. Err1:
  978. sourceUnlock(fp->msource);
  979. return -1;
  980. }
  981. static int
  982. fileMetaRemove(File *f, char *uid)
  983. {
  984. Block *b;
  985. MetaBlock mb;
  986. MetaEntry me;
  987. int i;
  988. File *up;
  989. up = f->up;
  990. fileWAccess(up, uid);
  991. fileMetaLock(f);
  992. sourceLock(up->msource, OReadWrite);
  993. b = sourceBlock(up->msource, f->boff, OReadWrite);
  994. if(b == nil)
  995. goto Err;
  996. if(!mbUnpack(&mb, b->data, up->msource->dsize))
  997. {
  998. fprint(2, "U\n");
  999. goto Err;
  1000. }
  1001. if(!mbSearch(&mb, f->dir.elem, &i, &me))
  1002. {
  1003. fprint(2, "S\n");
  1004. goto Err;
  1005. }
  1006. mbDelete(&mb, i);
  1007. mbPack(&mb);
  1008. sourceUnlock(up->msource);
  1009. blockDirty(b);
  1010. blockPut(b);
  1011. f->removed = 1;
  1012. f->boff = NilBlock;
  1013. f->dirty = 0;
  1014. fileMetaUnlock(f);
  1015. return 1;
  1016. Err:
  1017. sourceUnlock(up->msource);
  1018. blockPut(b);
  1019. fileMetaUnlock(f);
  1020. return 0;
  1021. }
  1022. /* assume file is locked, assume f->msource is locked */
  1023. static int
  1024. fileCheckEmpty(File *f)
  1025. {
  1026. u32int i, n;
  1027. Block *b;
  1028. MetaBlock mb;
  1029. Source *r;
  1030. r = f->msource;
  1031. n = (sourceGetSize(r)+r->dsize-1)/r->dsize;
  1032. for(i=0; i<n; i++){
  1033. b = sourceBlock(r, i, OReadOnly);
  1034. if(b == nil)
  1035. goto Err;
  1036. if(!mbUnpack(&mb, b->data, r->dsize))
  1037. goto Err;
  1038. if(mb.nindex > 0){
  1039. vtSetError(ENotEmpty);
  1040. goto Err;
  1041. }
  1042. blockPut(b);
  1043. }
  1044. return 1;
  1045. Err:
  1046. blockPut(b);
  1047. return 0;
  1048. }
  1049. int
  1050. fileRemove(File *f, char *uid)
  1051. {
  1052. File *ff;
  1053. /* can not remove the root */
  1054. if(fileIsRoot(f)){
  1055. vtSetError(ERoot);
  1056. return 0;
  1057. }
  1058. if(!fileLock(f))
  1059. return 0;
  1060. if(f->source->mode != OReadWrite){
  1061. vtSetError(EReadOnly);
  1062. goto Err1;
  1063. }
  1064. if(!sourceLock2(f->source, f->msource, -1))
  1065. goto Err1;
  1066. if(fileIsDir(f) && !fileCheckEmpty(f))
  1067. goto Err;
  1068. for(ff=f->down; ff; ff=ff->next)
  1069. assert(ff->removed);
  1070. sourceRemove(f->source);
  1071. f->source->file = nil; /* erase back pointer */
  1072. f->source = nil;
  1073. if(f->msource){
  1074. sourceRemove(f->msource);
  1075. f->msource = nil;
  1076. }
  1077. fileUnlock(f);
  1078. if(!fileMetaRemove(f, uid))
  1079. return 0;
  1080. return 1;
  1081. Err:
  1082. sourceUnlock(f->source);
  1083. if(f->msource)
  1084. sourceUnlock(f->msource);
  1085. Err1:
  1086. fileUnlock(f);
  1087. return 0;
  1088. }
  1089. static int
  1090. clri(File *f, char *uid)
  1091. {
  1092. int r;
  1093. if(f == nil)
  1094. return 0;
  1095. if(f->up->source->mode != OReadWrite){
  1096. vtSetError(EReadOnly);
  1097. fileDecRef(f);
  1098. return 0;
  1099. }
  1100. r = fileMetaRemove(f, uid);
  1101. fileDecRef(f);
  1102. return r;
  1103. }
  1104. int
  1105. fileClriPath(Fs *fs, char *path, char *uid)
  1106. {
  1107. return clri(_fileOpen(fs, path, 1), uid);
  1108. }
  1109. int
  1110. fileClri(File *dir, char *elem, char *uid)
  1111. {
  1112. return clri(_fileWalk(dir, elem, 1), uid);
  1113. }
  1114. File *
  1115. fileIncRef(File *vf)
  1116. {
  1117. fileMetaLock(vf);
  1118. assert(vf->ref > 0);
  1119. vf->ref++;
  1120. fileMetaUnlock(vf);
  1121. return vf;
  1122. }
  1123. int
  1124. fileDecRef(File *f)
  1125. {
  1126. File *p, *q, **qq;
  1127. if(f->up == nil){
  1128. /* never linked in */
  1129. assert(f->ref == 1);
  1130. fileFree(f);
  1131. return 1;
  1132. }
  1133. fileMetaLock(f);
  1134. f->ref--;
  1135. if(f->ref > 0){
  1136. fileMetaUnlock(f);
  1137. return 0;
  1138. }
  1139. assert(f->ref == 0);
  1140. assert(f->down == nil);
  1141. fileMetaFlush2(f, nil);
  1142. p = f->up;
  1143. qq = &p->down;
  1144. for(q = *qq; q; q = *qq){
  1145. if(q == f)
  1146. break;
  1147. qq = &q->next;
  1148. }
  1149. assert(q != nil);
  1150. *qq = f->next;
  1151. fileMetaUnlock(f);
  1152. fileFree(f);
  1153. fileDecRef(p);
  1154. return 1;
  1155. }
  1156. File *
  1157. fileGetParent(File *f)
  1158. {
  1159. if(fileIsRoot(f))
  1160. return fileIncRef(f);
  1161. return fileIncRef(f->up);
  1162. }
  1163. DirEntryEnum *
  1164. deeOpen(File *f)
  1165. {
  1166. DirEntryEnum *dee;
  1167. File *p;
  1168. if(!fileIsDir(f)){
  1169. vtSetError(ENotDir);
  1170. fileDecRef(f);
  1171. return nil;
  1172. }
  1173. /* flush out meta data */
  1174. if(!fileLock(f))
  1175. return nil;
  1176. for(p=f->down; p; p=p->next)
  1177. fileMetaFlush2(p, nil);
  1178. fileUnlock(f);
  1179. dee = vtMemAllocZ(sizeof(DirEntryEnum));
  1180. dee->file = fileIncRef(f);
  1181. return dee;
  1182. }
  1183. static int
  1184. dirEntrySize(Source *s, ulong elem, ulong gen, uvlong *size)
  1185. {
  1186. Block *b;
  1187. ulong bn;
  1188. Entry e;
  1189. int epb;
  1190. epb = s->dsize/VtEntrySize;
  1191. bn = elem/epb;
  1192. elem -= bn*epb;
  1193. b = sourceBlock(s, bn, OReadOnly);
  1194. if(b == nil)
  1195. goto Err;
  1196. if(!entryUnpack(&e, b->data, elem))
  1197. goto Err;
  1198. /* hanging entries are returned as zero size */
  1199. if(!(e.flags & VtEntryActive) || e.gen != gen)
  1200. *size = 0;
  1201. else
  1202. *size = e.size;
  1203. blockPut(b);
  1204. return 1;
  1205. Err:
  1206. blockPut(b);
  1207. return 0;
  1208. }
  1209. static int
  1210. deeFill(DirEntryEnum *dee)
  1211. {
  1212. int i, n;
  1213. Source *meta, *source;
  1214. MetaBlock mb;
  1215. MetaEntry me;
  1216. File *f;
  1217. Block *b;
  1218. DirEntry *de;
  1219. /* clean up first */
  1220. for(i=dee->i; i<dee->n; i++)
  1221. deCleanup(dee->buf+i);
  1222. vtMemFree(dee->buf);
  1223. dee->buf = nil;
  1224. dee->i = 0;
  1225. dee->n = 0;
  1226. f = dee->file;
  1227. source = f->source;
  1228. meta = f->msource;
  1229. b = sourceBlock(meta, dee->boff, OReadOnly);
  1230. if(b == nil)
  1231. goto Err;
  1232. if(!mbUnpack(&mb, b->data, meta->dsize))
  1233. goto Err;
  1234. n = mb.nindex;
  1235. dee->buf = vtMemAlloc(n * sizeof(DirEntry));
  1236. for(i=0; i<n; i++){
  1237. de = dee->buf + i;
  1238. meUnpack(&me, &mb, i);
  1239. if(!deUnpack(de, &me))
  1240. goto Err;
  1241. dee->n++;
  1242. if(!(de->mode & ModeDir))
  1243. if(!dirEntrySize(source, de->entry, de->gen, &de->size))
  1244. goto Err;
  1245. }
  1246. dee->boff++;
  1247. blockPut(b);
  1248. return 1;
  1249. Err:
  1250. blockPut(b);
  1251. return 0;
  1252. }
  1253. int
  1254. deeRead(DirEntryEnum *dee, DirEntry *de)
  1255. {
  1256. int ret, didread;
  1257. File *f;
  1258. u32int nb;
  1259. if(dee == nil){
  1260. vtSetError("cannot happen in deeRead");
  1261. return -1;
  1262. }
  1263. f = dee->file;
  1264. if(!fileRLock(f))
  1265. return -1;
  1266. if(!sourceLock2(f->source, f->msource, OReadOnly)){
  1267. fileRUnlock(f);
  1268. return -1;
  1269. }
  1270. nb = (sourceGetSize(f->msource)+f->msource->dsize-1)/f->msource->dsize;
  1271. didread = 0;
  1272. while(dee->i >= dee->n){
  1273. if(dee->boff >= nb){
  1274. ret = 0;
  1275. goto Return;
  1276. }
  1277. didread = 1;
  1278. if(!deeFill(dee)){
  1279. ret = -1;
  1280. goto Return;
  1281. }
  1282. }
  1283. memmove(de, dee->buf + dee->i, sizeof(DirEntry));
  1284. dee->i++;
  1285. ret = 1;
  1286. Return:
  1287. sourceUnlock(f->source);
  1288. sourceUnlock(f->msource);
  1289. fileRUnlock(f);
  1290. if(didread)
  1291. fileRAccess(f);
  1292. return ret;
  1293. }
  1294. void
  1295. deeClose(DirEntryEnum *dee)
  1296. {
  1297. int i;
  1298. if(dee == nil)
  1299. return;
  1300. for(i=dee->i; i<dee->n; i++)
  1301. deCleanup(dee->buf+i);
  1302. vtMemFree(dee->buf);
  1303. fileDecRef(dee->file);
  1304. vtMemFree(dee);
  1305. }
  1306. /*
  1307. * caller must lock f->source and f->msource
  1308. * caller must NOT lock the source and msource
  1309. * referenced by dir.
  1310. */
  1311. static u32int
  1312. fileMetaAlloc(File *f, DirEntry *dir, u32int start)
  1313. {
  1314. u32int nb, bo;
  1315. Block *b, *bb;
  1316. MetaBlock mb;
  1317. int nn;
  1318. uchar *p;
  1319. int i, n, epb;
  1320. MetaEntry me;
  1321. Source *s, *ms;
  1322. s = f->source;
  1323. ms = f->msource;
  1324. n = deSize(dir);
  1325. nb = (sourceGetSize(ms)+ms->dsize-1)/ms->dsize;
  1326. b = nil;
  1327. if(start > nb)
  1328. start = nb;
  1329. for(bo=start; bo<nb; bo++){
  1330. b = sourceBlock(ms, bo, OReadWrite);
  1331. if(b == nil)
  1332. goto Err;
  1333. if(!mbUnpack(&mb, b->data, ms->dsize))
  1334. goto Err;
  1335. nn = (mb.maxsize*FullPercentage/100) - mb.size + mb.free;
  1336. if(n <= nn && mb.nindex < mb.maxindex)
  1337. break;
  1338. blockPut(b);
  1339. b = nil;
  1340. }
  1341. /* add block to meta file */
  1342. if(b == nil){
  1343. b = sourceBlock(ms, bo, OReadWrite);
  1344. if(b == nil)
  1345. goto Err;
  1346. sourceSetSize(ms, (nb+1)*ms->dsize);
  1347. mbInit(&mb, b->data, ms->dsize, ms->dsize/BytesPerEntry);
  1348. }
  1349. p = mbAlloc(&mb, n);
  1350. if(p == nil){
  1351. /* mbAlloc might have changed block */
  1352. mbPack(&mb);
  1353. blockDirty(b);
  1354. vtSetError(EBadMeta);
  1355. goto Err;
  1356. }
  1357. mbSearch(&mb, dir->elem, &i, &me);
  1358. assert(me.p == nil);
  1359. me.p = p;
  1360. me.size = n;
  1361. dePack(dir, &me);
  1362. mbInsert(&mb, i, &me);
  1363. mbPack(&mb);
  1364. /* meta block depends on super block for qid ... */
  1365. bb = cacheLocal(b->c, PartSuper, 0, OReadOnly);
  1366. blockDependency(b, bb, -1, nil, nil);
  1367. blockPut(bb);
  1368. /* ... and one or two dir entries */
  1369. epb = s->dsize/VtEntrySize;
  1370. bb = sourceBlock(s, dir->entry/epb, OReadOnly);
  1371. blockDependency(b, bb, -1, nil, nil);
  1372. blockPut(bb);
  1373. if(dir->mode & ModeDir){
  1374. bb = sourceBlock(s, dir->mentry/epb, OReadOnly);
  1375. blockDependency(b, bb, -1, nil, nil);
  1376. blockPut(bb);
  1377. }
  1378. blockDirty(b);
  1379. blockPut(b);
  1380. return bo;
  1381. Err:
  1382. blockPut(b);
  1383. return NilBlock;
  1384. }
  1385. static int
  1386. chkSource(File *f)
  1387. {
  1388. if(f->partial)
  1389. return 1;
  1390. if(f->source == nil || (f->dir.mode & ModeDir) && f->msource == nil){
  1391. vtSetError(ERemoved);
  1392. return 0;
  1393. }
  1394. return 1;
  1395. }
  1396. static int
  1397. fileRLock(File *f)
  1398. {
  1399. assert(!vtCanLock(f->fs->elk));
  1400. vtRLock(f->lk);
  1401. if(!chkSource(f)){
  1402. fileRUnlock(f);
  1403. return 0;
  1404. }
  1405. return 1;
  1406. }
  1407. static void
  1408. fileRUnlock(File *f)
  1409. {
  1410. vtRUnlock(f->lk);
  1411. }
  1412. static int
  1413. fileLock(File *f)
  1414. {
  1415. assert(!vtCanLock(f->fs->elk));
  1416. vtLock(f->lk);
  1417. if(!chkSource(f)){
  1418. fileUnlock(f);
  1419. return 0;
  1420. }
  1421. return 1;
  1422. }
  1423. static void
  1424. fileUnlock(File *f)
  1425. {
  1426. vtUnlock(f->lk);
  1427. }
  1428. /*
  1429. * f->source and f->msource must NOT be locked.
  1430. * fileMetaFlush locks the fileMeta and then the source (in fileMetaFlush2).
  1431. * We have to respect that ordering.
  1432. */
  1433. static void
  1434. fileMetaLock(File *f)
  1435. {
  1436. if(f->up == nil)
  1437. fprint(2, "f->elem = %s\n", f->dir.elem);
  1438. assert(f->up != nil);
  1439. assert(!vtCanLock(f->fs->elk));
  1440. vtLock(f->up->lk);
  1441. }
  1442. static void
  1443. fileMetaUnlock(File *f)
  1444. {
  1445. vtUnlock(f->up->lk);
  1446. }
  1447. /*
  1448. * f->source and f->msource must NOT be locked.
  1449. * see fileMetaLock.
  1450. */
  1451. static void
  1452. fileRAccess(File* f)
  1453. {
  1454. if(f->mode == OReadOnly || f->fs->noatimeupd)
  1455. return;
  1456. fileMetaLock(f);
  1457. f->dir.atime = time(0L);
  1458. f->dirty = 1;
  1459. fileMetaUnlock(f);
  1460. }
  1461. /*
  1462. * f->source and f->msource must NOT be locked.
  1463. * see fileMetaLock.
  1464. */
  1465. static void
  1466. fileWAccess(File* f, char *mid)
  1467. {
  1468. if(f->mode == OReadOnly)
  1469. return;
  1470. fileMetaLock(f);
  1471. f->dir.atime = f->dir.mtime = time(0L);
  1472. if(strcmp(f->dir.mid, mid) != 0){
  1473. vtMemFree(f->dir.mid);
  1474. f->dir.mid = vtStrDup(mid);
  1475. }
  1476. f->dir.mcount++;
  1477. f->dirty = 1;
  1478. fileMetaUnlock(f);
  1479. /*RSC: let's try this */
  1480. /*presotto - lets not
  1481. if(f->up)
  1482. fileWAccess(f->up, mid);
  1483. */
  1484. }
  1485. static int
  1486. getEntry(Source *r, Entry *e, int checkepoch)
  1487. {
  1488. u32int epoch;
  1489. Block *b;
  1490. if(r == nil){
  1491. memset(&e, 0, sizeof e);
  1492. return 1;
  1493. }
  1494. b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadOnly);
  1495. if(b == nil)
  1496. return 0;
  1497. if(!entryUnpack(e, b->data, r->offset % r->epb)){
  1498. blockPut(b);
  1499. return 0;
  1500. }
  1501. epoch = b->l.epoch;
  1502. blockPut(b);
  1503. if(checkepoch){
  1504. b = cacheGlobal(r->fs->cache, e->score, entryType(e), e->tag, OReadOnly);
  1505. if(b){
  1506. if(b->l.epoch >= epoch)
  1507. fprint(2, "warning: entry %p epoch not older %#.8ux/%d %V/%d in getEntry\n",
  1508. r, b->addr, b->l.epoch, r->score, epoch);
  1509. blockPut(b);
  1510. }
  1511. }
  1512. return 1;
  1513. }
  1514. static int
  1515. setEntry(Source *r, Entry *e)
  1516. {
  1517. Block *b;
  1518. Entry oe;
  1519. b = cacheGlobal(r->fs->cache, r->score, BtDir, r->tag, OReadWrite);
  1520. if(0) fprint(2, "setEntry: b %#ux %d score=%V\n", b->addr, r->offset % r->epb, e->score);
  1521. if(b == nil)
  1522. return 0;
  1523. if(!entryUnpack(&oe, b->data, r->offset % r->epb)){
  1524. blockPut(b);
  1525. return 0;
  1526. }
  1527. e->gen = oe.gen;
  1528. entryPack(e, b->data, r->offset % r->epb);
  1529. /* BUG b should depend on the entry pointer */
  1530. blockDirty(b);
  1531. blockPut(b);
  1532. return 1;
  1533. }
  1534. /* assumes hold elk */
  1535. int
  1536. fileSnapshot(File *dst, File *src, u32int epoch, int doarchive)
  1537. {
  1538. Entry e, ee;
  1539. /* add link to snapshot */
  1540. if(!getEntry(src->source, &e, 1) || !getEntry(src->msource, &ee, 1))
  1541. return 0;
  1542. e.snap = epoch;
  1543. e.archive = doarchive;
  1544. ee.snap = epoch;
  1545. ee.archive = doarchive;
  1546. if(!setEntry(dst->source, &e) || !setEntry(dst->msource, &ee))
  1547. return 0;
  1548. return 1;
  1549. }
  1550. int
  1551. fileGetSources(File *f, Entry *e, Entry *ee)
  1552. {
  1553. if(!getEntry(f->source, e, 0)
  1554. || !getEntry(f->msource, ee, 0))
  1555. return 0;
  1556. return 1;
  1557. }
  1558. /*
  1559. * Walk down to the block(s) containing the Entries
  1560. * for f->source and f->msource, copying as we go.
  1561. */
  1562. int
  1563. fileWalkSources(File *f)
  1564. {
  1565. if(f->mode == OReadOnly){
  1566. fprint(2, "readonly in fileWalkSources\n");
  1567. return 1;
  1568. }
  1569. if(!sourceLock2(f->source, f->msource, OReadWrite)){
  1570. fprint(2, "sourceLock2 failed in fileWalkSources\n");
  1571. return 0;
  1572. }
  1573. sourceUnlock(f->source);
  1574. sourceUnlock(f->msource);
  1575. return 1;
  1576. }
  1577. /*
  1578. * convert File* to full path name in malloced string.
  1579. * this hasn't been as useful as we hoped it would be.
  1580. */
  1581. char *
  1582. fileName(File *f)
  1583. {
  1584. char *name, *pname;
  1585. File *p;
  1586. static char root[] = "/";
  1587. if (f == nil)
  1588. return vtStrDup("/**GOK**");
  1589. p = fileGetParent(f);
  1590. if (p == f)
  1591. name = vtStrDup(root);
  1592. else {
  1593. pname = fileName(p);
  1594. if (strcmp(pname, root) == 0)
  1595. name = smprint("/%s", f->dir.elem);
  1596. else
  1597. name = smprint("%s/%s", pname, f->dir.elem);
  1598. free(pname);
  1599. }
  1600. fileDecRef(p);
  1601. return name;
  1602. }