18ccd4a63SDavid du Colombier /*
28ccd4a63SDavid du Colombier * exportfs - Export a plan 9 name space across a network
38ccd4a63SDavid du Colombier */
48ccd4a63SDavid du Colombier #include <u.h>
58ccd4a63SDavid du Colombier #include <libc.h>
68ccd4a63SDavid du Colombier #include <fcall.h>
78ccd4a63SDavid du Colombier #include <libsec.h>
88ccd4a63SDavid du Colombier #include "drawterm.h"
98ccd4a63SDavid du Colombier #define Extern
108ccd4a63SDavid du Colombier #include "exportfs.h"
118ccd4a63SDavid du Colombier
128ccd4a63SDavid du Colombier /* #define QIDPATH ((1LL<<48)-1) */
138ccd4a63SDavid du Colombier #define QIDPATH ((((vlong)1)<<48)-1)
148ccd4a63SDavid du Colombier vlong newqid = 0;
158ccd4a63SDavid du Colombier
168ccd4a63SDavid du Colombier void (*fcalls[256])(Fsrpc*);
178ccd4a63SDavid du Colombier
188ccd4a63SDavid du Colombier /* accounting and debugging counters */
198ccd4a63SDavid du Colombier int filecnt;
208ccd4a63SDavid du Colombier int freecnt;
218ccd4a63SDavid du Colombier int qidcnt;
228ccd4a63SDavid du Colombier int qfreecnt;
238ccd4a63SDavid du Colombier int ncollision;
248ccd4a63SDavid du Colombier int netfd;
258ccd4a63SDavid du Colombier
268ccd4a63SDavid du Colombier int
exportfs(int fd,int msgsz)278ccd4a63SDavid du Colombier exportfs(int fd, int msgsz)
288ccd4a63SDavid du Colombier {
298ccd4a63SDavid du Colombier char buf[ERRMAX], ebuf[ERRMAX];
308ccd4a63SDavid du Colombier Fsrpc *r;
318ccd4a63SDavid du Colombier int i, n;
328ccd4a63SDavid du Colombier
338ccd4a63SDavid du Colombier fcalls[Tversion] = Xversion;
348ccd4a63SDavid du Colombier fcalls[Tauth] = Xauth;
358ccd4a63SDavid du Colombier fcalls[Tflush] = Xflush;
368ccd4a63SDavid du Colombier fcalls[Tattach] = Xattach;
378ccd4a63SDavid du Colombier fcalls[Twalk] = Xwalk;
388ccd4a63SDavid du Colombier fcalls[Topen] = slave;
398ccd4a63SDavid du Colombier fcalls[Tcreate] = Xcreate;
408ccd4a63SDavid du Colombier fcalls[Tclunk] = Xclunk;
418ccd4a63SDavid du Colombier fcalls[Tread] = slave;
428ccd4a63SDavid du Colombier fcalls[Twrite] = slave;
438ccd4a63SDavid du Colombier fcalls[Tremove] = Xremove;
448ccd4a63SDavid du Colombier fcalls[Tstat] = Xstat;
458ccd4a63SDavid du Colombier fcalls[Twstat] = Xwstat;
468ccd4a63SDavid du Colombier
478ccd4a63SDavid du Colombier srvfd = -1;
488ccd4a63SDavid du Colombier netfd = fd;
498ccd4a63SDavid du Colombier //dbg = 1;
508ccd4a63SDavid du Colombier
518ccd4a63SDavid du Colombier strcpy(buf, "this is buf");
528ccd4a63SDavid du Colombier strcpy(ebuf, "this is ebuf");
538ccd4a63SDavid du Colombier DEBUG(DFD, "exportfs: started\n");
548ccd4a63SDavid du Colombier
558ccd4a63SDavid du Colombier // rfork(RFNOTEG);
568ccd4a63SDavid du Colombier
578ccd4a63SDavid du Colombier messagesize = msgsz;
588ccd4a63SDavid du Colombier if(messagesize == 0){
598ccd4a63SDavid du Colombier messagesize = iounit(netfd);
608ccd4a63SDavid du Colombier if(messagesize == 0)
61*58da3067SDavid du Colombier messagesize = 8*8192+IOHDRSZ;
628ccd4a63SDavid du Colombier }
638ccd4a63SDavid du Colombier
648ccd4a63SDavid du Colombier Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs);
658ccd4a63SDavid du Colombier // for(i=0; i<Nr_workbufs; i++)
668ccd4a63SDavid du Colombier // Workq[i].buf = emallocz(messagesize);
678ccd4a63SDavid du Colombier fhash = emallocz(sizeof(Fid*)*FHASHSIZE);
688ccd4a63SDavid du Colombier
698ccd4a63SDavid du Colombier fmtinstall('F', fcallfmt);
708ccd4a63SDavid du Colombier
718ccd4a63SDavid du Colombier initroot();
728ccd4a63SDavid du Colombier
738ccd4a63SDavid du Colombier DEBUG(DFD, "exportfs: %s\n", buf);
748ccd4a63SDavid du Colombier
758ccd4a63SDavid du Colombier /*
768ccd4a63SDavid du Colombier * Start serving file requests from the network
778ccd4a63SDavid du Colombier */
788ccd4a63SDavid du Colombier for(;;) {
798ccd4a63SDavid du Colombier r = getsbuf();
808ccd4a63SDavid du Colombier if(r == 0)
818ccd4a63SDavid du Colombier fatal("Out of service buffers");
828ccd4a63SDavid du Colombier
838ccd4a63SDavid du Colombier DEBUG(DFD, "read9p...");
848ccd4a63SDavid du Colombier n = read9pmsg(netfd, r->buf, messagesize);
858ccd4a63SDavid du Colombier if(n <= 0)
868ccd4a63SDavid du Colombier fatal("eof: n=%d %r", n);
878ccd4a63SDavid du Colombier
888ccd4a63SDavid du Colombier if(convM2S(r->buf, n, &r->work) == 0){
898ccd4a63SDavid du Colombier iprint("convM2S %d byte message\n", n);
908ccd4a63SDavid du Colombier for(i=0; i<n; i++){
918ccd4a63SDavid du Colombier iprint(" %.2ux", r->buf[i]);
928ccd4a63SDavid du Colombier if(i%16 == 15)
938ccd4a63SDavid du Colombier iprint("\n");
948ccd4a63SDavid du Colombier }
958ccd4a63SDavid du Colombier if(i%16)
968ccd4a63SDavid du Colombier iprint("\n");
978ccd4a63SDavid du Colombier fatal("convM2S format error");
988ccd4a63SDavid du Colombier }
998ccd4a63SDavid du Colombier
1008ccd4a63SDavid du Colombier if(0) iprint("<- %F\n", &r->work);
1018ccd4a63SDavid du Colombier DEBUG(DFD, "%F\n", &r->work);
1028ccd4a63SDavid du Colombier (fcalls[r->work.type])(r);
1038ccd4a63SDavid du Colombier }
1048ccd4a63SDavid du Colombier }
1058ccd4a63SDavid du Colombier
1068ccd4a63SDavid du Colombier void
reply(Fcall * r,Fcall * t,char * err)1078ccd4a63SDavid du Colombier reply(Fcall *r, Fcall *t, char *err)
1088ccd4a63SDavid du Colombier {
1098ccd4a63SDavid du Colombier uchar *data;
1108ccd4a63SDavid du Colombier int m, n;
1118ccd4a63SDavid du Colombier
1128ccd4a63SDavid du Colombier t->tag = r->tag;
1138ccd4a63SDavid du Colombier t->fid = r->fid;
1148ccd4a63SDavid du Colombier if(err) {
1158ccd4a63SDavid du Colombier t->type = Rerror;
1168ccd4a63SDavid du Colombier t->ename = err;
1178ccd4a63SDavid du Colombier }
1188ccd4a63SDavid du Colombier else
1198ccd4a63SDavid du Colombier t->type = r->type + 1;
1208ccd4a63SDavid du Colombier
1218ccd4a63SDavid du Colombier if(0) iprint("-> %F\n", t);
1228ccd4a63SDavid du Colombier DEBUG(DFD, "\t%F\n", t);
1238ccd4a63SDavid du Colombier
1248ccd4a63SDavid du Colombier data = malloc(messagesize); /* not mallocz; no need to clear */
1258ccd4a63SDavid du Colombier if(data == nil)
1268ccd4a63SDavid du Colombier fatal(Enomem);
1278ccd4a63SDavid du Colombier n = convS2M(t, data, messagesize);
1288ccd4a63SDavid du Colombier if((m=write(netfd, data, n))!=n){
1298ccd4a63SDavid du Colombier iprint("wrote %d got %d (%r)\n", n, m);
1308ccd4a63SDavid du Colombier fatal("write");
1318ccd4a63SDavid du Colombier }
1328ccd4a63SDavid du Colombier free(data);
1338ccd4a63SDavid du Colombier }
1348ccd4a63SDavid du Colombier
1358ccd4a63SDavid du Colombier Fid *
getfid(int nr)1368ccd4a63SDavid du Colombier getfid(int nr)
1378ccd4a63SDavid du Colombier {
1388ccd4a63SDavid du Colombier Fid *f;
1398ccd4a63SDavid du Colombier
1408ccd4a63SDavid du Colombier for(f = fidhash(nr); f; f = f->next)
1418ccd4a63SDavid du Colombier if(f->nr == nr)
1428ccd4a63SDavid du Colombier return f;
1438ccd4a63SDavid du Colombier
1448ccd4a63SDavid du Colombier return 0;
1458ccd4a63SDavid du Colombier }
1468ccd4a63SDavid du Colombier
1478ccd4a63SDavid du Colombier int
freefid(int nr)1488ccd4a63SDavid du Colombier freefid(int nr)
1498ccd4a63SDavid du Colombier {
1508ccd4a63SDavid du Colombier Fid *f, **l;
1518ccd4a63SDavid du Colombier char buf[128];
1528ccd4a63SDavid du Colombier
1538ccd4a63SDavid du Colombier l = &fidhash(nr);
1548ccd4a63SDavid du Colombier for(f = *l; f; f = f->next) {
1558ccd4a63SDavid du Colombier if(f->nr == nr) {
1568ccd4a63SDavid du Colombier if(f->mid) {
1578ccd4a63SDavid du Colombier sprint(buf, "/mnt/exportfs/%d", f->mid);
1588ccd4a63SDavid du Colombier unmount(0, buf);
1598ccd4a63SDavid du Colombier psmap[f->mid] = 0;
1608ccd4a63SDavid du Colombier }
1618ccd4a63SDavid du Colombier if(f->f) {
1628ccd4a63SDavid du Colombier freefile(f->f);
1638ccd4a63SDavid du Colombier f->f = nil;
1648ccd4a63SDavid du Colombier }
1658ccd4a63SDavid du Colombier *l = f->next;
1668ccd4a63SDavid du Colombier f->next = fidfree;
1678ccd4a63SDavid du Colombier fidfree = f;
1688ccd4a63SDavid du Colombier return 1;
1698ccd4a63SDavid du Colombier }
1708ccd4a63SDavid du Colombier l = &f->next;
1718ccd4a63SDavid du Colombier }
1728ccd4a63SDavid du Colombier
1738ccd4a63SDavid du Colombier return 0;
1748ccd4a63SDavid du Colombier }
1758ccd4a63SDavid du Colombier
1768ccd4a63SDavid du Colombier Fid *
newfid(int nr)1778ccd4a63SDavid du Colombier newfid(int nr)
1788ccd4a63SDavid du Colombier {
1798ccd4a63SDavid du Colombier Fid *new, **l;
1808ccd4a63SDavid du Colombier int i;
1818ccd4a63SDavid du Colombier
1828ccd4a63SDavid du Colombier l = &fidhash(nr);
1838ccd4a63SDavid du Colombier for(new = *l; new; new = new->next)
1848ccd4a63SDavid du Colombier if(new->nr == nr)
1858ccd4a63SDavid du Colombier return 0;
1868ccd4a63SDavid du Colombier
1878ccd4a63SDavid du Colombier if(fidfree == 0) {
1888ccd4a63SDavid du Colombier fidfree = emallocz(sizeof(Fid) * Fidchunk);
1898ccd4a63SDavid du Colombier
1908ccd4a63SDavid du Colombier for(i = 0; i < Fidchunk-1; i++)
1918ccd4a63SDavid du Colombier fidfree[i].next = &fidfree[i+1];
1928ccd4a63SDavid du Colombier
1938ccd4a63SDavid du Colombier fidfree[Fidchunk-1].next = 0;
1948ccd4a63SDavid du Colombier }
1958ccd4a63SDavid du Colombier
1968ccd4a63SDavid du Colombier new = fidfree;
1978ccd4a63SDavid du Colombier fidfree = new->next;
1988ccd4a63SDavid du Colombier
1998ccd4a63SDavid du Colombier memset(new, 0, sizeof(Fid));
2008ccd4a63SDavid du Colombier new->next = *l;
2018ccd4a63SDavid du Colombier *l = new;
2028ccd4a63SDavid du Colombier new->nr = nr;
2038ccd4a63SDavid du Colombier new->fid = -1;
2048ccd4a63SDavid du Colombier new->mid = 0;
2058ccd4a63SDavid du Colombier
2068ccd4a63SDavid du Colombier return new;
2078ccd4a63SDavid du Colombier }
2088ccd4a63SDavid du Colombier
2098ccd4a63SDavid du Colombier Fsrpc *
getsbuf(void)2108ccd4a63SDavid du Colombier getsbuf(void)
2118ccd4a63SDavid du Colombier {
2128ccd4a63SDavid du Colombier static int ap;
2138ccd4a63SDavid du Colombier int look, rounds;
2148ccd4a63SDavid du Colombier Fsrpc *wb;
2158ccd4a63SDavid du Colombier int small_instead_of_fast = 1;
2168ccd4a63SDavid du Colombier
2178ccd4a63SDavid du Colombier if(small_instead_of_fast)
2188ccd4a63SDavid du Colombier ap = 0; /* so we always start looking at the beginning and reuse buffers */
2198ccd4a63SDavid du Colombier
2208ccd4a63SDavid du Colombier for(rounds = 0; rounds < 10; rounds++) {
2218ccd4a63SDavid du Colombier for(look = 0; look < Nr_workbufs; look++) {
2228ccd4a63SDavid du Colombier if(++ap == Nr_workbufs)
2238ccd4a63SDavid du Colombier ap = 0;
2248ccd4a63SDavid du Colombier if(Workq[ap].busy == 0)
2258ccd4a63SDavid du Colombier break;
2268ccd4a63SDavid du Colombier }
2278ccd4a63SDavid du Colombier
2288ccd4a63SDavid du Colombier if(look == Nr_workbufs){
2298ccd4a63SDavid du Colombier sleep(10 * rounds);
2308ccd4a63SDavid du Colombier continue;
2318ccd4a63SDavid du Colombier }
2328ccd4a63SDavid du Colombier
2338ccd4a63SDavid du Colombier wb = &Workq[ap];
2348ccd4a63SDavid du Colombier wb->pid = 0;
2358ccd4a63SDavid du Colombier wb->canint = 0;
2368ccd4a63SDavid du Colombier wb->flushtag = NOTAG;
2378ccd4a63SDavid du Colombier wb->busy = 1;
2388ccd4a63SDavid du Colombier if(wb->buf == nil) /* allocate buffers dynamically to keep size down */
2398ccd4a63SDavid du Colombier wb->buf = emallocz(messagesize);
2408ccd4a63SDavid du Colombier return wb;
2418ccd4a63SDavid du Colombier }
2428ccd4a63SDavid du Colombier fatal("No more work buffers");
2438ccd4a63SDavid du Colombier return nil;
2448ccd4a63SDavid du Colombier }
2458ccd4a63SDavid du Colombier
2468ccd4a63SDavid du Colombier void
freefile(File * f)2478ccd4a63SDavid du Colombier freefile(File *f)
2488ccd4a63SDavid du Colombier {
2498ccd4a63SDavid du Colombier File *parent, *child;
2508ccd4a63SDavid du Colombier
2518ccd4a63SDavid du Colombier Loop:
2528ccd4a63SDavid du Colombier f->ref--;
2538ccd4a63SDavid du Colombier if(f->ref > 0)
2548ccd4a63SDavid du Colombier return;
2558ccd4a63SDavid du Colombier freecnt++;
2568ccd4a63SDavid du Colombier if(f->ref < 0) abort();
2578ccd4a63SDavid du Colombier DEBUG(DFD, "free %s\n", f->name);
2588ccd4a63SDavid du Colombier /* delete from parent */
2598ccd4a63SDavid du Colombier parent = f->parent;
2608ccd4a63SDavid du Colombier if(parent->child == f)
2618ccd4a63SDavid du Colombier parent->child = f->childlist;
2628ccd4a63SDavid du Colombier else{
2638ccd4a63SDavid du Colombier for(child=parent->child; child->childlist!=f; child=child->childlist)
2648ccd4a63SDavid du Colombier if(child->childlist == nil)
2658ccd4a63SDavid du Colombier fatal("bad child list");
2668ccd4a63SDavid du Colombier child->childlist = f->childlist;
2678ccd4a63SDavid du Colombier }
2688ccd4a63SDavid du Colombier freeqid(f->qidt);
2698ccd4a63SDavid du Colombier free(f->name);
2708ccd4a63SDavid du Colombier f->name = nil;
2718ccd4a63SDavid du Colombier free(f);
2728ccd4a63SDavid du Colombier f = parent;
2738ccd4a63SDavid du Colombier if(f != nil)
2748ccd4a63SDavid du Colombier goto Loop;
2758ccd4a63SDavid du Colombier }
2768ccd4a63SDavid du Colombier
2778ccd4a63SDavid du Colombier File *
file(File * parent,char * name)2788ccd4a63SDavid du Colombier file(File *parent, char *name)
2798ccd4a63SDavid du Colombier {
2808ccd4a63SDavid du Colombier Dir *dir;
2818ccd4a63SDavid du Colombier char *path;
2828ccd4a63SDavid du Colombier File *f;
2838ccd4a63SDavid du Colombier
2848ccd4a63SDavid du Colombier DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name);
2858ccd4a63SDavid du Colombier
2868ccd4a63SDavid du Colombier path = makepath(parent, name);
2878ccd4a63SDavid du Colombier dir = dirstat(path);
2888ccd4a63SDavid du Colombier free(path);
2898ccd4a63SDavid du Colombier if(dir == nil)
2908ccd4a63SDavid du Colombier return nil;
2918ccd4a63SDavid du Colombier
2928ccd4a63SDavid du Colombier for(f = parent->child; f; f = f->childlist)
2938ccd4a63SDavid du Colombier if(strcmp(name, f->name) == 0)
2948ccd4a63SDavid du Colombier break;
2958ccd4a63SDavid du Colombier
2968ccd4a63SDavid du Colombier if(f == nil){
2978ccd4a63SDavid du Colombier f = emallocz(sizeof(File));
2988ccd4a63SDavid du Colombier f->name = estrdup(name);
2998ccd4a63SDavid du Colombier
3008ccd4a63SDavid du Colombier f->parent = parent;
3018ccd4a63SDavid du Colombier f->childlist = parent->child;
3028ccd4a63SDavid du Colombier parent->child = f;
3038ccd4a63SDavid du Colombier parent->ref++;
3048ccd4a63SDavid du Colombier f->ref = 0;
3058ccd4a63SDavid du Colombier filecnt++;
3068ccd4a63SDavid du Colombier }
3078ccd4a63SDavid du Colombier f->ref++;
3088ccd4a63SDavid du Colombier f->qid.type = dir->qid.type;
3098ccd4a63SDavid du Colombier f->qid.vers = dir->qid.vers;
3108ccd4a63SDavid du Colombier f->qidt = uniqueqid(dir);
3118ccd4a63SDavid du Colombier f->qid.path = f->qidt->uniqpath;
3128ccd4a63SDavid du Colombier
3138ccd4a63SDavid du Colombier f->inval = 0;
3148ccd4a63SDavid du Colombier
3158ccd4a63SDavid du Colombier free(dir);
3168ccd4a63SDavid du Colombier
3178ccd4a63SDavid du Colombier return f;
3188ccd4a63SDavid du Colombier }
3198ccd4a63SDavid du Colombier
3208ccd4a63SDavid du Colombier void
initroot(void)3218ccd4a63SDavid du Colombier initroot(void)
3228ccd4a63SDavid du Colombier {
3238ccd4a63SDavid du Colombier Dir *dir;
3248ccd4a63SDavid du Colombier
3258ccd4a63SDavid du Colombier root = emallocz(sizeof(File));
3268ccd4a63SDavid du Colombier root->name = estrdup(".");
3278ccd4a63SDavid du Colombier
3288ccd4a63SDavid du Colombier dir = dirstat(root->name);
3298ccd4a63SDavid du Colombier if(dir == nil)
3308ccd4a63SDavid du Colombier fatal("root stat");
3318ccd4a63SDavid du Colombier
3328ccd4a63SDavid du Colombier root->ref = 1;
3338ccd4a63SDavid du Colombier root->qid.vers = dir->qid.vers;
3348ccd4a63SDavid du Colombier root->qidt = uniqueqid(dir);
3358ccd4a63SDavid du Colombier root->qid.path = root->qidt->uniqpath;
3368ccd4a63SDavid du Colombier root->qid.type = QTDIR;
3378ccd4a63SDavid du Colombier free(dir);
3388ccd4a63SDavid du Colombier
3398ccd4a63SDavid du Colombier psmpt = emallocz(sizeof(File));
3408ccd4a63SDavid du Colombier psmpt->name = estrdup("/");
3418ccd4a63SDavid du Colombier
3428ccd4a63SDavid du Colombier dir = dirstat(psmpt->name);
3438ccd4a63SDavid du Colombier if(dir == nil)
3448ccd4a63SDavid du Colombier return;
3458ccd4a63SDavid du Colombier
3468ccd4a63SDavid du Colombier psmpt->ref = 1;
3478ccd4a63SDavid du Colombier psmpt->qid.vers = dir->qid.vers;
3488ccd4a63SDavid du Colombier psmpt->qidt = uniqueqid(dir);
3498ccd4a63SDavid du Colombier psmpt->qid.path = psmpt->qidt->uniqpath;
3508ccd4a63SDavid du Colombier free(dir);
3518ccd4a63SDavid du Colombier
3528ccd4a63SDavid du Colombier psmpt = file(psmpt, "mnt");
3538ccd4a63SDavid du Colombier if(psmpt == 0)
3548ccd4a63SDavid du Colombier return;
3558ccd4a63SDavid du Colombier psmpt = file(psmpt, "exportfs");
3568ccd4a63SDavid du Colombier }
3578ccd4a63SDavid du Colombier
3588ccd4a63SDavid du Colombier char*
makepath(File * p,char * name)3598ccd4a63SDavid du Colombier makepath(File *p, char *name)
3608ccd4a63SDavid du Colombier {
3618ccd4a63SDavid du Colombier int i, n;
3628ccd4a63SDavid du Colombier char *c, *s, *path, *seg[256];
3638ccd4a63SDavid du Colombier
3648ccd4a63SDavid du Colombier seg[0] = name;
3658ccd4a63SDavid du Colombier n = strlen(name)+2;
3668ccd4a63SDavid du Colombier for(i = 1; i < 256 && p; i++, p = p->parent){
3678ccd4a63SDavid du Colombier seg[i] = p->name;
3688ccd4a63SDavid du Colombier n += strlen(p->name)+1;
3698ccd4a63SDavid du Colombier }
3708ccd4a63SDavid du Colombier path = malloc(n);
3718ccd4a63SDavid du Colombier if(path == nil)
3728ccd4a63SDavid du Colombier fatal("out of memory");
3738ccd4a63SDavid du Colombier s = path;
3748ccd4a63SDavid du Colombier
3758ccd4a63SDavid du Colombier while(i--) {
3768ccd4a63SDavid du Colombier for(c = seg[i]; *c; c++)
3778ccd4a63SDavid du Colombier *s++ = *c;
3788ccd4a63SDavid du Colombier *s++ = '/';
3798ccd4a63SDavid du Colombier }
3808ccd4a63SDavid du Colombier while(s[-1] == '/')
3818ccd4a63SDavid du Colombier s--;
3828ccd4a63SDavid du Colombier *s = '\0';
3838ccd4a63SDavid du Colombier
3848ccd4a63SDavid du Colombier return path;
3858ccd4a63SDavid du Colombier }
3868ccd4a63SDavid du Colombier
3878ccd4a63SDavid du Colombier int
qidhash(vlong path)3888ccd4a63SDavid du Colombier qidhash(vlong path)
3898ccd4a63SDavid du Colombier {
3908ccd4a63SDavid du Colombier int h, n;
3918ccd4a63SDavid du Colombier
3928ccd4a63SDavid du Colombier h = 0;
3938ccd4a63SDavid du Colombier for(n=0; n<64; n+=Nqidbits){
3948ccd4a63SDavid du Colombier h ^= path;
3958ccd4a63SDavid du Colombier path >>= Nqidbits;
3968ccd4a63SDavid du Colombier }
3978ccd4a63SDavid du Colombier return h & (Nqidtab-1);
3988ccd4a63SDavid du Colombier }
3998ccd4a63SDavid du Colombier
4008ccd4a63SDavid du Colombier void
freeqid(Qidtab * q)4018ccd4a63SDavid du Colombier freeqid(Qidtab *q)
4028ccd4a63SDavid du Colombier {
4038ccd4a63SDavid du Colombier ulong h;
4048ccd4a63SDavid du Colombier Qidtab *l;
4058ccd4a63SDavid du Colombier
4068ccd4a63SDavid du Colombier q->ref--;
4078ccd4a63SDavid du Colombier if(q->ref > 0)
4088ccd4a63SDavid du Colombier return;
4098ccd4a63SDavid du Colombier qfreecnt++;
4108ccd4a63SDavid du Colombier h = qidhash(q->path);
4118ccd4a63SDavid du Colombier if(qidtab[h] == q)
4128ccd4a63SDavid du Colombier qidtab[h] = q->next;
4138ccd4a63SDavid du Colombier else{
4148ccd4a63SDavid du Colombier for(l=qidtab[h]; l->next!=q; l=l->next)
4158ccd4a63SDavid du Colombier if(l->next == nil)
4168ccd4a63SDavid du Colombier fatal("bad qid list");
4178ccd4a63SDavid du Colombier l->next = q->next;
4188ccd4a63SDavid du Colombier }
4198ccd4a63SDavid du Colombier free(q);
4208ccd4a63SDavid du Colombier }
4218ccd4a63SDavid du Colombier
4228ccd4a63SDavid du Colombier Qidtab*
qidlookup(Dir * d)4238ccd4a63SDavid du Colombier qidlookup(Dir *d)
4248ccd4a63SDavid du Colombier {
4258ccd4a63SDavid du Colombier ulong h;
4268ccd4a63SDavid du Colombier Qidtab *q;
4278ccd4a63SDavid du Colombier
4288ccd4a63SDavid du Colombier h = qidhash(d->qid.path);
4298ccd4a63SDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next)
4308ccd4a63SDavid du Colombier if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path)
4318ccd4a63SDavid du Colombier return q;
4328ccd4a63SDavid du Colombier return nil;
4338ccd4a63SDavid du Colombier }
4348ccd4a63SDavid du Colombier
4358ccd4a63SDavid du Colombier int
qidexists(vlong path)4368ccd4a63SDavid du Colombier qidexists(vlong path)
4378ccd4a63SDavid du Colombier {
4388ccd4a63SDavid du Colombier int h;
4398ccd4a63SDavid du Colombier Qidtab *q;
4408ccd4a63SDavid du Colombier
4418ccd4a63SDavid du Colombier for(h=0; h<Nqidtab; h++)
4428ccd4a63SDavid du Colombier for(q=qidtab[h]; q!=nil; q=q->next)
4438ccd4a63SDavid du Colombier if(q->uniqpath == path)
4448ccd4a63SDavid du Colombier return 1;
4458ccd4a63SDavid du Colombier return 0;
4468ccd4a63SDavid du Colombier }
4478ccd4a63SDavid du Colombier
4488ccd4a63SDavid du Colombier Qidtab*
uniqueqid(Dir * d)4498ccd4a63SDavid du Colombier uniqueqid(Dir *d)
4508ccd4a63SDavid du Colombier {
4518ccd4a63SDavid du Colombier ulong h;
4528ccd4a63SDavid du Colombier vlong path;
4538ccd4a63SDavid du Colombier Qidtab *q;
4548ccd4a63SDavid du Colombier
4558ccd4a63SDavid du Colombier q = qidlookup(d);
4568ccd4a63SDavid du Colombier if(q != nil){
4578ccd4a63SDavid du Colombier q->ref++;
4588ccd4a63SDavid du Colombier return q;
4598ccd4a63SDavid du Colombier }
4608ccd4a63SDavid du Colombier path = d->qid.path;
4618ccd4a63SDavid du Colombier while(qidexists(path)){
4628ccd4a63SDavid du Colombier DEBUG(DFD, "collision on %s\n", d->name);
4638ccd4a63SDavid du Colombier /* collision: find a new one */
4648ccd4a63SDavid du Colombier ncollision++;
4658ccd4a63SDavid du Colombier path &= QIDPATH;
4668ccd4a63SDavid du Colombier ++newqid;
4678ccd4a63SDavid du Colombier if(newqid >= (1<<16)){
4688ccd4a63SDavid du Colombier DEBUG(DFD, "collision wraparound\n");
4698ccd4a63SDavid du Colombier newqid = 1;
4708ccd4a63SDavid du Colombier }
4718ccd4a63SDavid du Colombier path |= newqid<<48;
4728ccd4a63SDavid du Colombier DEBUG(DFD, "assign qid %.16llux\n", path);
4738ccd4a63SDavid du Colombier }
4748ccd4a63SDavid du Colombier q = mallocz(sizeof(Qidtab), 1);
4758ccd4a63SDavid du Colombier if(q == nil)
4768ccd4a63SDavid du Colombier fatal("no memory for qid table");
4778ccd4a63SDavid du Colombier qidcnt++;
4788ccd4a63SDavid du Colombier q->ref = 1;
4798ccd4a63SDavid du Colombier q->type = d->type;
4808ccd4a63SDavid du Colombier q->dev = d->dev;
4818ccd4a63SDavid du Colombier q->path = d->qid.path;
4828ccd4a63SDavid du Colombier q->uniqpath = path;
4838ccd4a63SDavid du Colombier h = qidhash(d->qid.path);
4848ccd4a63SDavid du Colombier q->next = qidtab[h];
4858ccd4a63SDavid du Colombier qidtab[h] = q;
4868ccd4a63SDavid du Colombier return q;
4878ccd4a63SDavid du Colombier }
4888ccd4a63SDavid du Colombier
4898ccd4a63SDavid du Colombier void
fatal(char * s,...)4908ccd4a63SDavid du Colombier fatal(char *s, ...)
4918ccd4a63SDavid du Colombier {
4928ccd4a63SDavid du Colombier char buf[ERRMAX];
4938ccd4a63SDavid du Colombier va_list arg;
4948ccd4a63SDavid du Colombier
4958ccd4a63SDavid du Colombier if (s) {
4968ccd4a63SDavid du Colombier va_start(arg, s);
4978ccd4a63SDavid du Colombier vsnprint(buf, ERRMAX, s, arg);
4988ccd4a63SDavid du Colombier va_end(arg);
4998ccd4a63SDavid du Colombier }
5008ccd4a63SDavid du Colombier
5018ccd4a63SDavid du Colombier /* Clear away the slave children */
5028ccd4a63SDavid du Colombier // for(m = Proclist; m; m = m->next)
5038ccd4a63SDavid du Colombier // postnote(PNPROC, m->pid, "kill");
5048ccd4a63SDavid du Colombier
5058ccd4a63SDavid du Colombier DEBUG(DFD, "%s\n", buf);
5068ccd4a63SDavid du Colombier if (s)
5078ccd4a63SDavid du Colombier sysfatal(buf);
5088ccd4a63SDavid du Colombier else
5098ccd4a63SDavid du Colombier sysfatal("");
5108ccd4a63SDavid du Colombier }
5118ccd4a63SDavid du Colombier
512