entry.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include <thread.h>
  6. #include <9p.h>
  7. #include "flashfs.h"
  8. static int nextfnum;
  9. static Intmap* map;
  10. static Dir dirproto;
  11. static char user[] = "flash";
  12. Entry *root;
  13. ulong used;
  14. ulong limit;
  15. ulong maxwrite;
  16. enum
  17. {
  18. debug = 0,
  19. };
  20. static int
  21. fnum(void)
  22. {
  23. return ++nextfnum;
  24. }
  25. static void
  26. maxfnum(int n)
  27. {
  28. if(n > nextfnum)
  29. nextfnum = n;
  30. }
  31. static int
  32. hash(char *s)
  33. {
  34. int c, d, h;
  35. h = 0;
  36. while((c = *s++) != '\0') {
  37. d = c;
  38. c ^= c << 6;
  39. h += (c << 11) ^ (c >> 1);
  40. h ^= (d << 14) + (d << 7) + (d << 4) + d;
  41. }
  42. if(h < 0)
  43. return ~h;
  44. return h;
  45. }
  46. static void
  47. dirinit(Entry *e)
  48. {
  49. Entry **t;
  50. e->size = 0;
  51. t = emalloc9p(HSIZE * sizeof(Entry*));
  52. memset(t, 0, HSIZE * sizeof(Entry*));
  53. e->htab = t;
  54. e->files = nil;
  55. e->readers = nil;
  56. }
  57. static void
  58. fileinit(Entry *e)
  59. {
  60. e->size = 0;
  61. e->gen[0].head = nil;
  62. e->gen[0].tail = nil;
  63. e->gen[1].head = nil;
  64. e->gen[1].tail = nil;
  65. }
  66. static void
  67. elfree(Extent *x)
  68. {
  69. Extent *t;
  70. while(x != nil) {
  71. t = x->next;
  72. used -= x->size;
  73. free(x);
  74. x = t;
  75. }
  76. }
  77. static void
  78. extfree(Entry *e)
  79. {
  80. elfree(e->gen[0].head);
  81. elfree(e->gen[1].head);
  82. }
  83. static void
  84. efree(Entry *e)
  85. {
  86. if(debug)
  87. fprint(2, "free %s\n", e->name);
  88. if(e->mode & DMDIR)
  89. free(e->htab);
  90. else
  91. extfree(e);
  92. free(e->name);
  93. free(e);
  94. }
  95. void
  96. einit(void)
  97. {
  98. Entry *e;
  99. e = emalloc9p(sizeof(Entry));
  100. e->ref = 1;
  101. e->parent = nil;
  102. dirinit(e);
  103. e->name = estrdup9p("");
  104. e->fnum = 0;
  105. e->mode = DMDIR | 0775;
  106. e->mnum = 0;
  107. e->mtime = 0;
  108. root = e;
  109. map = allocmap(nil);
  110. }
  111. static void
  112. dumptree(Entry *e, int n)
  113. {
  114. Entry *l;
  115. if(debug)
  116. fprint(2, "%d %s %d\n", n, e->name, e->ref);
  117. if(e->mode & DMDIR) {
  118. n++;
  119. for(l = e->files; l != nil; l = l->fnext)
  120. dumptree(l, n);
  121. }
  122. }
  123. void
  124. edump(void)
  125. {
  126. if(debug)
  127. dumptree(root, 0);
  128. }
  129. Entry *
  130. elookup(ulong key)
  131. {
  132. if(key == 0)
  133. return root;
  134. maxfnum(key);
  135. return lookupkey(map, key);
  136. }
  137. Extent *
  138. esum(Entry *e, int sect, ulong addr, int *more)
  139. {
  140. Exts *x;
  141. Extent *t, *u;
  142. x = &e->gen[eparity];
  143. t = x->tail;
  144. if(t == nil || t->sect != sect || t->addr != addr)
  145. return nil;
  146. u = t->prev;
  147. if(u != nil) {
  148. u->next = nil;
  149. *more = 1;
  150. }
  151. else {
  152. x->head = nil;
  153. *more = 0;
  154. }
  155. x->tail = u;
  156. x = &e->gen[eparity^1];
  157. u = x->head;
  158. t->next = u;
  159. x->head = t;
  160. if(u == nil)
  161. x->tail = t;
  162. else
  163. u->prev = t;
  164. return t;
  165. }
  166. void
  167. edestroy(Entry *e)
  168. {
  169. e->ref--;
  170. if(e->ref == 0)
  171. efree(e);
  172. }
  173. Entry *
  174. ecreate(Entry *d, char *name, ulong n, ulong mode, ulong mtime, char **err)
  175. {
  176. int h;
  177. Entry *e, *f;
  178. h = hash(name) & HMASK;
  179. for(e = d->htab[h]; e != nil; e = e->hnext) {
  180. if(strcmp(e->name, name) == 0) {
  181. *err = Eexists;
  182. return nil;
  183. }
  184. }
  185. e = emalloc9p(sizeof(Entry));
  186. e->ref = 1;
  187. e->parent = d;
  188. d->ref++;
  189. f = d->htab[h];
  190. e->hnext = f;
  191. e->hprev = nil;
  192. if(f != nil)
  193. f->hprev = e;
  194. d->htab[h] = e;
  195. f = d->files;
  196. e->fnext = f;
  197. e->fprev = nil;
  198. if(f != nil)
  199. f->fprev = e;
  200. d->files = e;
  201. d->ref--;
  202. e->ref++;
  203. e->name = estrdup9p(name);
  204. if(n == 0)
  205. n = fnum();
  206. else
  207. maxfnum(n);
  208. insertkey(map, n, e);
  209. e->fnum = n;
  210. e->mode = mode & d->mode;
  211. e->mnum = 0;
  212. e->mtime = mtime;
  213. if(e->mode & DMDIR)
  214. dirinit(e);
  215. else
  216. fileinit(e);
  217. d->mtime = mtime;
  218. return e;
  219. }
  220. void
  221. etrunc(Entry *e, ulong n, ulong mtime)
  222. {
  223. extfree(e);
  224. deletekey(map, e->fnum);
  225. if(n == 0)
  226. n = fnum();
  227. else
  228. maxfnum(n);
  229. e->fnum = n;
  230. e->mnum = 0;
  231. e->mtime = mtime;
  232. insertkey(map, n, e);
  233. fileinit(e);
  234. e->parent->mtime = mtime;
  235. }
  236. char *
  237. eremove(Entry *e)
  238. {
  239. Dirr *r;
  240. Entry *d, *n, *p;
  241. d = e->parent;
  242. if(d == nil)
  243. return Eperm;
  244. if((e->mode & DMDIR) != 0 && e->files != nil)
  245. return Edirnotempty;
  246. p = e->hprev;
  247. n = e->hnext;
  248. if(n != nil)
  249. n->hprev = p;
  250. if(p != nil)
  251. p->hnext = n;
  252. else
  253. d->htab[hash(e->name) & HMASK] = n;
  254. for(r = d->readers; r != nil; r = r->next) {
  255. if(r->cur == e)
  256. r->cur = e->fnext;
  257. }
  258. p = e->fprev;
  259. n = e->fnext;
  260. if(n != nil)
  261. n->fprev = p;
  262. if(p != nil)
  263. p->fnext = n;
  264. else
  265. d->files = n;
  266. e->parent = nil;
  267. d->ref--;
  268. deletekey(map, e->fnum);
  269. edestroy(e);
  270. return nil;
  271. }
  272. Entry *
  273. ewalk(Entry *d, char *name, char **err)
  274. {
  275. Entry *e;
  276. if((d->mode & DMDIR) == 0) {
  277. *err = Enotdir;
  278. return nil;
  279. }
  280. if(strcmp(name, "..") == 0) {
  281. e = d->parent;
  282. if(e == nil)
  283. return d;
  284. edestroy(d);
  285. e->ref++;
  286. return e;
  287. }
  288. for(e = d->htab[hash(name) & HMASK]; e != nil; e = e->hnext) {
  289. if(strcmp(e->name, name) == 0) {
  290. d->ref--;
  291. e->ref++;
  292. return e;
  293. }
  294. }
  295. *err = Enonexist;
  296. return nil;
  297. }
  298. static void
  299. eread0(Extent *e, Extent *x, uchar *a, ulong n, ulong off)
  300. {
  301. uchar *a0, *a1;
  302. ulong n0, n1, o0, o1, d, z;
  303. for(;;) {
  304. while(e != nil) {
  305. if(off < e->off + e->size && off + n > e->off) {
  306. if(off >= e->off) {
  307. d = off - e->off;
  308. z = e->size - d;
  309. if(n <= z) {
  310. readdata(e->sect, a, n, e->addr + d);
  311. return;
  312. }
  313. readdata(e->sect, a, z, e->addr + d);
  314. a += z;
  315. n -= z;
  316. off += z;
  317. }
  318. else {
  319. a0 = a;
  320. n0 = e->off - off;
  321. o0 = off;
  322. a += n0;
  323. n -= n0;
  324. off += n0;
  325. z = e->size;
  326. if(n <= z) {
  327. readdata(e->sect, a, n, e->addr);
  328. a = a0;
  329. n = n0;
  330. off = o0;
  331. }
  332. else {
  333. readdata(e->sect, a, z, e->addr);
  334. a1 = a + z;
  335. n1 = n - z;
  336. o1 = off + z;
  337. if(n0 < n1) {
  338. eread0(e->next, x, a0, n0, o0);
  339. a = a1;
  340. n = n1;
  341. off = o1;
  342. }
  343. else {
  344. eread0(e->next, x, a1, n1, o1);
  345. a = a0;
  346. n = n0;
  347. off = o0;
  348. }
  349. }
  350. }
  351. }
  352. e = e->next;
  353. }
  354. if(x == nil)
  355. break;
  356. e = x;
  357. x = nil;
  358. }
  359. memset(a, 0, n);
  360. }
  361. ulong
  362. eread(Entry *e, int parity, void *a, ulong n, ulong off)
  363. {
  364. if(n + off >= e->size)
  365. n = e->size - off;
  366. if(n <= 0)
  367. return 0;
  368. eread0(e->gen[parity].head, e->gen[parity^1].head, a, n, off);
  369. return n;
  370. }
  371. void
  372. ewrite(Entry *e, Extent *x, int parity, ulong mtime)
  373. {
  374. ulong z;
  375. Extent *t;
  376. t = e->gen[parity].head;
  377. x->next = t;
  378. x->prev = nil;
  379. e->gen[parity].head = x;
  380. if(t == nil)
  381. e->gen[parity].tail = x;
  382. else
  383. t->prev = x;
  384. if(mtime != 0)
  385. e->mtime = mtime;
  386. used += x->size;
  387. z = x->off + x->size;
  388. if(z > e->size)
  389. e->size = z;
  390. }
  391. ulong
  392. echmod(Entry *e, ulong mode, ulong mnum)
  393. {
  394. if(mnum != 0)
  395. e->mnum = mnum;
  396. else
  397. e->mnum++;
  398. e->mode &= ~0777;
  399. e->mode |= mode;
  400. return e->mnum;
  401. }
  402. Qid
  403. eqid(Entry *e)
  404. {
  405. Qid qid;
  406. if(e->mode & DMDIR)
  407. qid.type = QTDIR;
  408. else
  409. qid.type = 0;
  410. qid.path = e->fnum;
  411. return qid;
  412. }
  413. void
  414. estat(Entry *e, Dir *d, int alloc)
  415. {
  416. d->type = 'z';
  417. d->dev = 0;
  418. if(alloc) {
  419. d->uid = estrdup9p(user);
  420. d->gid = estrdup9p(user);
  421. d->muid = estrdup9p(user);
  422. d->name = estrdup9p(e->name);
  423. }
  424. else {
  425. d->uid = user;
  426. d->gid = user;
  427. d->muid = user;
  428. d->name = e->name;
  429. }
  430. d->mode = e->mode;
  431. d->length = e->size;
  432. d->atime = e->mtime;
  433. d->mtime = e->mtime;
  434. d->qid = eqid(e);
  435. }
  436. Dirr *
  437. ediropen(Entry *e)
  438. {
  439. Dirr *d, *t;
  440. d = emalloc9p(sizeof(Dirr));
  441. d->dir = e;
  442. d->cur = e->files;
  443. t = e->readers;
  444. d->next = t;
  445. d->prev = nil;
  446. if(t != nil)
  447. t->prev = d;
  448. e->readers = d;
  449. e->ref++;
  450. return d;
  451. }
  452. int
  453. edirread(Dirr *r, char *a, long n)
  454. {
  455. Dir d;
  456. Entry *e;
  457. int m, x;
  458. m = 0;
  459. for(e = r->cur; e != nil; e = e->fnext) {
  460. estat(e, &d, 0);
  461. x = convD2M(&d, (uchar *)a, n);
  462. if(x <= BIT16SZ)
  463. break;
  464. a += x;
  465. n -= x;
  466. m += x;
  467. }
  468. r->cur = e;
  469. return m;
  470. }
  471. void
  472. edirclose(Dirr *d)
  473. {
  474. Entry *e;
  475. Dirr *p, *n;
  476. e = d->dir;
  477. p = d->prev;
  478. n = d->next;
  479. if(n != nil)
  480. n->prev = p;
  481. if(p != nil)
  482. p->next = n;
  483. else
  484. e->readers = n;
  485. edestroy(e);
  486. free(d);
  487. }
  488. static Renum R;
  489. static void
  490. xrenum(Extent *x)
  491. {
  492. while(x != nil) {
  493. if(x->sect == R.old)
  494. x->sect = R.new;
  495. x = x->next;
  496. }
  497. }
  498. static void
  499. renum(Entry *e)
  500. {
  501. if(e->mode & DMDIR) {
  502. for(e = e->files; e != nil; e = e->fnext)
  503. renum(e);
  504. }
  505. else {
  506. xrenum(e->gen[0].head);
  507. xrenum(e->gen[1].head);
  508. }
  509. }
  510. void
  511. erenum(Renum *r)
  512. {
  513. R = *r;
  514. renum(root);
  515. }