1*8ccd4a63SDavid du Colombier #include "u.h" 2*8ccd4a63SDavid du Colombier #include "lib.h" 3*8ccd4a63SDavid du Colombier #include "dat.h" 4*8ccd4a63SDavid du Colombier #include "fns.h" 5*8ccd4a63SDavid du Colombier #include "error.h" 6*8ccd4a63SDavid du Colombier 7*8ccd4a63SDavid du Colombier /* 8*8ccd4a63SDavid du Colombier * References are managed as follows: 9*8ccd4a63SDavid du Colombier * The channel to the server - a network connection or pipe - has one 10*8ccd4a63SDavid du Colombier * reference for every Chan open on the server. The server channel has 11*8ccd4a63SDavid du Colombier * c->mux set to the Mnt used for muxing control to that server. Mnts 12*8ccd4a63SDavid du Colombier * have no reference count; they go away when c goes away. 13*8ccd4a63SDavid du Colombier * Each channel derived from the mount point has mchan set to c, 14*8ccd4a63SDavid du Colombier * and increfs/decrefs mchan to manage references on the server 15*8ccd4a63SDavid du Colombier * connection. 16*8ccd4a63SDavid du Colombier */ 17*8ccd4a63SDavid du Colombier 18*8ccd4a63SDavid du Colombier #define MAXRPC (IOHDRSZ+8192) 19*8ccd4a63SDavid du Colombier 20*8ccd4a63SDavid du Colombier struct Mntrpc 21*8ccd4a63SDavid du Colombier { 22*8ccd4a63SDavid du Colombier Chan* c; /* Channel for whom we are working */ 23*8ccd4a63SDavid du Colombier Mntrpc* list; /* Free/pending list */ 24*8ccd4a63SDavid du Colombier Fcall request; /* Outgoing file system protocol message */ 25*8ccd4a63SDavid du Colombier Fcall reply; /* Incoming reply */ 26*8ccd4a63SDavid du Colombier Mnt* m; /* Mount device during rpc */ 27*8ccd4a63SDavid du Colombier Rendez r; /* Place to hang out */ 28*8ccd4a63SDavid du Colombier uchar* rpc; /* I/O Data buffer */ 29*8ccd4a63SDavid du Colombier uint rpclen; /* len of buffer */ 30*8ccd4a63SDavid du Colombier Block *b; /* reply blocks */ 31*8ccd4a63SDavid du Colombier char done; /* Rpc completed */ 32*8ccd4a63SDavid du Colombier uvlong stime; /* start time for mnt statistics */ 33*8ccd4a63SDavid du Colombier ulong reqlen; /* request length for mnt statistics */ 34*8ccd4a63SDavid du Colombier ulong replen; /* reply length for mnt statistics */ 35*8ccd4a63SDavid du Colombier Mntrpc* flushed; /* message this one flushes */ 36*8ccd4a63SDavid du Colombier }; 37*8ccd4a63SDavid du Colombier 38*8ccd4a63SDavid du Colombier enum 39*8ccd4a63SDavid du Colombier { 40*8ccd4a63SDavid du Colombier TAGSHIFT = 5, /* ulong has to be 32 bits */ 41*8ccd4a63SDavid du Colombier TAGMASK = (1<<TAGSHIFT)-1, 42*8ccd4a63SDavid du Colombier NMASK = (64*1024)>>TAGSHIFT, 43*8ccd4a63SDavid du Colombier }; 44*8ccd4a63SDavid du Colombier 45*8ccd4a63SDavid du Colombier struct Mntalloc 46*8ccd4a63SDavid du Colombier { 47*8ccd4a63SDavid du Colombier Lock lk; 48*8ccd4a63SDavid du Colombier Mnt* list; /* Mount devices in use */ 49*8ccd4a63SDavid du Colombier Mnt* mntfree; /* Free list */ 50*8ccd4a63SDavid du Colombier Mntrpc* rpcfree; 51*8ccd4a63SDavid du Colombier int nrpcfree; 52*8ccd4a63SDavid du Colombier int nrpcused; 53*8ccd4a63SDavid du Colombier ulong id; 54*8ccd4a63SDavid du Colombier ulong tagmask[NMASK]; 55*8ccd4a63SDavid du Colombier }mntalloc; 56*8ccd4a63SDavid du Colombier 57*8ccd4a63SDavid du Colombier void mattach(Mnt*, Chan*, char*); 58*8ccd4a63SDavid du Colombier Mnt* mntchk(Chan*); 59*8ccd4a63SDavid du Colombier void mntdirfix(uchar*, Chan*); 60*8ccd4a63SDavid du Colombier Mntrpc* mntflushalloc(Mntrpc*, ulong); 61*8ccd4a63SDavid du Colombier void mntflushfree(Mnt*, Mntrpc*); 62*8ccd4a63SDavid du Colombier void mntfree(Mntrpc*); 63*8ccd4a63SDavid du Colombier void mntgate(Mnt*); 64*8ccd4a63SDavid du Colombier void mntpntfree(Mnt*); 65*8ccd4a63SDavid du Colombier void mntqrm(Mnt*, Mntrpc*); 66*8ccd4a63SDavid du Colombier Mntrpc* mntralloc(Chan*, ulong); 67*8ccd4a63SDavid du Colombier long mntrdwr(int, Chan*, void*, long, vlong); 68*8ccd4a63SDavid du Colombier int mntrpcread(Mnt*, Mntrpc*); 69*8ccd4a63SDavid du Colombier void mountio(Mnt*, Mntrpc*); 70*8ccd4a63SDavid du Colombier void mountmux(Mnt*, Mntrpc*); 71*8ccd4a63SDavid du Colombier void mountrpc(Mnt*, Mntrpc*); 72*8ccd4a63SDavid du Colombier int rpcattn(void*); 73*8ccd4a63SDavid du Colombier Chan* mntchan(void); 74*8ccd4a63SDavid du Colombier 75*8ccd4a63SDavid du Colombier char Esbadstat[] = "invalid directory entry received from server"; 76*8ccd4a63SDavid du Colombier char Enoversion[] = "version not established for mount channel"; 77*8ccd4a63SDavid du Colombier 78*8ccd4a63SDavid du Colombier 79*8ccd4a63SDavid du Colombier void (*mntstats)(int, Chan*, uvlong, ulong); 80*8ccd4a63SDavid du Colombier 81*8ccd4a63SDavid du Colombier static void 82*8ccd4a63SDavid du Colombier mntreset(void) 83*8ccd4a63SDavid du Colombier { 84*8ccd4a63SDavid du Colombier mntalloc.id = 1; 85*8ccd4a63SDavid du Colombier mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */ 86*8ccd4a63SDavid du Colombier mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */ 87*8ccd4a63SDavid du Colombier fmtinstall('F', fcallfmt); 88*8ccd4a63SDavid du Colombier fmtinstall('D', dirfmt); 89*8ccd4a63SDavid du Colombier /* We can't install %M since eipfmt does and is used in the kernel [sape] */ 90*8ccd4a63SDavid du Colombier 91*8ccd4a63SDavid du Colombier cinit(); 92*8ccd4a63SDavid du Colombier } 93*8ccd4a63SDavid du Colombier 94*8ccd4a63SDavid du Colombier /* 95*8ccd4a63SDavid du Colombier * Version is not multiplexed: message sent only once per connection. 96*8ccd4a63SDavid du Colombier */ 97*8ccd4a63SDavid du Colombier long 98*8ccd4a63SDavid du Colombier mntversion(Chan *c, char *version, int msize, int returnlen) 99*8ccd4a63SDavid du Colombier { 100*8ccd4a63SDavid du Colombier Fcall f; 101*8ccd4a63SDavid du Colombier uchar *msg; 102*8ccd4a63SDavid du Colombier Mnt *m; 103*8ccd4a63SDavid du Colombier char *v; 104*8ccd4a63SDavid du Colombier long k, l; 105*8ccd4a63SDavid du Colombier uvlong oo; 106*8ccd4a63SDavid du Colombier char buf[128]; 107*8ccd4a63SDavid du Colombier 108*8ccd4a63SDavid du Colombier qlock(&c->umqlock); /* make sure no one else does this until we've established ourselves */ 109*8ccd4a63SDavid du Colombier if(waserror()){ 110*8ccd4a63SDavid du Colombier qunlock(&c->umqlock); 111*8ccd4a63SDavid du Colombier nexterror(); 112*8ccd4a63SDavid du Colombier } 113*8ccd4a63SDavid du Colombier 114*8ccd4a63SDavid du Colombier /* defaults */ 115*8ccd4a63SDavid du Colombier if(msize == 0) 116*8ccd4a63SDavid du Colombier msize = MAXRPC; 117*8ccd4a63SDavid du Colombier if(msize > c->iounit && c->iounit != 0) 118*8ccd4a63SDavid du Colombier msize = c->iounit; 119*8ccd4a63SDavid du Colombier v = version; 120*8ccd4a63SDavid du Colombier if(v == nil || v[0] == '\0') 121*8ccd4a63SDavid du Colombier v = VERSION9P; 122*8ccd4a63SDavid du Colombier 123*8ccd4a63SDavid du Colombier /* validity */ 124*8ccd4a63SDavid du Colombier if(msize < 0) 125*8ccd4a63SDavid du Colombier error("bad iounit in version call"); 126*8ccd4a63SDavid du Colombier if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0) 127*8ccd4a63SDavid du Colombier error("bad 9P version specification"); 128*8ccd4a63SDavid du Colombier 129*8ccd4a63SDavid du Colombier m = c->mux; 130*8ccd4a63SDavid du Colombier 131*8ccd4a63SDavid du Colombier if(m != nil){ 132*8ccd4a63SDavid du Colombier qunlock(&c->umqlock); 133*8ccd4a63SDavid du Colombier poperror(); 134*8ccd4a63SDavid du Colombier 135*8ccd4a63SDavid du Colombier strecpy(buf, buf+sizeof buf, m->version); 136*8ccd4a63SDavid du Colombier k = strlen(buf); 137*8ccd4a63SDavid du Colombier if(strncmp(buf, v, k) != 0){ 138*8ccd4a63SDavid du Colombier snprint(buf, sizeof buf, "incompatible 9P versions %s %s", m->version, v); 139*8ccd4a63SDavid du Colombier error(buf); 140*8ccd4a63SDavid du Colombier } 141*8ccd4a63SDavid du Colombier if(returnlen > 0){ 142*8ccd4a63SDavid du Colombier if(returnlen < k) 143*8ccd4a63SDavid du Colombier error(Eshort); 144*8ccd4a63SDavid du Colombier memmove(version, buf, k); 145*8ccd4a63SDavid du Colombier } 146*8ccd4a63SDavid du Colombier return k; 147*8ccd4a63SDavid du Colombier } 148*8ccd4a63SDavid du Colombier 149*8ccd4a63SDavid du Colombier f.type = Tversion; 150*8ccd4a63SDavid du Colombier f.tag = NOTAG; 151*8ccd4a63SDavid du Colombier f.msize = msize; 152*8ccd4a63SDavid du Colombier f.version = v; 153*8ccd4a63SDavid du Colombier msg = malloc(8192+IOHDRSZ); 154*8ccd4a63SDavid du Colombier if(msg == nil) 155*8ccd4a63SDavid du Colombier exhausted("version memory"); 156*8ccd4a63SDavid du Colombier if(waserror()){ 157*8ccd4a63SDavid du Colombier free(msg); 158*8ccd4a63SDavid du Colombier nexterror(); 159*8ccd4a63SDavid du Colombier } 160*8ccd4a63SDavid du Colombier k = convS2M(&f, msg, 8192+IOHDRSZ); 161*8ccd4a63SDavid du Colombier if(k == 0) 162*8ccd4a63SDavid du Colombier error("bad fversion conversion on send"); 163*8ccd4a63SDavid du Colombier 164*8ccd4a63SDavid du Colombier lock(&c->ref.lk); 165*8ccd4a63SDavid du Colombier oo = c->offset; 166*8ccd4a63SDavid du Colombier c->offset += k; 167*8ccd4a63SDavid du Colombier unlock(&c->ref.lk); 168*8ccd4a63SDavid du Colombier 169*8ccd4a63SDavid du Colombier l = devtab[c->type]->write(c, msg, k, oo); 170*8ccd4a63SDavid du Colombier 171*8ccd4a63SDavid du Colombier if(l < k){ 172*8ccd4a63SDavid du Colombier lock(&c->ref.lk); 173*8ccd4a63SDavid du Colombier c->offset -= k - l; 174*8ccd4a63SDavid du Colombier unlock(&c->ref.lk); 175*8ccd4a63SDavid du Colombier error("short write in fversion"); 176*8ccd4a63SDavid du Colombier } 177*8ccd4a63SDavid du Colombier 178*8ccd4a63SDavid du Colombier /* message sent; receive and decode reply */ 179*8ccd4a63SDavid du Colombier k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset); 180*8ccd4a63SDavid du Colombier if(k <= 0) 181*8ccd4a63SDavid du Colombier error("EOF receiving fversion reply"); 182*8ccd4a63SDavid du Colombier 183*8ccd4a63SDavid du Colombier lock(&c->ref.lk); 184*8ccd4a63SDavid du Colombier c->offset += k; 185*8ccd4a63SDavid du Colombier unlock(&c->ref.lk); 186*8ccd4a63SDavid du Colombier 187*8ccd4a63SDavid du Colombier l = convM2S(msg, k, &f); 188*8ccd4a63SDavid du Colombier if(l != k) 189*8ccd4a63SDavid du Colombier error("bad fversion conversion on reply"); 190*8ccd4a63SDavid du Colombier if(f.type != Rversion){ 191*8ccd4a63SDavid du Colombier if(f.type == Rerror) 192*8ccd4a63SDavid du Colombier error(f.ename); 193*8ccd4a63SDavid du Colombier error("unexpected reply type in fversion"); 194*8ccd4a63SDavid du Colombier } 195*8ccd4a63SDavid du Colombier if(f.msize > msize) 196*8ccd4a63SDavid du Colombier error("server tries to increase msize in fversion"); 197*8ccd4a63SDavid du Colombier if(f.msize<256 || f.msize>1024*1024) 198*8ccd4a63SDavid du Colombier error("nonsense value of msize in fversion"); 199*8ccd4a63SDavid du Colombier if(strncmp(f.version, v, strlen(f.version)) != 0) 200*8ccd4a63SDavid du Colombier error("bad 9P version returned from server"); 201*8ccd4a63SDavid du Colombier 202*8ccd4a63SDavid du Colombier /* now build Mnt associated with this connection */ 203*8ccd4a63SDavid du Colombier lock(&mntalloc.lk); 204*8ccd4a63SDavid du Colombier m = mntalloc.mntfree; 205*8ccd4a63SDavid du Colombier if(m != 0) 206*8ccd4a63SDavid du Colombier mntalloc.mntfree = m->list; 207*8ccd4a63SDavid du Colombier else { 208*8ccd4a63SDavid du Colombier m = malloc(sizeof(Mnt)); 209*8ccd4a63SDavid du Colombier if(m == 0) { 210*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 211*8ccd4a63SDavid du Colombier exhausted("mount devices"); 212*8ccd4a63SDavid du Colombier } 213*8ccd4a63SDavid du Colombier } 214*8ccd4a63SDavid du Colombier m->list = mntalloc.list; 215*8ccd4a63SDavid du Colombier mntalloc.list = m; 216*8ccd4a63SDavid du Colombier m->version = nil; 217*8ccd4a63SDavid du Colombier kstrdup(&m->version, f.version); 218*8ccd4a63SDavid du Colombier m->id = mntalloc.id++; 219*8ccd4a63SDavid du Colombier m->q = qopen(10*MAXRPC, 0, nil, nil); 220*8ccd4a63SDavid du Colombier m->msize = f.msize; 221*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 222*8ccd4a63SDavid du Colombier 223*8ccd4a63SDavid du Colombier poperror(); /* msg */ 224*8ccd4a63SDavid du Colombier free(msg); 225*8ccd4a63SDavid du Colombier 226*8ccd4a63SDavid du Colombier lock(&m->lk); 227*8ccd4a63SDavid du Colombier m->queue = 0; 228*8ccd4a63SDavid du Colombier m->rip = 0; 229*8ccd4a63SDavid du Colombier 230*8ccd4a63SDavid du Colombier c->flag |= CMSG; 231*8ccd4a63SDavid du Colombier c->mux = m; 232*8ccd4a63SDavid du Colombier m->c = c; 233*8ccd4a63SDavid du Colombier unlock(&m->lk); 234*8ccd4a63SDavid du Colombier 235*8ccd4a63SDavid du Colombier poperror(); /* c */ 236*8ccd4a63SDavid du Colombier qunlock(&c->umqlock); 237*8ccd4a63SDavid du Colombier 238*8ccd4a63SDavid du Colombier k = strlen(f.version); 239*8ccd4a63SDavid du Colombier if(returnlen > 0){ 240*8ccd4a63SDavid du Colombier if(returnlen < k) 241*8ccd4a63SDavid du Colombier error(Eshort); 242*8ccd4a63SDavid du Colombier memmove(version, f.version, k); 243*8ccd4a63SDavid du Colombier } 244*8ccd4a63SDavid du Colombier 245*8ccd4a63SDavid du Colombier return k; 246*8ccd4a63SDavid du Colombier } 247*8ccd4a63SDavid du Colombier 248*8ccd4a63SDavid du Colombier Chan* 249*8ccd4a63SDavid du Colombier mntauth(Chan *c, char *spec) 250*8ccd4a63SDavid du Colombier { 251*8ccd4a63SDavid du Colombier Mnt *m; 252*8ccd4a63SDavid du Colombier Mntrpc *r; 253*8ccd4a63SDavid du Colombier 254*8ccd4a63SDavid du Colombier m = c->mux; 255*8ccd4a63SDavid du Colombier 256*8ccd4a63SDavid du Colombier if(m == nil){ 257*8ccd4a63SDavid du Colombier mntversion(c, VERSION9P, MAXRPC, 0); 258*8ccd4a63SDavid du Colombier m = c->mux; 259*8ccd4a63SDavid du Colombier if(m == nil) 260*8ccd4a63SDavid du Colombier error(Enoversion); 261*8ccd4a63SDavid du Colombier } 262*8ccd4a63SDavid du Colombier 263*8ccd4a63SDavid du Colombier c = mntchan(); 264*8ccd4a63SDavid du Colombier if(waserror()) { 265*8ccd4a63SDavid du Colombier /* Close must not be called since it will 266*8ccd4a63SDavid du Colombier * call mnt recursively 267*8ccd4a63SDavid du Colombier */ 268*8ccd4a63SDavid du Colombier chanfree(c); 269*8ccd4a63SDavid du Colombier nexterror(); 270*8ccd4a63SDavid du Colombier } 271*8ccd4a63SDavid du Colombier 272*8ccd4a63SDavid du Colombier r = mntralloc(0, m->msize); 273*8ccd4a63SDavid du Colombier 274*8ccd4a63SDavid du Colombier if(waserror()) { 275*8ccd4a63SDavid du Colombier mntfree(r); 276*8ccd4a63SDavid du Colombier nexterror(); 277*8ccd4a63SDavid du Colombier } 278*8ccd4a63SDavid du Colombier 279*8ccd4a63SDavid du Colombier r->request.type = Tauth; 280*8ccd4a63SDavid du Colombier r->request.afid = c->fid; 281*8ccd4a63SDavid du Colombier r->request.uname = up->user; 282*8ccd4a63SDavid du Colombier r->request.aname = spec; 283*8ccd4a63SDavid du Colombier mountrpc(m, r); 284*8ccd4a63SDavid du Colombier 285*8ccd4a63SDavid du Colombier c->qid = r->reply.aqid; 286*8ccd4a63SDavid du Colombier c->mchan = m->c; 287*8ccd4a63SDavid du Colombier incref(&m->c->ref); 288*8ccd4a63SDavid du Colombier c->mqid = c->qid; 289*8ccd4a63SDavid du Colombier c->mode = ORDWR; 290*8ccd4a63SDavid du Colombier 291*8ccd4a63SDavid du Colombier poperror(); /* r */ 292*8ccd4a63SDavid du Colombier mntfree(r); 293*8ccd4a63SDavid du Colombier 294*8ccd4a63SDavid du Colombier poperror(); /* c */ 295*8ccd4a63SDavid du Colombier 296*8ccd4a63SDavid du Colombier return c; 297*8ccd4a63SDavid du Colombier 298*8ccd4a63SDavid du Colombier } 299*8ccd4a63SDavid du Colombier 300*8ccd4a63SDavid du Colombier static Chan* 301*8ccd4a63SDavid du Colombier mntattach(char *muxattach) 302*8ccd4a63SDavid du Colombier { 303*8ccd4a63SDavid du Colombier Mnt *m; 304*8ccd4a63SDavid du Colombier Chan *c; 305*8ccd4a63SDavid du Colombier Mntrpc *r; 306*8ccd4a63SDavid du Colombier struct bogus{ 307*8ccd4a63SDavid du Colombier Chan *chan; 308*8ccd4a63SDavid du Colombier Chan *authchan; 309*8ccd4a63SDavid du Colombier char *spec; 310*8ccd4a63SDavid du Colombier int flags; 311*8ccd4a63SDavid du Colombier }bogus; 312*8ccd4a63SDavid du Colombier 313*8ccd4a63SDavid du Colombier bogus = *((struct bogus *)muxattach); 314*8ccd4a63SDavid du Colombier c = bogus.chan; 315*8ccd4a63SDavid du Colombier 316*8ccd4a63SDavid du Colombier m = c->mux; 317*8ccd4a63SDavid du Colombier 318*8ccd4a63SDavid du Colombier if(m == nil){ 319*8ccd4a63SDavid du Colombier mntversion(c, nil, 0, 0); 320*8ccd4a63SDavid du Colombier m = c->mux; 321*8ccd4a63SDavid du Colombier if(m == nil) 322*8ccd4a63SDavid du Colombier error(Enoversion); 323*8ccd4a63SDavid du Colombier } 324*8ccd4a63SDavid du Colombier 325*8ccd4a63SDavid du Colombier c = mntchan(); 326*8ccd4a63SDavid du Colombier if(waserror()) { 327*8ccd4a63SDavid du Colombier /* Close must not be called since it will 328*8ccd4a63SDavid du Colombier * call mnt recursively 329*8ccd4a63SDavid du Colombier */ 330*8ccd4a63SDavid du Colombier chanfree(c); 331*8ccd4a63SDavid du Colombier nexterror(); 332*8ccd4a63SDavid du Colombier } 333*8ccd4a63SDavid du Colombier 334*8ccd4a63SDavid du Colombier r = mntralloc(0, m->msize); 335*8ccd4a63SDavid du Colombier 336*8ccd4a63SDavid du Colombier if(waserror()) { 337*8ccd4a63SDavid du Colombier mntfree(r); 338*8ccd4a63SDavid du Colombier nexterror(); 339*8ccd4a63SDavid du Colombier } 340*8ccd4a63SDavid du Colombier 341*8ccd4a63SDavid du Colombier r->request.type = Tattach; 342*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 343*8ccd4a63SDavid du Colombier if(bogus.authchan == nil) 344*8ccd4a63SDavid du Colombier r->request.afid = NOFID; 345*8ccd4a63SDavid du Colombier else 346*8ccd4a63SDavid du Colombier r->request.afid = bogus.authchan->fid; 347*8ccd4a63SDavid du Colombier r->request.uname = up->user; 348*8ccd4a63SDavid du Colombier r->request.aname = bogus.spec; 349*8ccd4a63SDavid du Colombier mountrpc(m, r); 350*8ccd4a63SDavid du Colombier 351*8ccd4a63SDavid du Colombier c->qid = r->reply.qid; 352*8ccd4a63SDavid du Colombier c->mchan = m->c; 353*8ccd4a63SDavid du Colombier incref(&m->c->ref); 354*8ccd4a63SDavid du Colombier c->mqid = c->qid; 355*8ccd4a63SDavid du Colombier 356*8ccd4a63SDavid du Colombier poperror(); /* r */ 357*8ccd4a63SDavid du Colombier mntfree(r); 358*8ccd4a63SDavid du Colombier 359*8ccd4a63SDavid du Colombier poperror(); /* c */ 360*8ccd4a63SDavid du Colombier 361*8ccd4a63SDavid du Colombier if(bogus.flags&MCACHE) 362*8ccd4a63SDavid du Colombier c->flag |= CCACHE; 363*8ccd4a63SDavid du Colombier return c; 364*8ccd4a63SDavid du Colombier } 365*8ccd4a63SDavid du Colombier 366*8ccd4a63SDavid du Colombier Chan* 367*8ccd4a63SDavid du Colombier mntchan(void) 368*8ccd4a63SDavid du Colombier { 369*8ccd4a63SDavid du Colombier Chan *c; 370*8ccd4a63SDavid du Colombier 371*8ccd4a63SDavid du Colombier c = devattach('M', 0); 372*8ccd4a63SDavid du Colombier lock(&mntalloc.lk); 373*8ccd4a63SDavid du Colombier c->dev = mntalloc.id++; 374*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 375*8ccd4a63SDavid du Colombier 376*8ccd4a63SDavid du Colombier if(c->mchan) 377*8ccd4a63SDavid du Colombier panic("mntchan non-zero %p", c->mchan); 378*8ccd4a63SDavid du Colombier return c; 379*8ccd4a63SDavid du Colombier } 380*8ccd4a63SDavid du Colombier 381*8ccd4a63SDavid du Colombier static Walkqid* 382*8ccd4a63SDavid du Colombier mntwalk(Chan *c, Chan *nc, char **name, int nname) 383*8ccd4a63SDavid du Colombier { 384*8ccd4a63SDavid du Colombier int i, alloc; 385*8ccd4a63SDavid du Colombier Mnt *m; 386*8ccd4a63SDavid du Colombier Mntrpc *r; 387*8ccd4a63SDavid du Colombier Walkqid *wq; 388*8ccd4a63SDavid du Colombier 389*8ccd4a63SDavid du Colombier if(nc != nil) 390*8ccd4a63SDavid du Colombier print("mntwalk: nc != nil\n"); 391*8ccd4a63SDavid du Colombier if(nname > MAXWELEM) 392*8ccd4a63SDavid du Colombier error("devmnt: too many name elements"); 393*8ccd4a63SDavid du Colombier alloc = 0; 394*8ccd4a63SDavid du Colombier wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid)); 395*8ccd4a63SDavid du Colombier if(waserror()){ 396*8ccd4a63SDavid du Colombier if(alloc && wq->clone!=nil) 397*8ccd4a63SDavid du Colombier cclose(wq->clone); 398*8ccd4a63SDavid du Colombier free(wq); 399*8ccd4a63SDavid du Colombier return nil; 400*8ccd4a63SDavid du Colombier } 401*8ccd4a63SDavid du Colombier 402*8ccd4a63SDavid du Colombier alloc = 0; 403*8ccd4a63SDavid du Colombier m = mntchk(c); 404*8ccd4a63SDavid du Colombier r = mntralloc(c, m->msize); 405*8ccd4a63SDavid du Colombier if(nc == nil){ 406*8ccd4a63SDavid du Colombier nc = devclone(c); 407*8ccd4a63SDavid du Colombier /* 408*8ccd4a63SDavid du Colombier * Until the other side accepts this fid, we can't mntclose it. 409*8ccd4a63SDavid du Colombier * Therefore set type to 0 for now; rootclose is known to be safe. 410*8ccd4a63SDavid du Colombier */ 411*8ccd4a63SDavid du Colombier nc->type = 0; 412*8ccd4a63SDavid du Colombier alloc = 1; 413*8ccd4a63SDavid du Colombier } 414*8ccd4a63SDavid du Colombier wq->clone = nc; 415*8ccd4a63SDavid du Colombier 416*8ccd4a63SDavid du Colombier if(waserror()) { 417*8ccd4a63SDavid du Colombier mntfree(r); 418*8ccd4a63SDavid du Colombier nexterror(); 419*8ccd4a63SDavid du Colombier } 420*8ccd4a63SDavid du Colombier r->request.type = Twalk; 421*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 422*8ccd4a63SDavid du Colombier r->request.newfid = nc->fid; 423*8ccd4a63SDavid du Colombier r->request.nwname = nname; 424*8ccd4a63SDavid du Colombier memmove(r->request.wname, name, nname*sizeof(char*)); 425*8ccd4a63SDavid du Colombier 426*8ccd4a63SDavid du Colombier mountrpc(m, r); 427*8ccd4a63SDavid du Colombier 428*8ccd4a63SDavid du Colombier if(r->reply.nwqid > nname) 429*8ccd4a63SDavid du Colombier error("too many QIDs returned by walk"); 430*8ccd4a63SDavid du Colombier if(r->reply.nwqid < nname){ 431*8ccd4a63SDavid du Colombier if(alloc) 432*8ccd4a63SDavid du Colombier cclose(nc); 433*8ccd4a63SDavid du Colombier wq->clone = nil; 434*8ccd4a63SDavid du Colombier if(r->reply.nwqid == 0){ 435*8ccd4a63SDavid du Colombier free(wq); 436*8ccd4a63SDavid du Colombier wq = nil; 437*8ccd4a63SDavid du Colombier goto Return; 438*8ccd4a63SDavid du Colombier } 439*8ccd4a63SDavid du Colombier } 440*8ccd4a63SDavid du Colombier 441*8ccd4a63SDavid du Colombier /* move new fid onto mnt device and update its qid */ 442*8ccd4a63SDavid du Colombier if(wq->clone != nil){ 443*8ccd4a63SDavid du Colombier if(wq->clone != c){ 444*8ccd4a63SDavid du Colombier wq->clone->type = c->type; 445*8ccd4a63SDavid du Colombier wq->clone->mchan = c->mchan; 446*8ccd4a63SDavid du Colombier incref(&c->mchan->ref); 447*8ccd4a63SDavid du Colombier } 448*8ccd4a63SDavid du Colombier if(r->reply.nwqid > 0) 449*8ccd4a63SDavid du Colombier wq->clone->qid = r->reply.wqid[r->reply.nwqid-1]; 450*8ccd4a63SDavid du Colombier } 451*8ccd4a63SDavid du Colombier wq->nqid = r->reply.nwqid; 452*8ccd4a63SDavid du Colombier for(i=0; i<wq->nqid; i++) 453*8ccd4a63SDavid du Colombier wq->qid[i] = r->reply.wqid[i]; 454*8ccd4a63SDavid du Colombier 455*8ccd4a63SDavid du Colombier Return: 456*8ccd4a63SDavid du Colombier poperror(); 457*8ccd4a63SDavid du Colombier mntfree(r); 458*8ccd4a63SDavid du Colombier poperror(); 459*8ccd4a63SDavid du Colombier return wq; 460*8ccd4a63SDavid du Colombier } 461*8ccd4a63SDavid du Colombier 462*8ccd4a63SDavid du Colombier static int 463*8ccd4a63SDavid du Colombier mntstat(Chan *c, uchar *dp, int n) 464*8ccd4a63SDavid du Colombier { 465*8ccd4a63SDavid du Colombier Mnt *m; 466*8ccd4a63SDavid du Colombier Mntrpc *r; 467*8ccd4a63SDavid du Colombier 468*8ccd4a63SDavid du Colombier if(n < BIT16SZ) 469*8ccd4a63SDavid du Colombier error(Eshortstat); 470*8ccd4a63SDavid du Colombier m = mntchk(c); 471*8ccd4a63SDavid du Colombier r = mntralloc(c, m->msize); 472*8ccd4a63SDavid du Colombier if(waserror()) { 473*8ccd4a63SDavid du Colombier mntfree(r); 474*8ccd4a63SDavid du Colombier nexterror(); 475*8ccd4a63SDavid du Colombier } 476*8ccd4a63SDavid du Colombier r->request.type = Tstat; 477*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 478*8ccd4a63SDavid du Colombier mountrpc(m, r); 479*8ccd4a63SDavid du Colombier 480*8ccd4a63SDavid du Colombier /* r->reply.nstat is 16 bits 481*8ccd4a63SDavid du Colombier if(r->reply.nstat >= 1<<16) 482*8ccd4a63SDavid du Colombier error("returned stat buffer count too large"); 483*8ccd4a63SDavid du Colombier */ 484*8ccd4a63SDavid du Colombier 485*8ccd4a63SDavid du Colombier if(r->reply.nstat > n){ 486*8ccd4a63SDavid du Colombier /* 487*8ccd4a63SDavid du Colombier * 12/31/2002 RSC 488*8ccd4a63SDavid du Colombier * 489*8ccd4a63SDavid du Colombier * This should be nstat-2, which is the first two 490*8ccd4a63SDavid du Colombier * bytes of the stat buffer. But dirstat and dirfstat 491*8ccd4a63SDavid du Colombier * depended on getting the full nstat (they didn't 492*8ccd4a63SDavid du Colombier * add BIT16SZ themselves). I fixed dirstat and dirfstat 493*8ccd4a63SDavid du Colombier * but am leaving this unchanged for now. After a 494*8ccd4a63SDavid du Colombier * few months, once enough of the relevant binaries 495*8ccd4a63SDavid du Colombier * have been recompiled for other reasons, we can 496*8ccd4a63SDavid du Colombier * change this to nstat-2. Devstat gets this right 497*8ccd4a63SDavid du Colombier * (via convD2M). 498*8ccd4a63SDavid du Colombier */ 499*8ccd4a63SDavid du Colombier /* doesn't fit; just patch the count and return */ 500*8ccd4a63SDavid du Colombier PBIT16((uchar*)dp, r->reply.nstat); 501*8ccd4a63SDavid du Colombier n = BIT16SZ; 502*8ccd4a63SDavid du Colombier }else{ 503*8ccd4a63SDavid du Colombier n = r->reply.nstat; 504*8ccd4a63SDavid du Colombier memmove(dp, r->reply.stat, n); 505*8ccd4a63SDavid du Colombier validstat(dp, n); 506*8ccd4a63SDavid du Colombier mntdirfix(dp, c); 507*8ccd4a63SDavid du Colombier } 508*8ccd4a63SDavid du Colombier poperror(); 509*8ccd4a63SDavid du Colombier mntfree(r); 510*8ccd4a63SDavid du Colombier return n; 511*8ccd4a63SDavid du Colombier } 512*8ccd4a63SDavid du Colombier 513*8ccd4a63SDavid du Colombier static Chan* 514*8ccd4a63SDavid du Colombier mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) 515*8ccd4a63SDavid du Colombier { 516*8ccd4a63SDavid du Colombier Mnt *m; 517*8ccd4a63SDavid du Colombier Mntrpc *r; 518*8ccd4a63SDavid du Colombier 519*8ccd4a63SDavid du Colombier m = mntchk(c); 520*8ccd4a63SDavid du Colombier r = mntralloc(c, m->msize); 521*8ccd4a63SDavid du Colombier if(waserror()) { 522*8ccd4a63SDavid du Colombier mntfree(r); 523*8ccd4a63SDavid du Colombier nexterror(); 524*8ccd4a63SDavid du Colombier } 525*8ccd4a63SDavid du Colombier r->request.type = type; 526*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 527*8ccd4a63SDavid du Colombier r->request.mode = omode; 528*8ccd4a63SDavid du Colombier if(type == Tcreate){ 529*8ccd4a63SDavid du Colombier r->request.perm = perm; 530*8ccd4a63SDavid du Colombier r->request.name = name; 531*8ccd4a63SDavid du Colombier } 532*8ccd4a63SDavid du Colombier mountrpc(m, r); 533*8ccd4a63SDavid du Colombier 534*8ccd4a63SDavid du Colombier c->qid = r->reply.qid; 535*8ccd4a63SDavid du Colombier c->offset = 0; 536*8ccd4a63SDavid du Colombier c->mode = openmode(omode); 537*8ccd4a63SDavid du Colombier c->iounit = r->reply.iounit; 538*8ccd4a63SDavid du Colombier if(c->iounit == 0 || c->iounit > m->msize-IOHDRSZ) 539*8ccd4a63SDavid du Colombier c->iounit = m->msize-IOHDRSZ; 540*8ccd4a63SDavid du Colombier c->flag |= COPEN; 541*8ccd4a63SDavid du Colombier poperror(); 542*8ccd4a63SDavid du Colombier mntfree(r); 543*8ccd4a63SDavid du Colombier 544*8ccd4a63SDavid du Colombier if(c->flag & CCACHE) 545*8ccd4a63SDavid du Colombier copen(c); 546*8ccd4a63SDavid du Colombier 547*8ccd4a63SDavid du Colombier return c; 548*8ccd4a63SDavid du Colombier } 549*8ccd4a63SDavid du Colombier 550*8ccd4a63SDavid du Colombier static Chan* 551*8ccd4a63SDavid du Colombier mntopen(Chan *c, int omode) 552*8ccd4a63SDavid du Colombier { 553*8ccd4a63SDavid du Colombier return mntopencreate(Topen, c, nil, omode, 0); 554*8ccd4a63SDavid du Colombier } 555*8ccd4a63SDavid du Colombier 556*8ccd4a63SDavid du Colombier static void 557*8ccd4a63SDavid du Colombier mntcreate(Chan *c, char *name, int omode, ulong perm) 558*8ccd4a63SDavid du Colombier { 559*8ccd4a63SDavid du Colombier mntopencreate(Tcreate, c, name, omode, perm); 560*8ccd4a63SDavid du Colombier } 561*8ccd4a63SDavid du Colombier 562*8ccd4a63SDavid du Colombier static void 563*8ccd4a63SDavid du Colombier mntclunk(Chan *c, int t) 564*8ccd4a63SDavid du Colombier { 565*8ccd4a63SDavid du Colombier Mnt *m; 566*8ccd4a63SDavid du Colombier Mntrpc *r; 567*8ccd4a63SDavid du Colombier 568*8ccd4a63SDavid du Colombier m = mntchk(c); 569*8ccd4a63SDavid du Colombier r = mntralloc(c, m->msize); 570*8ccd4a63SDavid du Colombier if(waserror()){ 571*8ccd4a63SDavid du Colombier mntfree(r); 572*8ccd4a63SDavid du Colombier nexterror(); 573*8ccd4a63SDavid du Colombier } 574*8ccd4a63SDavid du Colombier 575*8ccd4a63SDavid du Colombier r->request.type = t; 576*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 577*8ccd4a63SDavid du Colombier mountrpc(m, r); 578*8ccd4a63SDavid du Colombier mntfree(r); 579*8ccd4a63SDavid du Colombier poperror(); 580*8ccd4a63SDavid du Colombier } 581*8ccd4a63SDavid du Colombier 582*8ccd4a63SDavid du Colombier void 583*8ccd4a63SDavid du Colombier muxclose(Mnt *m) 584*8ccd4a63SDavid du Colombier { 585*8ccd4a63SDavid du Colombier Mntrpc *q, *r; 586*8ccd4a63SDavid du Colombier 587*8ccd4a63SDavid du Colombier for(q = m->queue; q; q = r) { 588*8ccd4a63SDavid du Colombier r = q->list; 589*8ccd4a63SDavid du Colombier mntfree(q); 590*8ccd4a63SDavid du Colombier } 591*8ccd4a63SDavid du Colombier m->id = 0; 592*8ccd4a63SDavid du Colombier free(m->version); 593*8ccd4a63SDavid du Colombier m->version = nil; 594*8ccd4a63SDavid du Colombier mntpntfree(m); 595*8ccd4a63SDavid du Colombier } 596*8ccd4a63SDavid du Colombier 597*8ccd4a63SDavid du Colombier void 598*8ccd4a63SDavid du Colombier mntpntfree(Mnt *m) 599*8ccd4a63SDavid du Colombier { 600*8ccd4a63SDavid du Colombier Mnt *f, **l; 601*8ccd4a63SDavid du Colombier Queue *q; 602*8ccd4a63SDavid du Colombier 603*8ccd4a63SDavid du Colombier lock(&mntalloc.lk); 604*8ccd4a63SDavid du Colombier l = &mntalloc.list; 605*8ccd4a63SDavid du Colombier for(f = *l; f; f = f->list) { 606*8ccd4a63SDavid du Colombier if(f == m) { 607*8ccd4a63SDavid du Colombier *l = m->list; 608*8ccd4a63SDavid du Colombier break; 609*8ccd4a63SDavid du Colombier } 610*8ccd4a63SDavid du Colombier l = &f->list; 611*8ccd4a63SDavid du Colombier } 612*8ccd4a63SDavid du Colombier m->list = mntalloc.mntfree; 613*8ccd4a63SDavid du Colombier mntalloc.mntfree = m; 614*8ccd4a63SDavid du Colombier q = m->q; 615*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 616*8ccd4a63SDavid du Colombier 617*8ccd4a63SDavid du Colombier qfree(q); 618*8ccd4a63SDavid du Colombier } 619*8ccd4a63SDavid du Colombier 620*8ccd4a63SDavid du Colombier static void 621*8ccd4a63SDavid du Colombier mntclose(Chan *c) 622*8ccd4a63SDavid du Colombier { 623*8ccd4a63SDavid du Colombier mntclunk(c, Tclunk); 624*8ccd4a63SDavid du Colombier } 625*8ccd4a63SDavid du Colombier 626*8ccd4a63SDavid du Colombier static void 627*8ccd4a63SDavid du Colombier mntremove(Chan *c) 628*8ccd4a63SDavid du Colombier { 629*8ccd4a63SDavid du Colombier mntclunk(c, Tremove); 630*8ccd4a63SDavid du Colombier } 631*8ccd4a63SDavid du Colombier 632*8ccd4a63SDavid du Colombier static int 633*8ccd4a63SDavid du Colombier mntwstat(Chan *c, uchar *dp, int n) 634*8ccd4a63SDavid du Colombier { 635*8ccd4a63SDavid du Colombier Mnt *m; 636*8ccd4a63SDavid du Colombier Mntrpc *r; 637*8ccd4a63SDavid du Colombier 638*8ccd4a63SDavid du Colombier m = mntchk(c); 639*8ccd4a63SDavid du Colombier r = mntralloc(c, m->msize); 640*8ccd4a63SDavid du Colombier if(waserror()) { 641*8ccd4a63SDavid du Colombier mntfree(r); 642*8ccd4a63SDavid du Colombier nexterror(); 643*8ccd4a63SDavid du Colombier } 644*8ccd4a63SDavid du Colombier r->request.type = Twstat; 645*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 646*8ccd4a63SDavid du Colombier r->request.nstat = n; 647*8ccd4a63SDavid du Colombier r->request.stat = dp; 648*8ccd4a63SDavid du Colombier mountrpc(m, r); 649*8ccd4a63SDavid du Colombier poperror(); 650*8ccd4a63SDavid du Colombier mntfree(r); 651*8ccd4a63SDavid du Colombier return n; 652*8ccd4a63SDavid du Colombier } 653*8ccd4a63SDavid du Colombier 654*8ccd4a63SDavid du Colombier static long 655*8ccd4a63SDavid du Colombier mntread(Chan *c, void *buf, long n, vlong off) 656*8ccd4a63SDavid du Colombier { 657*8ccd4a63SDavid du Colombier uchar *p, *e; 658*8ccd4a63SDavid du Colombier int nc, cache, isdir, dirlen; 659*8ccd4a63SDavid du Colombier 660*8ccd4a63SDavid du Colombier isdir = 0; 661*8ccd4a63SDavid du Colombier cache = c->flag & CCACHE; 662*8ccd4a63SDavid du Colombier if(c->qid.type & QTDIR) { 663*8ccd4a63SDavid du Colombier cache = 0; 664*8ccd4a63SDavid du Colombier isdir = 1; 665*8ccd4a63SDavid du Colombier } 666*8ccd4a63SDavid du Colombier 667*8ccd4a63SDavid du Colombier p = buf; 668*8ccd4a63SDavid du Colombier if(cache) { 669*8ccd4a63SDavid du Colombier nc = cread(c, buf, n, off); 670*8ccd4a63SDavid du Colombier if(nc > 0) { 671*8ccd4a63SDavid du Colombier n -= nc; 672*8ccd4a63SDavid du Colombier if(n == 0) 673*8ccd4a63SDavid du Colombier return nc; 674*8ccd4a63SDavid du Colombier p += nc; 675*8ccd4a63SDavid du Colombier off += nc; 676*8ccd4a63SDavid du Colombier } 677*8ccd4a63SDavid du Colombier n = mntrdwr(Tread, c, p, n, off); 678*8ccd4a63SDavid du Colombier cupdate(c, p, n, off); 679*8ccd4a63SDavid du Colombier return n + nc; 680*8ccd4a63SDavid du Colombier } 681*8ccd4a63SDavid du Colombier 682*8ccd4a63SDavid du Colombier n = mntrdwr(Tread, c, buf, n, off); 683*8ccd4a63SDavid du Colombier if(isdir) { 684*8ccd4a63SDavid du Colombier for(e = &p[n]; p+BIT16SZ < e; p += dirlen){ 685*8ccd4a63SDavid du Colombier dirlen = BIT16SZ+GBIT16(p); 686*8ccd4a63SDavid du Colombier if(p+dirlen > e) 687*8ccd4a63SDavid du Colombier break; 688*8ccd4a63SDavid du Colombier validstat(p, dirlen); 689*8ccd4a63SDavid du Colombier mntdirfix(p, c); 690*8ccd4a63SDavid du Colombier } 691*8ccd4a63SDavid du Colombier if(p != e) 692*8ccd4a63SDavid du Colombier error(Esbadstat); 693*8ccd4a63SDavid du Colombier } 694*8ccd4a63SDavid du Colombier return n; 695*8ccd4a63SDavid du Colombier } 696*8ccd4a63SDavid du Colombier 697*8ccd4a63SDavid du Colombier static long 698*8ccd4a63SDavid du Colombier mntwrite(Chan *c, void *buf, long n, vlong off) 699*8ccd4a63SDavid du Colombier { 700*8ccd4a63SDavid du Colombier return mntrdwr(Twrite, c, buf, n, off); 701*8ccd4a63SDavid du Colombier } 702*8ccd4a63SDavid du Colombier 703*8ccd4a63SDavid du Colombier long 704*8ccd4a63SDavid du Colombier mntrdwr(int type, Chan *c, void *buf, long n, vlong off) 705*8ccd4a63SDavid du Colombier { 706*8ccd4a63SDavid du Colombier Mnt *m; 707*8ccd4a63SDavid du Colombier Mntrpc *r; 708*8ccd4a63SDavid du Colombier char *uba; 709*8ccd4a63SDavid du Colombier int cache; 710*8ccd4a63SDavid du Colombier ulong cnt, nr, nreq; 711*8ccd4a63SDavid du Colombier 712*8ccd4a63SDavid du Colombier m = mntchk(c); 713*8ccd4a63SDavid du Colombier uba = buf; 714*8ccd4a63SDavid du Colombier cnt = 0; 715*8ccd4a63SDavid du Colombier cache = c->flag & CCACHE; 716*8ccd4a63SDavid du Colombier if(c->qid.type & QTDIR) 717*8ccd4a63SDavid du Colombier cache = 0; 718*8ccd4a63SDavid du Colombier for(;;) { 719*8ccd4a63SDavid du Colombier r = mntralloc(c, m->msize); 720*8ccd4a63SDavid du Colombier if(waserror()) { 721*8ccd4a63SDavid du Colombier mntfree(r); 722*8ccd4a63SDavid du Colombier nexterror(); 723*8ccd4a63SDavid du Colombier } 724*8ccd4a63SDavid du Colombier r->request.type = type; 725*8ccd4a63SDavid du Colombier r->request.fid = c->fid; 726*8ccd4a63SDavid du Colombier r->request.offset = off; 727*8ccd4a63SDavid du Colombier r->request.data = uba; 728*8ccd4a63SDavid du Colombier nr = n; 729*8ccd4a63SDavid du Colombier if(nr > m->msize-IOHDRSZ) 730*8ccd4a63SDavid du Colombier nr = m->msize-IOHDRSZ; 731*8ccd4a63SDavid du Colombier r->request.count = nr; 732*8ccd4a63SDavid du Colombier mountrpc(m, r); 733*8ccd4a63SDavid du Colombier nreq = r->request.count; 734*8ccd4a63SDavid du Colombier nr = r->reply.count; 735*8ccd4a63SDavid du Colombier if(nr > nreq) 736*8ccd4a63SDavid du Colombier nr = nreq; 737*8ccd4a63SDavid du Colombier 738*8ccd4a63SDavid du Colombier if(type == Tread) 739*8ccd4a63SDavid du Colombier r->b = bl2mem((uchar*)uba, r->b, nr); 740*8ccd4a63SDavid du Colombier else if(cache) 741*8ccd4a63SDavid du Colombier cwrite(c, (uchar*)uba, nr, off); 742*8ccd4a63SDavid du Colombier 743*8ccd4a63SDavid du Colombier poperror(); 744*8ccd4a63SDavid du Colombier mntfree(r); 745*8ccd4a63SDavid du Colombier off += nr; 746*8ccd4a63SDavid du Colombier uba += nr; 747*8ccd4a63SDavid du Colombier cnt += nr; 748*8ccd4a63SDavid du Colombier n -= nr; 749*8ccd4a63SDavid du Colombier if(nr != nreq || n == 0) 750*8ccd4a63SDavid du Colombier break; 751*8ccd4a63SDavid du Colombier } 752*8ccd4a63SDavid du Colombier return cnt; 753*8ccd4a63SDavid du Colombier } 754*8ccd4a63SDavid du Colombier 755*8ccd4a63SDavid du Colombier void 756*8ccd4a63SDavid du Colombier mountrpc(Mnt *m, Mntrpc *r) 757*8ccd4a63SDavid du Colombier { 758*8ccd4a63SDavid du Colombier char *sn, *cn; 759*8ccd4a63SDavid du Colombier int t; 760*8ccd4a63SDavid du Colombier 761*8ccd4a63SDavid du Colombier r->reply.tag = 0; 762*8ccd4a63SDavid du Colombier r->reply.type = Tmax; /* can't ever be a valid message type */ 763*8ccd4a63SDavid du Colombier 764*8ccd4a63SDavid du Colombier mountio(m, r); 765*8ccd4a63SDavid du Colombier 766*8ccd4a63SDavid du Colombier t = r->reply.type; 767*8ccd4a63SDavid du Colombier switch(t) { 768*8ccd4a63SDavid du Colombier case Rerror: 769*8ccd4a63SDavid du Colombier error(r->reply.ename); 770*8ccd4a63SDavid du Colombier case Rflush: 771*8ccd4a63SDavid du Colombier error(Eintr); 772*8ccd4a63SDavid du Colombier default: 773*8ccd4a63SDavid du Colombier if(t == r->request.type+1) 774*8ccd4a63SDavid du Colombier break; 775*8ccd4a63SDavid du Colombier sn = "?"; 776*8ccd4a63SDavid du Colombier if(m->c->name != nil) 777*8ccd4a63SDavid du Colombier sn = m->c->name->s; 778*8ccd4a63SDavid du Colombier cn = "?"; 779*8ccd4a63SDavid du Colombier if(r->c != nil && r->c->name != nil) 780*8ccd4a63SDavid du Colombier cn = r->c->name->s; 781*8ccd4a63SDavid du Colombier print("mnt: proc %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n", 782*8ccd4a63SDavid du Colombier up->pid, sn, cn, 783*8ccd4a63SDavid du Colombier r, r->request.tag, r->request.fid, r->request.type, 784*8ccd4a63SDavid du Colombier r->reply.type, r->reply.tag); 785*8ccd4a63SDavid du Colombier error(Emountrpc); 786*8ccd4a63SDavid du Colombier } 787*8ccd4a63SDavid du Colombier } 788*8ccd4a63SDavid du Colombier 789*8ccd4a63SDavid du Colombier void 790*8ccd4a63SDavid du Colombier mountio(Mnt *m, Mntrpc *r) 791*8ccd4a63SDavid du Colombier { 792*8ccd4a63SDavid du Colombier int n; 793*8ccd4a63SDavid du Colombier 794*8ccd4a63SDavid du Colombier while(waserror()) { 795*8ccd4a63SDavid du Colombier if(m->rip == up) 796*8ccd4a63SDavid du Colombier mntgate(m); 797*8ccd4a63SDavid du Colombier if(strcmp(up->errstr, Eintr) != 0){ 798*8ccd4a63SDavid du Colombier mntflushfree(m, r); 799*8ccd4a63SDavid du Colombier nexterror(); 800*8ccd4a63SDavid du Colombier } 801*8ccd4a63SDavid du Colombier r = mntflushalloc(r, m->msize); 802*8ccd4a63SDavid du Colombier } 803*8ccd4a63SDavid du Colombier 804*8ccd4a63SDavid du Colombier lock(&m->lk); 805*8ccd4a63SDavid du Colombier r->m = m; 806*8ccd4a63SDavid du Colombier r->list = m->queue; 807*8ccd4a63SDavid du Colombier m->queue = r; 808*8ccd4a63SDavid du Colombier unlock(&m->lk); 809*8ccd4a63SDavid du Colombier 810*8ccd4a63SDavid du Colombier /* Transmit a file system rpc */ 811*8ccd4a63SDavid du Colombier if(m->msize == 0) 812*8ccd4a63SDavid du Colombier panic("msize"); 813*8ccd4a63SDavid du Colombier n = convS2M(&r->request, r->rpc, m->msize); 814*8ccd4a63SDavid du Colombier if(n < 0) 815*8ccd4a63SDavid du Colombier panic("bad message type in mountio"); 816*8ccd4a63SDavid du Colombier if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n) 817*8ccd4a63SDavid du Colombier error(Emountrpc); 818*8ccd4a63SDavid du Colombier r->stime = fastticks(nil); 819*8ccd4a63SDavid du Colombier r->reqlen = n; 820*8ccd4a63SDavid du Colombier 821*8ccd4a63SDavid du Colombier /* Gate readers onto the mount point one at a time */ 822*8ccd4a63SDavid du Colombier for(;;) { 823*8ccd4a63SDavid du Colombier lock(&m->lk); 824*8ccd4a63SDavid du Colombier if(m->rip == 0) 825*8ccd4a63SDavid du Colombier break; 826*8ccd4a63SDavid du Colombier unlock(&m->lk); 827*8ccd4a63SDavid du Colombier sleep(&r->r, rpcattn, r); 828*8ccd4a63SDavid du Colombier if(r->done){ 829*8ccd4a63SDavid du Colombier poperror(); 830*8ccd4a63SDavid du Colombier mntflushfree(m, r); 831*8ccd4a63SDavid du Colombier return; 832*8ccd4a63SDavid du Colombier } 833*8ccd4a63SDavid du Colombier } 834*8ccd4a63SDavid du Colombier m->rip = up; 835*8ccd4a63SDavid du Colombier unlock(&m->lk); 836*8ccd4a63SDavid du Colombier while(r->done == 0) { 837*8ccd4a63SDavid du Colombier if(mntrpcread(m, r) < 0) 838*8ccd4a63SDavid du Colombier error(Emountrpc); 839*8ccd4a63SDavid du Colombier mountmux(m, r); 840*8ccd4a63SDavid du Colombier } 841*8ccd4a63SDavid du Colombier mntgate(m); 842*8ccd4a63SDavid du Colombier poperror(); 843*8ccd4a63SDavid du Colombier mntflushfree(m, r); 844*8ccd4a63SDavid du Colombier } 845*8ccd4a63SDavid du Colombier 846*8ccd4a63SDavid du Colombier static int 847*8ccd4a63SDavid du Colombier doread(Mnt *m, int len) 848*8ccd4a63SDavid du Colombier { 849*8ccd4a63SDavid du Colombier Block *b; 850*8ccd4a63SDavid du Colombier 851*8ccd4a63SDavid du Colombier while(qlen(m->q) < len){ 852*8ccd4a63SDavid du Colombier b = devtab[m->c->type]->bread(m->c, m->msize, 0); 853*8ccd4a63SDavid du Colombier if(b == nil) 854*8ccd4a63SDavid du Colombier return -1; 855*8ccd4a63SDavid du Colombier if(BLEN(b) == 0){ 856*8ccd4a63SDavid du Colombier freeblist(b); 857*8ccd4a63SDavid du Colombier return -1; 858*8ccd4a63SDavid du Colombier } 859*8ccd4a63SDavid du Colombier qaddlist(m->q, b); 860*8ccd4a63SDavid du Colombier } 861*8ccd4a63SDavid du Colombier return 0; 862*8ccd4a63SDavid du Colombier } 863*8ccd4a63SDavid du Colombier 864*8ccd4a63SDavid du Colombier int 865*8ccd4a63SDavid du Colombier mntrpcread(Mnt *m, Mntrpc *r) 866*8ccd4a63SDavid du Colombier { 867*8ccd4a63SDavid du Colombier int i, t, len, hlen; 868*8ccd4a63SDavid du Colombier Block *b, **l, *nb; 869*8ccd4a63SDavid du Colombier 870*8ccd4a63SDavid du Colombier r->reply.type = 0; 871*8ccd4a63SDavid du Colombier r->reply.tag = 0; 872*8ccd4a63SDavid du Colombier 873*8ccd4a63SDavid du Colombier /* read at least length, type, and tag and pullup to a single block */ 874*8ccd4a63SDavid du Colombier if(doread(m, BIT32SZ+BIT8SZ+BIT16SZ) < 0) 875*8ccd4a63SDavid du Colombier return -1; 876*8ccd4a63SDavid du Colombier nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ); 877*8ccd4a63SDavid du Colombier 878*8ccd4a63SDavid du Colombier /* read in the rest of the message, avoid rediculous (for now) message sizes */ 879*8ccd4a63SDavid du Colombier len = GBIT32(nb->rp); 880*8ccd4a63SDavid du Colombier if(len > m->msize){ 881*8ccd4a63SDavid du Colombier qdiscard(m->q, qlen(m->q)); 882*8ccd4a63SDavid du Colombier return -1; 883*8ccd4a63SDavid du Colombier } 884*8ccd4a63SDavid du Colombier if(doread(m, len) < 0) 885*8ccd4a63SDavid du Colombier return -1; 886*8ccd4a63SDavid du Colombier 887*8ccd4a63SDavid du Colombier /* pullup the header (i.e. everything except data) */ 888*8ccd4a63SDavid du Colombier t = nb->rp[BIT32SZ]; 889*8ccd4a63SDavid du Colombier switch(t){ 890*8ccd4a63SDavid du Colombier case Rread: 891*8ccd4a63SDavid du Colombier hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ; 892*8ccd4a63SDavid du Colombier break; 893*8ccd4a63SDavid du Colombier default: 894*8ccd4a63SDavid du Colombier hlen = len; 895*8ccd4a63SDavid du Colombier break; 896*8ccd4a63SDavid du Colombier } 897*8ccd4a63SDavid du Colombier nb = pullupqueue(m->q, hlen); 898*8ccd4a63SDavid du Colombier 899*8ccd4a63SDavid du Colombier if(convM2S(nb->rp, len, &r->reply) <= 0){ 900*8ccd4a63SDavid du Colombier /* bad message, dump it */ 901*8ccd4a63SDavid du Colombier print("mntrpcread: convM2S failed\n"); 902*8ccd4a63SDavid du Colombier qdiscard(m->q, len); 903*8ccd4a63SDavid du Colombier return -1; 904*8ccd4a63SDavid du Colombier } 905*8ccd4a63SDavid du Colombier 906*8ccd4a63SDavid du Colombier /* hang the data off of the fcall struct */ 907*8ccd4a63SDavid du Colombier l = &r->b; 908*8ccd4a63SDavid du Colombier *l = nil; 909*8ccd4a63SDavid du Colombier do { 910*8ccd4a63SDavid du Colombier b = qremove(m->q); 911*8ccd4a63SDavid du Colombier if(hlen > 0){ 912*8ccd4a63SDavid du Colombier b->rp += hlen; 913*8ccd4a63SDavid du Colombier len -= hlen; 914*8ccd4a63SDavid du Colombier hlen = 0; 915*8ccd4a63SDavid du Colombier } 916*8ccd4a63SDavid du Colombier i = BLEN(b); 917*8ccd4a63SDavid du Colombier if(i <= len){ 918*8ccd4a63SDavid du Colombier len -= i; 919*8ccd4a63SDavid du Colombier *l = b; 920*8ccd4a63SDavid du Colombier l = &(b->next); 921*8ccd4a63SDavid du Colombier } else { 922*8ccd4a63SDavid du Colombier /* split block and put unused bit back */ 923*8ccd4a63SDavid du Colombier nb = allocb(i-len); 924*8ccd4a63SDavid du Colombier memmove(nb->wp, b->rp+len, i-len); 925*8ccd4a63SDavid du Colombier b->wp = b->rp+len; 926*8ccd4a63SDavid du Colombier nb->wp += i-len; 927*8ccd4a63SDavid du Colombier qputback(m->q, nb); 928*8ccd4a63SDavid du Colombier *l = b; 929*8ccd4a63SDavid du Colombier return 0; 930*8ccd4a63SDavid du Colombier } 931*8ccd4a63SDavid du Colombier }while(len > 0); 932*8ccd4a63SDavid du Colombier 933*8ccd4a63SDavid du Colombier return 0; 934*8ccd4a63SDavid du Colombier } 935*8ccd4a63SDavid du Colombier 936*8ccd4a63SDavid du Colombier void 937*8ccd4a63SDavid du Colombier mntgate(Mnt *m) 938*8ccd4a63SDavid du Colombier { 939*8ccd4a63SDavid du Colombier Mntrpc *q; 940*8ccd4a63SDavid du Colombier 941*8ccd4a63SDavid du Colombier lock(&m->lk); 942*8ccd4a63SDavid du Colombier m->rip = 0; 943*8ccd4a63SDavid du Colombier for(q = m->queue; q; q = q->list) { 944*8ccd4a63SDavid du Colombier if(q->done == 0) 945*8ccd4a63SDavid du Colombier if(wakeup(&q->r)) 946*8ccd4a63SDavid du Colombier break; 947*8ccd4a63SDavid du Colombier } 948*8ccd4a63SDavid du Colombier unlock(&m->lk); 949*8ccd4a63SDavid du Colombier } 950*8ccd4a63SDavid du Colombier 951*8ccd4a63SDavid du Colombier void 952*8ccd4a63SDavid du Colombier mountmux(Mnt *m, Mntrpc *r) 953*8ccd4a63SDavid du Colombier { 954*8ccd4a63SDavid du Colombier Mntrpc **l, *q; 955*8ccd4a63SDavid du Colombier 956*8ccd4a63SDavid du Colombier lock(&m->lk); 957*8ccd4a63SDavid du Colombier l = &m->queue; 958*8ccd4a63SDavid du Colombier for(q = *l; q; q = q->list) { 959*8ccd4a63SDavid du Colombier /* look for a reply to a message */ 960*8ccd4a63SDavid du Colombier if(q->request.tag == r->reply.tag) { 961*8ccd4a63SDavid du Colombier *l = q->list; 962*8ccd4a63SDavid du Colombier if(q != r) { 963*8ccd4a63SDavid du Colombier /* 964*8ccd4a63SDavid du Colombier * Completed someone else. 965*8ccd4a63SDavid du Colombier * Trade pointers to receive buffer. 966*8ccd4a63SDavid du Colombier */ 967*8ccd4a63SDavid du Colombier q->reply = r->reply; 968*8ccd4a63SDavid du Colombier q->b = r->b; 969*8ccd4a63SDavid du Colombier r->b = nil; 970*8ccd4a63SDavid du Colombier } 971*8ccd4a63SDavid du Colombier q->done = 1; 972*8ccd4a63SDavid du Colombier unlock(&m->lk); 973*8ccd4a63SDavid du Colombier if(mntstats != nil) 974*8ccd4a63SDavid du Colombier (*mntstats)(q->request.type, 975*8ccd4a63SDavid du Colombier m->c, q->stime, 976*8ccd4a63SDavid du Colombier q->reqlen + r->replen); 977*8ccd4a63SDavid du Colombier if(q != r) 978*8ccd4a63SDavid du Colombier wakeup(&q->r); 979*8ccd4a63SDavid du Colombier return; 980*8ccd4a63SDavid du Colombier } 981*8ccd4a63SDavid du Colombier l = &q->list; 982*8ccd4a63SDavid du Colombier } 983*8ccd4a63SDavid du Colombier unlock(&m->lk); 984*8ccd4a63SDavid du Colombier print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type); 985*8ccd4a63SDavid du Colombier } 986*8ccd4a63SDavid du Colombier 987*8ccd4a63SDavid du Colombier /* 988*8ccd4a63SDavid du Colombier * Create a new flush request and chain the previous 989*8ccd4a63SDavid du Colombier * requests from it 990*8ccd4a63SDavid du Colombier */ 991*8ccd4a63SDavid du Colombier Mntrpc* 992*8ccd4a63SDavid du Colombier mntflushalloc(Mntrpc *r, ulong iounit) 993*8ccd4a63SDavid du Colombier { 994*8ccd4a63SDavid du Colombier Mntrpc *fr; 995*8ccd4a63SDavid du Colombier 996*8ccd4a63SDavid du Colombier fr = mntralloc(0, iounit); 997*8ccd4a63SDavid du Colombier 998*8ccd4a63SDavid du Colombier fr->request.type = Tflush; 999*8ccd4a63SDavid du Colombier if(r->request.type == Tflush) 1000*8ccd4a63SDavid du Colombier fr->request.oldtag = r->request.oldtag; 1001*8ccd4a63SDavid du Colombier else 1002*8ccd4a63SDavid du Colombier fr->request.oldtag = r->request.tag; 1003*8ccd4a63SDavid du Colombier fr->flushed = r; 1004*8ccd4a63SDavid du Colombier 1005*8ccd4a63SDavid du Colombier return fr; 1006*8ccd4a63SDavid du Colombier } 1007*8ccd4a63SDavid du Colombier 1008*8ccd4a63SDavid du Colombier /* 1009*8ccd4a63SDavid du Colombier * Free a chain of flushes. Remove each unanswered 1010*8ccd4a63SDavid du Colombier * flush and the original message from the unanswered 1011*8ccd4a63SDavid du Colombier * request queue. Mark the original message as done 1012*8ccd4a63SDavid du Colombier * and if it hasn't been answered set the reply to to 1013*8ccd4a63SDavid du Colombier * Rflush. 1014*8ccd4a63SDavid du Colombier */ 1015*8ccd4a63SDavid du Colombier void 1016*8ccd4a63SDavid du Colombier mntflushfree(Mnt *m, Mntrpc *r) 1017*8ccd4a63SDavid du Colombier { 1018*8ccd4a63SDavid du Colombier Mntrpc *fr; 1019*8ccd4a63SDavid du Colombier 1020*8ccd4a63SDavid du Colombier while(r){ 1021*8ccd4a63SDavid du Colombier fr = r->flushed; 1022*8ccd4a63SDavid du Colombier if(!r->done){ 1023*8ccd4a63SDavid du Colombier r->reply.type = Rflush; 1024*8ccd4a63SDavid du Colombier mntqrm(m, r); 1025*8ccd4a63SDavid du Colombier } 1026*8ccd4a63SDavid du Colombier if(fr) 1027*8ccd4a63SDavid du Colombier mntfree(r); 1028*8ccd4a63SDavid du Colombier r = fr; 1029*8ccd4a63SDavid du Colombier } 1030*8ccd4a63SDavid du Colombier } 1031*8ccd4a63SDavid du Colombier 1032*8ccd4a63SDavid du Colombier int 1033*8ccd4a63SDavid du Colombier alloctag(void) 1034*8ccd4a63SDavid du Colombier { 1035*8ccd4a63SDavid du Colombier int i, j; 1036*8ccd4a63SDavid du Colombier ulong v; 1037*8ccd4a63SDavid du Colombier 1038*8ccd4a63SDavid du Colombier for(i = 0; i < NMASK; i++){ 1039*8ccd4a63SDavid du Colombier v = mntalloc.tagmask[i]; 1040*8ccd4a63SDavid du Colombier if(v == ~0UL) 1041*8ccd4a63SDavid du Colombier continue; 1042*8ccd4a63SDavid du Colombier for(j = 0; j < 1<<TAGSHIFT; j++) 1043*8ccd4a63SDavid du Colombier if((v & (1<<j)) == 0){ 1044*8ccd4a63SDavid du Colombier mntalloc.tagmask[i] |= 1<<j; 1045*8ccd4a63SDavid du Colombier return (i<<TAGSHIFT) + j; 1046*8ccd4a63SDavid du Colombier } 1047*8ccd4a63SDavid du Colombier } 1048*8ccd4a63SDavid du Colombier panic("no friggin tags left"); 1049*8ccd4a63SDavid du Colombier return NOTAG; 1050*8ccd4a63SDavid du Colombier } 1051*8ccd4a63SDavid du Colombier 1052*8ccd4a63SDavid du Colombier void 1053*8ccd4a63SDavid du Colombier freetag(int t) 1054*8ccd4a63SDavid du Colombier { 1055*8ccd4a63SDavid du Colombier mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK)); 1056*8ccd4a63SDavid du Colombier } 1057*8ccd4a63SDavid du Colombier 1058*8ccd4a63SDavid du Colombier Mntrpc* 1059*8ccd4a63SDavid du Colombier mntralloc(Chan *c, ulong msize) 1060*8ccd4a63SDavid du Colombier { 1061*8ccd4a63SDavid du Colombier Mntrpc *new; 1062*8ccd4a63SDavid du Colombier 1063*8ccd4a63SDavid du Colombier lock(&mntalloc.lk); 1064*8ccd4a63SDavid du Colombier new = mntalloc.rpcfree; 1065*8ccd4a63SDavid du Colombier if(new == nil){ 1066*8ccd4a63SDavid du Colombier new = malloc(sizeof(Mntrpc)); 1067*8ccd4a63SDavid du Colombier if(new == nil) { 1068*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 1069*8ccd4a63SDavid du Colombier exhausted("mount rpc header"); 1070*8ccd4a63SDavid du Colombier } 1071*8ccd4a63SDavid du Colombier /* 1072*8ccd4a63SDavid du Colombier * The header is split from the data buffer as 1073*8ccd4a63SDavid du Colombier * mountmux may swap the buffer with another header. 1074*8ccd4a63SDavid du Colombier */ 1075*8ccd4a63SDavid du Colombier new->rpc = mallocz(msize, 0); 1076*8ccd4a63SDavid du Colombier if(new->rpc == nil){ 1077*8ccd4a63SDavid du Colombier free(new); 1078*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 1079*8ccd4a63SDavid du Colombier exhausted("mount rpc buffer"); 1080*8ccd4a63SDavid du Colombier } 1081*8ccd4a63SDavid du Colombier new->rpclen = msize; 1082*8ccd4a63SDavid du Colombier new->request.tag = alloctag(); 1083*8ccd4a63SDavid du Colombier } 1084*8ccd4a63SDavid du Colombier else { 1085*8ccd4a63SDavid du Colombier mntalloc.rpcfree = new->list; 1086*8ccd4a63SDavid du Colombier mntalloc.nrpcfree--; 1087*8ccd4a63SDavid du Colombier if(new->rpclen < msize){ 1088*8ccd4a63SDavid du Colombier free(new->rpc); 1089*8ccd4a63SDavid du Colombier new->rpc = mallocz(msize, 0); 1090*8ccd4a63SDavid du Colombier if(new->rpc == nil){ 1091*8ccd4a63SDavid du Colombier free(new); 1092*8ccd4a63SDavid du Colombier mntalloc.nrpcused--; 1093*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 1094*8ccd4a63SDavid du Colombier exhausted("mount rpc buffer"); 1095*8ccd4a63SDavid du Colombier } 1096*8ccd4a63SDavid du Colombier new->rpclen = msize; 1097*8ccd4a63SDavid du Colombier } 1098*8ccd4a63SDavid du Colombier } 1099*8ccd4a63SDavid du Colombier mntalloc.nrpcused++; 1100*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 1101*8ccd4a63SDavid du Colombier new->c = c; 1102*8ccd4a63SDavid du Colombier new->done = 0; 1103*8ccd4a63SDavid du Colombier new->flushed = nil; 1104*8ccd4a63SDavid du Colombier new->b = nil; 1105*8ccd4a63SDavid du Colombier return new; 1106*8ccd4a63SDavid du Colombier } 1107*8ccd4a63SDavid du Colombier 1108*8ccd4a63SDavid du Colombier void 1109*8ccd4a63SDavid du Colombier mntfree(Mntrpc *r) 1110*8ccd4a63SDavid du Colombier { 1111*8ccd4a63SDavid du Colombier if(r->b != nil) 1112*8ccd4a63SDavid du Colombier freeblist(r->b); 1113*8ccd4a63SDavid du Colombier lock(&mntalloc.lk); 1114*8ccd4a63SDavid du Colombier if(mntalloc.nrpcfree >= 10){ 1115*8ccd4a63SDavid du Colombier free(r->rpc); 1116*8ccd4a63SDavid du Colombier free(r); 1117*8ccd4a63SDavid du Colombier freetag(r->request.tag); 1118*8ccd4a63SDavid du Colombier } 1119*8ccd4a63SDavid du Colombier else{ 1120*8ccd4a63SDavid du Colombier r->list = mntalloc.rpcfree; 1121*8ccd4a63SDavid du Colombier mntalloc.rpcfree = r; 1122*8ccd4a63SDavid du Colombier mntalloc.nrpcfree++; 1123*8ccd4a63SDavid du Colombier } 1124*8ccd4a63SDavid du Colombier mntalloc.nrpcused--; 1125*8ccd4a63SDavid du Colombier unlock(&mntalloc.lk); 1126*8ccd4a63SDavid du Colombier } 1127*8ccd4a63SDavid du Colombier 1128*8ccd4a63SDavid du Colombier void 1129*8ccd4a63SDavid du Colombier mntqrm(Mnt *m, Mntrpc *r) 1130*8ccd4a63SDavid du Colombier { 1131*8ccd4a63SDavid du Colombier Mntrpc **l, *f; 1132*8ccd4a63SDavid du Colombier 1133*8ccd4a63SDavid du Colombier lock(&m->lk); 1134*8ccd4a63SDavid du Colombier r->done = 1; 1135*8ccd4a63SDavid du Colombier 1136*8ccd4a63SDavid du Colombier l = &m->queue; 1137*8ccd4a63SDavid du Colombier for(f = *l; f; f = f->list) { 1138*8ccd4a63SDavid du Colombier if(f == r) { 1139*8ccd4a63SDavid du Colombier *l = r->list; 1140*8ccd4a63SDavid du Colombier break; 1141*8ccd4a63SDavid du Colombier } 1142*8ccd4a63SDavid du Colombier l = &f->list; 1143*8ccd4a63SDavid du Colombier } 1144*8ccd4a63SDavid du Colombier unlock(&m->lk); 1145*8ccd4a63SDavid du Colombier } 1146*8ccd4a63SDavid du Colombier 1147*8ccd4a63SDavid du Colombier Mnt* 1148*8ccd4a63SDavid du Colombier mntchk(Chan *c) 1149*8ccd4a63SDavid du Colombier { 1150*8ccd4a63SDavid du Colombier Mnt *m; 1151*8ccd4a63SDavid du Colombier 1152*8ccd4a63SDavid du Colombier /* This routine is mostly vestiges of prior lives; now it's just sanity checking */ 1153*8ccd4a63SDavid du Colombier 1154*8ccd4a63SDavid du Colombier if(c->mchan == nil) 1155*8ccd4a63SDavid du Colombier panic("mntchk 1: nil mchan c %s\n", c2name(c)); 1156*8ccd4a63SDavid du Colombier 1157*8ccd4a63SDavid du Colombier m = c->mchan->mux; 1158*8ccd4a63SDavid du Colombier 1159*8ccd4a63SDavid du Colombier if(m == nil) 1160*8ccd4a63SDavid du Colombier print("mntchk 2: nil mux c %s c->mchan %s \n", c2name(c), c2name(c->mchan)); 1161*8ccd4a63SDavid du Colombier 1162*8ccd4a63SDavid du Colombier /* 1163*8ccd4a63SDavid du Colombier * Was it closed and reused (was error(Eshutdown); now, it can't happen) 1164*8ccd4a63SDavid du Colombier */ 1165*8ccd4a63SDavid du Colombier if(m->id == 0 || m->id >= c->dev) 1166*8ccd4a63SDavid du Colombier panic("mntchk 3: can't happen"); 1167*8ccd4a63SDavid du Colombier 1168*8ccd4a63SDavid du Colombier return m; 1169*8ccd4a63SDavid du Colombier } 1170*8ccd4a63SDavid du Colombier 1171*8ccd4a63SDavid du Colombier /* 1172*8ccd4a63SDavid du Colombier * Rewrite channel type and dev for in-flight data to 1173*8ccd4a63SDavid du Colombier * reflect local values. These entries are known to be 1174*8ccd4a63SDavid du Colombier * the first two in the Dir encoding after the count. 1175*8ccd4a63SDavid du Colombier */ 1176*8ccd4a63SDavid du Colombier void 1177*8ccd4a63SDavid du Colombier mntdirfix(uchar *dirbuf, Chan *c) 1178*8ccd4a63SDavid du Colombier { 1179*8ccd4a63SDavid du Colombier uint r; 1180*8ccd4a63SDavid du Colombier 1181*8ccd4a63SDavid du Colombier r = devtab[c->type]->dc; 1182*8ccd4a63SDavid du Colombier dirbuf += BIT16SZ; /* skip count */ 1183*8ccd4a63SDavid du Colombier PBIT16(dirbuf, r); 1184*8ccd4a63SDavid du Colombier dirbuf += BIT16SZ; 1185*8ccd4a63SDavid du Colombier PBIT32(dirbuf, c->dev); 1186*8ccd4a63SDavid du Colombier } 1187*8ccd4a63SDavid du Colombier 1188*8ccd4a63SDavid du Colombier int 1189*8ccd4a63SDavid du Colombier rpcattn(void *v) 1190*8ccd4a63SDavid du Colombier { 1191*8ccd4a63SDavid du Colombier Mntrpc *r; 1192*8ccd4a63SDavid du Colombier 1193*8ccd4a63SDavid du Colombier r = v; 1194*8ccd4a63SDavid du Colombier return r->done || r->m->rip == 0; 1195*8ccd4a63SDavid du Colombier } 1196*8ccd4a63SDavid du Colombier 1197*8ccd4a63SDavid du Colombier Dev mntdevtab = { 1198*8ccd4a63SDavid du Colombier 'M', 1199*8ccd4a63SDavid du Colombier "mnt", 1200*8ccd4a63SDavid du Colombier 1201*8ccd4a63SDavid du Colombier mntreset, 1202*8ccd4a63SDavid du Colombier devinit, 1203*8ccd4a63SDavid du Colombier devshutdown, 1204*8ccd4a63SDavid du Colombier mntattach, 1205*8ccd4a63SDavid du Colombier mntwalk, 1206*8ccd4a63SDavid du Colombier mntstat, 1207*8ccd4a63SDavid du Colombier mntopen, 1208*8ccd4a63SDavid du Colombier mntcreate, 1209*8ccd4a63SDavid du Colombier mntclose, 1210*8ccd4a63SDavid du Colombier mntread, 1211*8ccd4a63SDavid du Colombier devbread, 1212*8ccd4a63SDavid du Colombier mntwrite, 1213*8ccd4a63SDavid du Colombier devbwrite, 1214*8ccd4a63SDavid du Colombier mntremove, 1215*8ccd4a63SDavid du Colombier mntwstat, 1216*8ccd4a63SDavid du Colombier }; 1217