sub.c 11 KB

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