sub.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  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 "all.h"
  10. Lock wpathlock;
  11. struct {
  12. Lock flock;
  13. File* ffree; /* free file structures */
  14. Wpath* wfree;
  15. } suballoc;
  16. enum{
  17. Finc= 128, /* allocation chunksize for files */
  18. Fmax= 10000, /* maximum file structures to be allocated */
  19. Winc= 8*128, /* allocation chunksize for wpath */
  20. Wmax= 8*10000, /* maximum wpath structures to be allocated */
  21. };
  22. Filsys*
  23. fsstr(char *p)
  24. {
  25. Filsys *fs;
  26. for(fs=filesys; fs->name; fs++)
  27. if(strcmp(fs->name, p) == 0)
  28. return fs;
  29. return 0;
  30. }
  31. void
  32. fileinit(Chan *cp)
  33. {
  34. File *f;
  35. Tlock *t;
  36. loop:
  37. lock(&cp->flock);
  38. f = cp->flist;
  39. if(!f) {
  40. unlock(&cp->flock);
  41. return;
  42. }
  43. cp->flist = f->next;
  44. unlock(&cp->flock);
  45. qlock(f);
  46. if(t = f->tlock) {
  47. t->time = 0;
  48. f->tlock = 0;
  49. }
  50. if(f->open & FREMOV)
  51. doremove(f, 0);
  52. freewp(f->wpath);
  53. f->open = 0;
  54. f->cp = 0;
  55. qunlock(f);
  56. goto loop;
  57. }
  58. /*
  59. * returns a locked file structure
  60. */
  61. File*
  62. filep(Chan *cp, int fid, int flag)
  63. {
  64. File *f, *prev;
  65. if(fid == NOF)
  66. return 0;
  67. loop:
  68. lock(&cp->flock);
  69. for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
  70. if(f->fid != fid)
  71. continue;
  72. if(prev) {
  73. prev->next = f->next;
  74. f->next = cp->flist;
  75. cp->flist = f;
  76. }
  77. goto out;
  78. }
  79. if(flag) {
  80. f = newfp(cp);
  81. if(f) {
  82. f->fid = fid;
  83. goto out;
  84. }
  85. }
  86. else print("cannot find %p.%d (list=%p)\n", cp, fid, cp->flist);
  87. unlock(&cp->flock);
  88. return 0;
  89. out:
  90. unlock(&cp->flock);
  91. qlock(f);
  92. if(f->fid != fid) {
  93. qunlock(f);
  94. goto loop;
  95. }
  96. return f;
  97. }
  98. void
  99. sublockinit(void)
  100. {
  101. lock(&suballoc.flock);
  102. lock(&wpathlock);
  103. conf.nfile = 0;
  104. conf.nwpath = 0;
  105. unlock(&suballoc.flock);
  106. unlock(&wpathlock);
  107. }
  108. /*
  109. * always called with cp->flock locked
  110. */
  111. File*
  112. newfp(Chan *cp)
  113. {
  114. File *f, *e;
  115. retry:
  116. lock(&suballoc.flock);
  117. f = suballoc.ffree;
  118. if(f != nil){
  119. suballoc.ffree = f->list;
  120. unlock(&suballoc.flock);
  121. f->list = 0;
  122. f->cp = cp;
  123. f->next = cp->flist;
  124. f->wpath = 0;
  125. f->tlock = 0;
  126. f->dslot = 0;
  127. f->doffset = 0;
  128. f->uid = 0;
  129. f->cuid = 0;
  130. cp->flist = f;
  131. return f;
  132. }
  133. unlock(&suballoc.flock);
  134. if(conf.nfile > Fmax){
  135. print("%d: out of files\n", cp->chan);
  136. return 0;
  137. }
  138. /*
  139. * create a few new files
  140. */
  141. f = malloc(Finc*sizeof(*f));
  142. memset(f, 0, Finc*sizeof(*f));
  143. lock(&suballoc.flock);
  144. for(e = f+Finc; f < e; f++){
  145. qlock(f);
  146. qunlock(f);
  147. f->list = suballoc.ffree;
  148. suballoc.ffree = f;
  149. }
  150. conf.nfile += Finc;
  151. unlock(&suballoc.flock);
  152. goto retry;
  153. }
  154. void
  155. freefp(File *fp)
  156. {
  157. Chan *cp;
  158. File *f, *prev;
  159. if(!fp || !(cp = fp->cp))
  160. return;
  161. authfree(fp);
  162. lock(&cp->flock);
  163. for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
  164. if(f != fp)
  165. continue;
  166. if(prev)
  167. prev->next = f->next;
  168. else
  169. cp->flist = f->next;
  170. f->cp = 0;
  171. lock(&suballoc.flock);
  172. f->list = suballoc.ffree;
  173. suballoc.ffree = f;
  174. unlock(&suballoc.flock);
  175. break;
  176. }
  177. unlock(&cp->flock);
  178. }
  179. Wpath*
  180. newwp(void)
  181. {
  182. Wpath *w, *e;
  183. retry:
  184. lock(&wpathlock);
  185. w = suballoc.wfree;
  186. if(w != nil){
  187. suballoc.wfree = w->list;
  188. unlock(&wpathlock);
  189. memset(w, 0, sizeof(*w));
  190. w->refs = 1;
  191. w->up = 0;
  192. return w;
  193. }
  194. unlock(&wpathlock);
  195. if(conf.nwpath > Wmax){
  196. print("out of wpaths\n");
  197. return 0;
  198. }
  199. /*
  200. * create a few new wpaths
  201. */
  202. w = malloc(Winc*sizeof(*w));
  203. memset(w, 0, Winc*sizeof(*w));
  204. lock(&wpathlock);
  205. for(e = w+Winc; w < e; w++){
  206. w->list = suballoc.wfree;
  207. suballoc.wfree = w;
  208. }
  209. conf.nwpath += Winc;
  210. unlock(&wpathlock);
  211. goto retry;
  212. }
  213. /*
  214. * increment the references for the whole path
  215. */
  216. Wpath*
  217. getwp(Wpath *w)
  218. {
  219. Wpath *nw;
  220. lock(&wpathlock);
  221. for(nw = w; nw; nw=nw->up)
  222. nw->refs++;
  223. unlock(&wpathlock);
  224. return w;
  225. }
  226. /*
  227. * decrement the reference for each element of the path
  228. */
  229. void
  230. freewp(Wpath *w)
  231. {
  232. lock(&wpathlock);
  233. for(; w; w=w->up){
  234. w->refs--;
  235. if(w->refs == 0){
  236. w->list = suballoc.wfree;
  237. suballoc.wfree = w;
  238. }
  239. }
  240. unlock(&wpathlock);
  241. }
  242. /*
  243. * decrement the reference for just this element
  244. */
  245. void
  246. putwp(Wpath *w)
  247. {
  248. lock(&wpathlock);
  249. w->refs--;
  250. if(w->refs == 0){
  251. w->list = suballoc.wfree;
  252. suballoc.wfree = w;
  253. }
  254. unlock(&wpathlock);
  255. }
  256. int
  257. iaccess(File *f, Dentry *d, int m)
  258. {
  259. if(wstatallow)
  260. return 0;
  261. /*
  262. * owner is next
  263. */
  264. if(f->uid == d->uid)
  265. if((m<<6) & d->mode)
  266. return 0;
  267. /*
  268. * group membership is hard
  269. */
  270. if(ingroup(f->uid, d->gid))
  271. if((m<<3) & d->mode)
  272. return 0;
  273. /*
  274. * other access for everyone except members of group 9999
  275. */
  276. if(m & d->mode){
  277. /*
  278. * walk directories regardless.
  279. * otherwise its impossible to get
  280. * from the root to noworld's directories.
  281. */
  282. if((d->mode & DDIR) && (m == DEXEC))
  283. return 0;
  284. if(!ingroup(f->uid, 9999))
  285. return 0;
  286. }
  287. return 1;
  288. }
  289. Tlock*
  290. tlocked(Iobuf *p, Dentry *d)
  291. {
  292. Tlock *t, *t1;
  293. int32_t qpath, tim;
  294. Device dev;
  295. tim = time(0);
  296. qpath = d->qid.path;
  297. dev = p->dev;
  298. t1 = 0;
  299. for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
  300. if(t->qpath == qpath)
  301. if(t->time >= tim)
  302. if(devcmp(t->dev, dev) == 0)
  303. return 0; /* its locked */
  304. if(!t1 && t->time < tim)
  305. t1 = t; /* steal first lock */
  306. }
  307. if(t1) {
  308. t1->dev = dev;
  309. t1->qpath = qpath;
  310. t1->time = tim + TLOCK;
  311. }
  312. /* botch
  313. * out of tlock nodes simulates
  314. * a locked file
  315. */
  316. return t1;
  317. }
  318. Qid
  319. newqid(Device dev)
  320. {
  321. Iobuf *p;
  322. Superb *sb;
  323. Qid qid;
  324. p = getbuf(dev, superaddr(dev), Bread|Bmod);
  325. if(!p || checktag(p, Tsuper, QPSUPER))
  326. panic("newqid: super block");
  327. sb = (Superb*)p->iobuf;
  328. sb->qidgen++;
  329. qid.path = sb->qidgen;
  330. qid.vers = 0;
  331. qid.type = 0;
  332. putbuf(p);
  333. return qid;
  334. }
  335. /*
  336. * what are legal characters in a name?
  337. * only disallow control characters.
  338. * a) utf avoids control characters.
  339. * b) '/' may not be the separator
  340. */
  341. int
  342. checkname(char *n)
  343. {
  344. int i, c;
  345. for(i=0; i<NAMELEN; i++) {
  346. c = *n & 0xff;
  347. if(c == 0) {
  348. if(i == 0)
  349. return 1;
  350. memset(n, 0, NAMELEN-i);
  351. return 0;
  352. }
  353. if(c <= 040)
  354. return 1;
  355. n++;
  356. }
  357. return 1; /* too long */
  358. }
  359. void
  360. bfree(Device dev, int32_t addr, int d)
  361. {
  362. Iobuf *p;
  363. int32_t a;
  364. int i;
  365. if(!addr)
  366. return;
  367. if(d > 0) {
  368. d--;
  369. p = getbuf(dev, addr, Bread);
  370. if(p) {
  371. for(i=INDPERBUF-1; i>=0; i--) {
  372. a = ((int32_t*)p->iobuf)[i];
  373. bfree(dev, a, d);
  374. }
  375. putbuf(p);
  376. }
  377. }
  378. /*
  379. * stop outstanding i/o
  380. */
  381. p = getbuf(dev, addr, Bprobe);
  382. if(p) {
  383. p->flags &= ~(Bmod|Bimm);
  384. putbuf(p);
  385. }
  386. /*
  387. * dont put written worm
  388. * blocks into free list
  389. */
  390. if(nofree(dev, addr))
  391. return;
  392. p = getbuf(dev, superaddr(dev), Bread|Bmod);
  393. if(!p || checktag(p, Tsuper, QPSUPER))
  394. panic("bfree: super block");
  395. addfree(dev, addr, (Superb*)p->iobuf);
  396. putbuf(p);
  397. }
  398. int32_t
  399. balloc(Device dev, int tag, int32_t qid)
  400. {
  401. Iobuf *bp, *p;
  402. Superb *sb;
  403. int32_t a;
  404. int n;
  405. p = getbuf(dev, superaddr(dev), Bread|Bmod);
  406. if(!p || checktag(p, Tsuper, QPSUPER))
  407. panic("balloc: super block");
  408. sb = (Superb*)p->iobuf;
  409. loop:
  410. n = --sb->fbuf.nfree;
  411. sb->tfree--;
  412. if(n < 0 || n >= FEPERBUF)
  413. panic("balloc: bad freelist");
  414. a = sb->fbuf.free[n];
  415. if(n <= 0) {
  416. if(a == 0) {
  417. sb->tfree = 0;
  418. sb->fbuf.nfree = 1;
  419. if(devgrow(dev, sb))
  420. goto loop;
  421. putbuf(p);
  422. return 0;
  423. }
  424. bp = getbuf(dev, a, Bread);
  425. if(!bp || checktag(bp, Tfree, QPNONE)) {
  426. if(bp)
  427. putbuf(bp);
  428. putbuf(p);
  429. return 0;
  430. }
  431. memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(int32_t));
  432. putbuf(bp);
  433. }
  434. bp = getbuf(dev, a, Bmod);
  435. memset(bp->iobuf, 0, RBUFSIZE);
  436. settag(bp, tag, qid);
  437. if(tag == Tind1 || tag == Tind2 || tag == Tdir)
  438. bp->flags |= Bimm;
  439. putbuf(bp);
  440. putbuf(p);
  441. return a;
  442. }
  443. void
  444. addfree(Device dev, int32_t addr, Superb *sb)
  445. {
  446. int n;
  447. Iobuf *p;
  448. if(addr >= sb->fsize){
  449. print("addfree: bad addr %lx\n", addr);
  450. return;
  451. }
  452. n = sb->fbuf.nfree;
  453. if(n < 0 || n > FEPERBUF)
  454. panic("addfree: bad freelist");
  455. if(n >= FEPERBUF) {
  456. p = getbuf(dev, addr, Bmod);
  457. if(p == 0)
  458. panic("addfree: getbuf");
  459. memmove(p->iobuf, &sb->fbuf, (FEPERBUF+1)*sizeof(int32_t));
  460. settag(p, Tfree, QPNONE);
  461. putbuf(p);
  462. n = 0;
  463. }
  464. sb->fbuf.free[n++] = addr;
  465. sb->fbuf.nfree = n;
  466. sb->tfree++;
  467. if(addr >= sb->fsize)
  468. sb->fsize = addr+1;
  469. }
  470. int
  471. Cfmt(Fmt *f1)
  472. {
  473. Chan *cp;
  474. cp = va_arg(f1->args, Chan*);
  475. return fmtprint(f1, "C%d.%.3d", cp->type, cp->chan);
  476. }
  477. int
  478. Dfmt(Fmt *f1)
  479. {
  480. Device d;
  481. d = va_arg(f1->args, Device);
  482. return fmtprint(f1, "D%d.%d.%d.%d", d.type, d.ctrl, d.unit, d.part);
  483. }
  484. int
  485. Afmt(Fmt *f1)
  486. {
  487. Filta a;
  488. a = va_arg(f1->args, Filta);
  489. return fmtprint(f1, "%6lu %6lu %6lu",
  490. fdf(a.f->filter[0], a.scale*60),
  491. fdf(a.f->filter[1], a.scale*600),
  492. fdf(a.f->filter[2], a.scale*6000));
  493. }
  494. int
  495. Gfmt(Fmt *f1)
  496. {
  497. int t;
  498. t = va_arg(f1->args, int);
  499. if(t >= 0 && t < MAXTAG)
  500. return fmtstrcpy(f1, tagnames[t]);
  501. else
  502. return fmtprint(f1, "<badtag %d>", t);
  503. }
  504. void
  505. formatinit(void)
  506. {
  507. fmtinstall('C', Cfmt); /* print channels */
  508. fmtinstall('D', Dfmt); /* print devices */
  509. fmtinstall('A', Afmt); /* print filters */
  510. fmtinstall('G', Gfmt); /* print tags */
  511. fmtinstall('T', Tfmt); /* print times */
  512. fmtinstall('O', ofcallfmt); /* print old fcalls */
  513. }
  514. int
  515. devcmp(Device d1, Device d2)
  516. {
  517. if(d1.type == d2.type)
  518. if(d1.ctrl == d2.ctrl)
  519. if(d1.unit == d2.unit)
  520. if(d1.part == d2.part)
  521. return 0;
  522. return 1;
  523. }
  524. void
  525. rootream(Device dev, int32_t addr)
  526. {
  527. Iobuf *p;
  528. Dentry *d;
  529. p = getbuf(dev, addr, Bmod|Bimm);
  530. memset(p->iobuf, 0, RBUFSIZE);
  531. settag(p, Tdir, QPROOT);
  532. d = getdir(p, 0);
  533. strcpy(d->name, "/");
  534. d->uid = -1;
  535. d->gid = -1;
  536. d->mode = DALLOC | DDIR |
  537. ((DREAD|DWRITE|DEXEC) << 6) |
  538. ((DREAD|DWRITE|DEXEC) << 3) |
  539. ((DREAD|DWRITE|DEXEC) << 0);
  540. d->qid = QID9P1(QPROOT|QPDIR,0);
  541. d->atime = time(0);
  542. d->mtime = d->atime;
  543. putbuf(p);
  544. }
  545. int
  546. superok(Device dev, int32_t addr, int set)
  547. {
  548. Iobuf *p;
  549. Superb *s;
  550. int ok;
  551. p = getbuf(dev, addr, Bread|Bmod|Bimm);
  552. s = (Superb*)p->iobuf;
  553. ok = s->fsok;
  554. s->fsok = set;
  555. putbuf(p);
  556. return ok;
  557. }
  558. void
  559. superream(Device dev, int32_t addr)
  560. {
  561. Iobuf *p;
  562. Superb *s;
  563. int32_t i;
  564. p = getbuf(dev, addr, Bmod|Bimm);
  565. memset(p->iobuf, 0, RBUFSIZE);
  566. settag(p, Tsuper, QPSUPER);
  567. s = (Superb*)p->iobuf;
  568. s->fstart = 1;
  569. s->fsize = devsize(dev);
  570. s->fbuf.nfree = 1;
  571. s->qidgen = 10;
  572. for(i=s->fsize-1; i>=addr+2; i--)
  573. addfree(dev, i, s);
  574. putbuf(p);
  575. }
  576. /*
  577. * returns 1 if n is prime
  578. * used for adjusting lengths
  579. * of hashing things.
  580. * there is no need to be clever
  581. */
  582. int
  583. prime(int32_t n)
  584. {
  585. int32_t i;
  586. if((n%2) == 0)
  587. return 0;
  588. for(i=3;; i+=2) {
  589. if((n%i) == 0)
  590. return 0;
  591. if(i*i >= n)
  592. return 1;
  593. }
  594. }
  595. void
  596. hexdump(void *a, int n)
  597. {
  598. char s1[30], s2[4];
  599. uint8_t *p;
  600. int i;
  601. p = a;
  602. s1[0] = 0;
  603. for(i=0; i<n; i++) {
  604. sprint(s2, " %.2x", p[i]);
  605. strcat(s1, s2);
  606. if((i&7) == 7) {
  607. print("%s\n", s1);
  608. s1[0] = 0;
  609. }
  610. }
  611. if(s1[0])
  612. print("%s\n", s1);
  613. }
  614. int32_t
  615. qidpathgen(Device *dev)
  616. {
  617. Iobuf *p;
  618. Superb *sb;
  619. int32_t path;
  620. p = getbuf(*dev, superaddr((*dev)), Bread|Bmod);
  621. if(!p || checktag(p, Tsuper, QPSUPER))
  622. panic("newqid: super block");
  623. sb = (Superb*)p->iobuf;
  624. sb->qidgen++;
  625. path = sb->qidgen;
  626. putbuf(p);
  627. return path;
  628. }