7 File* ffree; /* free file structures */
12 Finc= 128, /* allocation chunksize for files */
13 Fmax= 10000, /* maximum file structures to be allocated */
15 Winc= 8*128, /* allocation chunksize for wpath */
16 Wmax= 8*10000, /* maximum wpath structures to be allocated */
25 for(fs=filesys; fs->name; fs++)
26 if(strcmp(fs->name, p) == 0)
63 * returns a locked file structure
66 filep(Chan *cp, int fid, int flag)
75 for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
92 else print("cannot find %p.%ud (list=%p)\n", cp, fid, cp->flist);
109 lock(&suballoc.flock);
113 unlock(&suballoc.flock);
118 * always called with cp->flock locked
126 lock(&suballoc.flock);
129 suballoc.ffree = f->list;
130 unlock(&suballoc.flock);
143 unlock(&suballoc.flock);
145 if(conf.nfile > Fmax){
146 print("%d: out of files\n", cp->chan);
151 * create a few new files
153 f = malloc(Finc*sizeof(*f));
154 memset(f, 0, Finc*sizeof(*f));
155 lock(&suballoc.flock);
156 for(e = f+Finc; f < e; f++){
159 f->list = suballoc.ffree;
163 unlock(&suballoc.flock);
173 if(!fp || !(cp = fp->cp))
177 for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
181 prev->next = f->next;
185 lock(&suballoc.flock);
186 f->list = suballoc.ffree;
188 unlock(&suballoc.flock);
203 suballoc.wfree = w->list;
205 memset(w, 0, sizeof(*w));
212 if(conf.nwpath > Wmax){
213 print("out of wpaths\n");
218 * create a few new wpaths
220 w = malloc(Winc*sizeof(*w));
221 memset(w, 0, Winc*sizeof(*w));
223 for(e = w+Winc; w < e; w++){
224 w->list = suballoc.wfree;
233 * increment the references for the whole path
241 for(nw = w; nw; nw=nw->up)
248 * decrement the reference for each element of the path
257 w->list = suballoc.wfree;
265 * decrement the reference for just this element
273 w->list = suballoc.wfree;
280 iaccess(File *f, Dentry *d, int m)
292 * group membership is hard
294 if(ingroup(f->uid, d->gid))
298 * other access for everyone except members of group 9999
302 * walk directories regardless.
303 * otherwise its impossible to get
304 * from the root to noworld's directories.
306 if((d->mode & DDIR) && (m == DEXEC))
308 if(!ingroup(f->uid, 9999))
315 tlocked(Iobuf *p, Dentry *d)
325 for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
326 if(t->qpath == qpath)
328 if(devcmp(t->dev, dev) == 0)
329 return 0; /* its locked */
330 if(!t1 && t->time < tim)
331 t1 = t; /* steal first lock */
336 t1->time = tim + TLOCK;
339 * out of tlock nodes simulates
352 p = getbuf(dev, superaddr(dev), Bread|Bmod);
353 if(!p || checktag(p, Tsuper, QPSUPER))
354 panic("newqid: super block");
355 sb = (Superb*)p->iobuf;
357 qid.path = sb->qidgen;
365 * what are legal characters in a name?
366 * only disallow control characters.
367 * a) utf avoids control characters.
368 * b) '/' may not be the separator
375 for(i=0; i<NAMELEN; i++) {
380 memset(n, 0, NAMELEN-i);
387 return 1; /* too long */
391 bfree(Device dev, long addr, int d)
401 p = getbuf(dev, addr, Bread);
403 for(i=INDPERBUF-1; i>=0; i--) {
404 a = ((long*)p->iobuf)[i];
411 * stop outstanding i/o
413 p = getbuf(dev, addr, Bprobe);
415 p->flags &= ~(Bmod|Bimm);
419 * dont put written worm
420 * blocks into free list
422 if(nofree(dev, addr))
424 p = getbuf(dev, superaddr(dev), Bread|Bmod);
425 if(!p || checktag(p, Tsuper, QPSUPER))
426 panic("bfree: super block");
427 addfree(dev, addr, (Superb*)p->iobuf);
432 balloc(Device dev, int tag, long qid)
439 p = getbuf(dev, superaddr(dev), Bread|Bmod);
440 if(!p || checktag(p, Tsuper, QPSUPER))
441 panic("balloc: super block");
442 sb = (Superb*)p->iobuf;
445 n = --sb->fbuf.nfree;
447 if(n < 0 || n >= FEPERBUF)
448 panic("balloc: bad freelist");
449 a = sb->fbuf.free[n];
459 bp = getbuf(dev, a, Bread);
460 if(!bp || checktag(bp, Tfree, QPNONE)) {
466 memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(long));
469 bp = getbuf(dev, a, Bmod);
470 memset(bp->iobuf, 0, RBUFSIZE);
471 settag(bp, tag, qid);
472 if(tag == Tind1 || tag == Tind2 || tag == Tdir)
480 addfree(Device dev, long addr, Superb *sb)
485 if(addr >= sb->fsize){
486 print("addfree: bad addr %lux\n", addr);
490 if(n < 0 || n > FEPERBUF)
491 panic("addfree: bad freelist");
493 p = getbuf(dev, addr, Bmod);
495 panic("addfree: getbuf");
496 memmove(p->iobuf, &sb->fbuf, (FEPERBUF+1)*sizeof(long));
497 settag(p, Tfree, QPNONE);
501 sb->fbuf.free[n++] = addr;
504 if(addr >= sb->fsize)
513 cp = va_arg(f1->args, Chan*);
514 return fmtprint(f1, "C%d.%.3d", cp->type, cp->chan);
522 d = va_arg(f1->args, Device);
523 return fmtprint(f1, "D%d.%d.%d.%d", d.type, d.ctrl, d.unit, d.part);
531 a = va_arg(f1->args, Filta);
532 return fmtprint(f1, "%6lud %6lud %6lud",
533 fdf(a.f->filter[0], a.scale*60),
534 fdf(a.f->filter[1], a.scale*600),
535 fdf(a.f->filter[2], a.scale*6000));
543 t = va_arg(f1->args, int);
544 if(t >= 0 && t < MAXTAG)
545 return fmtstrcpy(f1, tagnames[t]);
547 return fmtprint(f1, "<badtag %d>", t);
554 fmtinstall('C', Cfmt); /* print channels */
555 fmtinstall('D', Dfmt); /* print devices */
556 fmtinstall('A', Afmt); /* print filters */
557 fmtinstall('G', Gfmt); /* print tags */
558 fmtinstall('T', Tfmt); /* print times */
559 fmtinstall('O', ofcallfmt); /* print old fcalls */
562 devcmp(Device d1, Device d2)
565 if(d1.type == d2.type)
566 if(d1.ctrl == d2.ctrl)
567 if(d1.unit == d2.unit)
568 if(d1.part == d2.part)
574 rootream(Device dev, long addr)
579 p = getbuf(dev, addr, Bmod|Bimm);
580 memset(p->iobuf, 0, RBUFSIZE);
581 settag(p, Tdir, QPROOT);
583 strcpy(d->name, "/");
586 d->mode = DALLOC | DDIR |
587 ((DREAD|DWRITE|DEXEC) << 6) |
588 ((DREAD|DWRITE|DEXEC) << 3) |
589 ((DREAD|DWRITE|DEXEC) << 0);
590 d->qid = QID9P1(QPROOT|QPDIR,0);
597 superok(Device dev, long addr, int set)
603 p = getbuf(dev, addr, Bread|Bmod|Bimm);
604 s = (Superb*)p->iobuf;
612 superream(Device dev, long addr)
618 p = getbuf(dev, addr, Bmod|Bimm);
619 memset(p->iobuf, 0, RBUFSIZE);
620 settag(p, Tsuper, QPSUPER);
622 s = (Superb*)p->iobuf;
624 s->fsize = devsize(dev);
627 for(i=s->fsize-1; i>=addr+2; i--)
633 * returns 1 if n is prime
634 * used for adjusting lengths
636 * there is no need to be clever
654 hexdump(void *a, int n)
663 sprint(s2, " %.2ux", p[i]);
675 qidpathgen(Device *dev)
681 p = getbuf(*dev, superaddr((*dev)), Bread|Bmod);
682 if(!p || checktag(p, Tsuper, QPSUPER))
683 panic("newqid: super block");
684 sb = (Superb*)p->iobuf;