123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "all.h"
- Lock wpathlock;
- struct {
- Lock flock;
- File* ffree; /* free file structures */
- Wpath* wfree;
- } suballoc;
- enum{
- Finc= 128, /* allocation chunksize for files */
- Fmax= 10000, /* maximum file structures to be allocated */
- Winc= 8*128, /* allocation chunksize for wpath */
- Wmax= 8*10000, /* maximum wpath structures to be allocated */
- };
- Filsys*
- fsstr(char *p)
- {
- Filsys *fs;
- for(fs=filesys; fs->name; fs++)
- if(strcmp(fs->name, p) == 0)
- return fs;
- return 0;
- }
- void
- fileinit(Chan *cp)
- {
- File *f;
- Tlock *t;
- loop:
- lock(&cp->flock);
- f = cp->flist;
- if(!f) {
- unlock(&cp->flock);
- return;
- }
- cp->flist = f->next;
- unlock(&cp->flock);
- qlock(f);
- if(t = f->tlock) {
- t->time = 0;
- f->tlock = 0;
- }
- if(f->open & FREMOV)
- doremove(f, 0);
- freewp(f->wpath);
- f->open = 0;
- f->cp = 0;
- qunlock(f);
- goto loop;
- }
- /*
- * returns a locked file structure
- */
- File*
- filep(Chan *cp, int fid, int flag)
- {
- File *f, *prev;
- if(fid == NOF)
- return 0;
- loop:
- lock(&cp->flock);
- for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
- if(f->fid != fid)
- continue;
- if(prev) {
- prev->next = f->next;
- f->next = cp->flist;
- cp->flist = f;
- }
- goto out;
- }
- if(flag) {
- f = newfp(cp);
- if(f) {
- f->fid = fid;
- goto out;
- }
- }
- else print("cannot find %p.%d (list=%p)\n", cp, fid, cp->flist);
- unlock(&cp->flock);
- return 0;
- out:
- unlock(&cp->flock);
- qlock(f);
- if(f->fid != fid) {
- qunlock(f);
- goto loop;
- }
- return f;
- }
- void
- sublockinit(void)
- {
- lock(&suballoc.flock);
- lock(&wpathlock);
- conf.nfile = 0;
- conf.nwpath = 0;
- unlock(&suballoc.flock);
- unlock(&wpathlock);
- }
- /*
- * always called with cp->flock locked
- */
- File*
- newfp(Chan *cp)
- {
- File *f, *e;
- retry:
- lock(&suballoc.flock);
- f = suballoc.ffree;
- if(f != nil){
- suballoc.ffree = f->list;
- unlock(&suballoc.flock);
- f->list = 0;
- f->cp = cp;
- f->next = cp->flist;
- f->wpath = 0;
- f->tlock = 0;
- f->dslot = 0;
- f->doffset = 0;
- f->uid = 0;
- f->cuid = 0;
- cp->flist = f;
- return f;
- }
- unlock(&suballoc.flock);
- if(conf.nfile > Fmax){
- print("%d: out of files\n", cp->chan);
- return 0;
- }
- /*
- * create a few new files
- */
- f = malloc(Finc*sizeof(*f));
- memset(f, 0, Finc*sizeof(*f));
- lock(&suballoc.flock);
- for(e = f+Finc; f < e; f++){
- qlock(f);
- qunlock(f);
- f->list = suballoc.ffree;
- suballoc.ffree = f;
- }
- conf.nfile += Finc;
- unlock(&suballoc.flock);
- goto retry;
- }
- void
- freefp(File *fp)
- {
- Chan *cp;
- File *f, *prev;
- if(!fp || !(cp = fp->cp))
- return;
- authfree(fp);
- lock(&cp->flock);
- for(prev=0,f=cp->flist; f; prev=f,f=f->next) {
- if(f != fp)
- continue;
- if(prev)
- prev->next = f->next;
- else
- cp->flist = f->next;
- f->cp = 0;
- lock(&suballoc.flock);
- f->list = suballoc.ffree;
- suballoc.ffree = f;
- unlock(&suballoc.flock);
- break;
- }
- unlock(&cp->flock);
- }
- Wpath*
- newwp(void)
- {
- Wpath *w, *e;
- retry:
- lock(&wpathlock);
- w = suballoc.wfree;
- if(w != nil){
- suballoc.wfree = w->list;
- unlock(&wpathlock);
- memset(w, 0, sizeof(*w));
- w->refs = 1;
- w->up = 0;
- return w;
- }
- unlock(&wpathlock);
- if(conf.nwpath > Wmax){
- print("out of wpaths\n");
- return 0;
- }
- /*
- * create a few new wpaths
- */
- w = malloc(Winc*sizeof(*w));
- memset(w, 0, Winc*sizeof(*w));
- lock(&wpathlock);
- for(e = w+Winc; w < e; w++){
- w->list = suballoc.wfree;
- suballoc.wfree = w;
- }
- conf.nwpath += Winc;
- unlock(&wpathlock);
- goto retry;
- }
- /*
- * increment the references for the whole path
- */
- Wpath*
- getwp(Wpath *w)
- {
- Wpath *nw;
- lock(&wpathlock);
- for(nw = w; nw; nw=nw->up)
- nw->refs++;
- unlock(&wpathlock);
- return w;
- }
- /*
- * decrement the reference for each element of the path
- */
- void
- freewp(Wpath *w)
- {
- lock(&wpathlock);
- for(; w; w=w->up){
- w->refs--;
- if(w->refs == 0){
- w->list = suballoc.wfree;
- suballoc.wfree = w;
- }
- }
- unlock(&wpathlock);
- }
- /*
- * decrement the reference for just this element
- */
- void
- putwp(Wpath *w)
- {
- lock(&wpathlock);
- w->refs--;
- if(w->refs == 0){
- w->list = suballoc.wfree;
- suballoc.wfree = w;
- }
- unlock(&wpathlock);
- }
- int
- iaccess(File *f, Dentry *d, int m)
- {
- if(wstatallow)
- return 0;
- /*
- * owner is next
- */
- if(f->uid == d->uid)
- if((m<<6) & d->mode)
- return 0;
- /*
- * group membership is hard
- */
- if(ingroup(f->uid, d->gid))
- if((m<<3) & d->mode)
- return 0;
- /*
- * other access for everyone except members of group 9999
- */
- if(m & d->mode){
- /*
- * walk directories regardless.
- * otherwise its impossible to get
- * from the root to noworld's directories.
- */
- if((d->mode & DDIR) && (m == DEXEC))
- return 0;
- if(!ingroup(f->uid, 9999))
- return 0;
- }
- return 1;
- }
- Tlock*
- tlocked(Iobuf *p, Dentry *d)
- {
- Tlock *t, *t1;
- int32_t qpath, tim;
- Device dev;
- tim = time(0);
- qpath = d->qid.path;
- dev = p->dev;
- t1 = 0;
- for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
- if(t->qpath == qpath)
- if(t->time >= tim)
- if(devcmp(t->dev, dev) == 0)
- return 0; /* its locked */
- if(!t1 && t->time < tim)
- t1 = t; /* steal first lock */
- }
- if(t1) {
- t1->dev = dev;
- t1->qpath = qpath;
- t1->time = tim + TLOCK;
- }
- /* botch
- * out of tlock nodes simulates
- * a locked file
- */
- return t1;
- }
- Qid
- newqid(Device dev)
- {
- Iobuf *p;
- Superb *sb;
- Qid qid;
- p = getbuf(dev, superaddr(dev), Bread|Bmod);
- if(!p || checktag(p, Tsuper, QPSUPER))
- panic("newqid: super block");
- sb = (Superb*)p->iobuf;
- sb->qidgen++;
- qid.path = sb->qidgen;
- qid.vers = 0;
- qid.type = 0;
- putbuf(p);
- return qid;
- }
- /*
- * what are legal characters in a name?
- * only disallow control characters.
- * a) utf avoids control characters.
- * b) '/' may not be the separator
- */
- int
- checkname(char *n)
- {
- int i, c;
- for(i=0; i<NAMELEN; i++) {
- c = *n & 0xff;
- if(c == 0) {
- if(i == 0)
- return 1;
- memset(n, 0, NAMELEN-i);
- return 0;
- }
- if(c <= 040)
- return 1;
- n++;
- }
- return 1; /* too long */
- }
- void
- bfree(Device dev, int32_t addr, int d)
- {
- Iobuf *p;
- int32_t a;
- int i;
- if(!addr)
- return;
- if(d > 0) {
- d--;
- p = getbuf(dev, addr, Bread);
- if(p) {
- for(i=INDPERBUF-1; i>=0; i--) {
- a = ((int32_t*)p->iobuf)[i];
- bfree(dev, a, d);
- }
- putbuf(p);
- }
- }
- /*
- * stop outstanding i/o
- */
- p = getbuf(dev, addr, Bprobe);
- if(p) {
- p->flags &= ~(Bmod|Bimm);
- putbuf(p);
- }
- /*
- * dont put written worm
- * blocks into free list
- */
- if(nofree(dev, addr))
- return;
- p = getbuf(dev, superaddr(dev), Bread|Bmod);
- if(!p || checktag(p, Tsuper, QPSUPER))
- panic("bfree: super block");
- addfree(dev, addr, (Superb*)p->iobuf);
- putbuf(p);
- }
- int32_t
- balloc(Device dev, int tag, int32_t qid)
- {
- Iobuf *bp, *p;
- Superb *sb;
- int32_t a;
- int n;
- p = getbuf(dev, superaddr(dev), Bread|Bmod);
- if(!p || checktag(p, Tsuper, QPSUPER))
- panic("balloc: super block");
- sb = (Superb*)p->iobuf;
- loop:
- n = --sb->fbuf.nfree;
- sb->tfree--;
- if(n < 0 || n >= FEPERBUF)
- panic("balloc: bad freelist");
- a = sb->fbuf.free[n];
- if(n <= 0) {
- if(a == 0) {
- sb->tfree = 0;
- sb->fbuf.nfree = 1;
- if(devgrow(dev, sb))
- goto loop;
- putbuf(p);
- return 0;
- }
- bp = getbuf(dev, a, Bread);
- if(!bp || checktag(bp, Tfree, QPNONE)) {
- if(bp)
- putbuf(bp);
- putbuf(p);
- return 0;
- }
- memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(int32_t));
- putbuf(bp);
- }
- bp = getbuf(dev, a, Bmod);
- memset(bp->iobuf, 0, RBUFSIZE);
- settag(bp, tag, qid);
- if(tag == Tind1 || tag == Tind2 || tag == Tdir)
- bp->flags |= Bimm;
- putbuf(bp);
- putbuf(p);
- return a;
- }
- void
- addfree(Device dev, int32_t addr, Superb *sb)
- {
- int n;
- Iobuf *p;
- if(addr >= sb->fsize){
- print("addfree: bad addr %lx\n", addr);
- return;
- }
- n = sb->fbuf.nfree;
- if(n < 0 || n > FEPERBUF)
- panic("addfree: bad freelist");
- if(n >= FEPERBUF) {
- p = getbuf(dev, addr, Bmod);
- if(p == 0)
- panic("addfree: getbuf");
- memmove(p->iobuf, &sb->fbuf, (FEPERBUF+1)*sizeof(int32_t));
- settag(p, Tfree, QPNONE);
- putbuf(p);
- n = 0;
- }
- sb->fbuf.free[n++] = addr;
- sb->fbuf.nfree = n;
- sb->tfree++;
- if(addr >= sb->fsize)
- sb->fsize = addr+1;
- }
- int
- Cfmt(Fmt *f1)
- {
- Chan *cp;
- cp = va_arg(f1->args, Chan*);
- return fmtprint(f1, "C%d.%.3d", cp->type, cp->chan);
- }
- int
- Dfmt(Fmt *f1)
- {
- Device d;
- d = va_arg(f1->args, Device);
- return fmtprint(f1, "D%d.%d.%d.%d", d.type, d.ctrl, d.unit, d.part);
- }
- int
- Afmt(Fmt *f1)
- {
- Filta a;
- a = va_arg(f1->args, Filta);
- return fmtprint(f1, "%6lu %6lu %6lu",
- fdf(a.f->filter[0], a.scale*60),
- fdf(a.f->filter[1], a.scale*600),
- fdf(a.f->filter[2], a.scale*6000));
- }
- int
- Gfmt(Fmt *f1)
- {
- int t;
- t = va_arg(f1->args, int);
- if(t >= 0 && t < MAXTAG)
- return fmtstrcpy(f1, tagnames[t]);
- else
- return fmtprint(f1, "<badtag %d>", t);
- }
- void
- formatinit(void)
- {
- fmtinstall('C', Cfmt); /* print channels */
- fmtinstall('D', Dfmt); /* print devices */
- fmtinstall('A', Afmt); /* print filters */
- fmtinstall('G', Gfmt); /* print tags */
- fmtinstall('T', Tfmt); /* print times */
- fmtinstall('O', ofcallfmt); /* print old fcalls */
- }
- int
- devcmp(Device d1, Device d2)
- {
- if(d1.type == d2.type)
- if(d1.ctrl == d2.ctrl)
- if(d1.unit == d2.unit)
- if(d1.part == d2.part)
- return 0;
- return 1;
- }
- void
- rootream(Device dev, int32_t addr)
- {
- Iobuf *p;
- Dentry *d;
- p = getbuf(dev, addr, Bmod|Bimm);
- memset(p->iobuf, 0, RBUFSIZE);
- settag(p, Tdir, QPROOT);
- d = getdir(p, 0);
- strcpy(d->name, "/");
- d->uid = -1;
- d->gid = -1;
- d->mode = DALLOC | DDIR |
- ((DREAD|DWRITE|DEXEC) << 6) |
- ((DREAD|DWRITE|DEXEC) << 3) |
- ((DREAD|DWRITE|DEXEC) << 0);
- d->qid = QID9P1(QPROOT|QPDIR,0);
- d->atime = time(0);
- d->mtime = d->atime;
- putbuf(p);
- }
- int
- superok(Device dev, int32_t addr, int set)
- {
- Iobuf *p;
- Superb *s;
- int ok;
- p = getbuf(dev, addr, Bread|Bmod|Bimm);
- s = (Superb*)p->iobuf;
- ok = s->fsok;
- s->fsok = set;
- putbuf(p);
- return ok;
- }
- void
- superream(Device dev, int32_t addr)
- {
- Iobuf *p;
- Superb *s;
- int32_t i;
- p = getbuf(dev, addr, Bmod|Bimm);
- memset(p->iobuf, 0, RBUFSIZE);
- settag(p, Tsuper, QPSUPER);
- s = (Superb*)p->iobuf;
- s->fstart = 1;
- s->fsize = devsize(dev);
- s->fbuf.nfree = 1;
- s->qidgen = 10;
- for(i=s->fsize-1; i>=addr+2; i--)
- addfree(dev, i, s);
- putbuf(p);
- }
- /*
- * returns 1 if n is prime
- * used for adjusting lengths
- * of hashing things.
- * there is no need to be clever
- */
- int
- prime(int32_t n)
- {
- int32_t i;
- if((n%2) == 0)
- return 0;
- for(i=3;; i+=2) {
- if((n%i) == 0)
- return 0;
- if(i*i >= n)
- return 1;
- }
- }
- void
- hexdump(void *a, int n)
- {
- char s1[30], s2[4];
- uint8_t *p;
- int i;
- p = a;
- s1[0] = 0;
- for(i=0; i<n; i++) {
- sprint(s2, " %.2x", p[i]);
- strcat(s1, s2);
- if((i&7) == 7) {
- print("%s\n", s1);
- s1[0] = 0;
- }
- }
- if(s1[0])
- print("%s\n", s1);
- }
- int32_t
- qidpathgen(Device *dev)
- {
- Iobuf *p;
- Superb *sb;
- int32_t path;
- p = getbuf(*dev, superaddr((*dev)), Bread|Bmod);
- if(!p || checktag(p, Tsuper, QPSUPER))
- panic("newqid: super block");
- sb = (Superb*)p->iobuf;
- sb->qidgen++;
- path = sb->qidgen;
- putbuf(p);
- return path;
- }
|