19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier /*
99ef1f84bSDavid du Colombier * References are managed as follows:
109ef1f84bSDavid du Colombier * The channel to the server - a network connection or pipe - has one
119ef1f84bSDavid du Colombier * reference for every Chan open on the server. The server channel has
129ef1f84bSDavid du Colombier * c->mux set to the Mnt used for muxing control to that server. Mnts
139ef1f84bSDavid du Colombier * have no reference count; they go away when c goes away.
149ef1f84bSDavid du Colombier * Each channel derived from the mount point has mchan set to c,
159ef1f84bSDavid du Colombier * and increfs/decrefs mchan to manage references on the server
169ef1f84bSDavid du Colombier * connection.
179ef1f84bSDavid du Colombier */
189ef1f84bSDavid du Colombier
19*3ecb1704SDavid du Colombier #define MAXRPC (IOHDRSZ+16*1024) /* maybe a larger size will be faster */
20*3ecb1704SDavid du Colombier /* use a known-good common size for initial negotiation */
21*3ecb1704SDavid du Colombier #define MAXCMNRPC (IOHDRSZ+8192)
229ef1f84bSDavid du Colombier
239ef1f84bSDavid du Colombier struct Mntrpc
249ef1f84bSDavid du Colombier {
259ef1f84bSDavid du Colombier Chan* c; /* Channel for whom we are working */
269ef1f84bSDavid du Colombier Mntrpc* list; /* Free/pending list */
279ef1f84bSDavid du Colombier Fcall request; /* Outgoing file system protocol message */
289ef1f84bSDavid du Colombier Fcall reply; /* Incoming reply */
299ef1f84bSDavid du Colombier Mnt* m; /* Mount device during rpc */
309ef1f84bSDavid du Colombier Rendez r; /* Place to hang out */
319ef1f84bSDavid du Colombier uchar* rpc; /* I/O Data buffer */
329ef1f84bSDavid du Colombier uint rpclen; /* len of buffer */
339ef1f84bSDavid du Colombier Block *b; /* reply blocks */
349ef1f84bSDavid du Colombier char done; /* Rpc completed */
359ef1f84bSDavid du Colombier uvlong stime; /* start time for mnt statistics */
369ef1f84bSDavid du Colombier ulong reqlen; /* request length for mnt statistics */
379ef1f84bSDavid du Colombier ulong replen; /* reply length for mnt statistics */
389ef1f84bSDavid du Colombier Mntrpc* flushed; /* message this one flushes */
399ef1f84bSDavid du Colombier };
409ef1f84bSDavid du Colombier
419ef1f84bSDavid du Colombier enum
429ef1f84bSDavid du Colombier {
439ef1f84bSDavid du Colombier TAGSHIFT = 5, /* ulong has to be 32 bits */
449ef1f84bSDavid du Colombier TAGMASK = (1<<TAGSHIFT)-1,
459ef1f84bSDavid du Colombier NMASK = (64*1024)>>TAGSHIFT,
469ef1f84bSDavid du Colombier };
479ef1f84bSDavid du Colombier
489ef1f84bSDavid du Colombier struct Mntalloc
499ef1f84bSDavid du Colombier {
509ef1f84bSDavid du Colombier Lock;
519ef1f84bSDavid du Colombier Mnt* list; /* Mount devices in use */
529ef1f84bSDavid du Colombier Mnt* mntfree; /* Free list */
539ef1f84bSDavid du Colombier Mntrpc* rpcfree;
549ef1f84bSDavid du Colombier int nrpcfree;
559ef1f84bSDavid du Colombier int nrpcused;
569ef1f84bSDavid du Colombier uint id;
579ef1f84bSDavid du Colombier ulong tagmask[NMASK];
589ef1f84bSDavid du Colombier }mntalloc;
599ef1f84bSDavid du Colombier
609ef1f84bSDavid du Colombier Mnt* mntchk(Chan*);
619ef1f84bSDavid du Colombier void mntdirfix(uchar*, Chan*);
629ef1f84bSDavid du Colombier Mntrpc* mntflushalloc(Mntrpc*, ulong);
639ef1f84bSDavid du Colombier void mntflushfree(Mnt*, Mntrpc*);
649ef1f84bSDavid du Colombier void mntfree(Mntrpc*);
659ef1f84bSDavid du Colombier void mntgate(Mnt*);
669ef1f84bSDavid du Colombier void mntpntfree(Mnt*);
679ef1f84bSDavid du Colombier void mntqrm(Mnt*, Mntrpc*);
689ef1f84bSDavid du Colombier Mntrpc* mntralloc(Chan*, ulong);
699ef1f84bSDavid du Colombier long mntrdwr(int, Chan*, void*, long, vlong);
709ef1f84bSDavid du Colombier int mntrpcread(Mnt*, Mntrpc*);
719ef1f84bSDavid du Colombier void mountio(Mnt*, Mntrpc*);
729ef1f84bSDavid du Colombier void mountmux(Mnt*, Mntrpc*);
739ef1f84bSDavid du Colombier void mountrpc(Mnt*, Mntrpc*);
749ef1f84bSDavid du Colombier int rpcattn(void*);
759ef1f84bSDavid du Colombier Chan* mntchan(void);
769ef1f84bSDavid du Colombier
779ef1f84bSDavid du Colombier char Esbadstat[] = "invalid directory entry received from server";
789ef1f84bSDavid du Colombier char Enoversion[] = "version not established for mount channel";
799ef1f84bSDavid du Colombier
809ef1f84bSDavid du Colombier
819ef1f84bSDavid du Colombier void (*mntstats)(int, Chan*, uvlong, ulong);
829ef1f84bSDavid du Colombier
839ef1f84bSDavid du Colombier static void
mntreset(void)849ef1f84bSDavid du Colombier mntreset(void)
859ef1f84bSDavid du Colombier {
869ef1f84bSDavid du Colombier mntalloc.id = 1;
879ef1f84bSDavid du Colombier mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */
889ef1f84bSDavid du Colombier mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */
899ef1f84bSDavid du Colombier fmtinstall('F', fcallfmt);
909ef1f84bSDavid du Colombier fmtinstall('D', dirfmt);
919ef1f84bSDavid du Colombier /* We can't install %M since eipfmt does and is used in the kernel [sape] */
929ef1f84bSDavid du Colombier
939ef1f84bSDavid du Colombier cinit();
949ef1f84bSDavid du Colombier }
959ef1f84bSDavid du Colombier
969ef1f84bSDavid du Colombier /*
979ef1f84bSDavid du Colombier * Version is not multiplexed: message sent only once per connection.
989ef1f84bSDavid du Colombier */
999ef1f84bSDavid du Colombier usize
mntversion(Chan * c,u32int msize,char * version,usize returnlen)1009ef1f84bSDavid du Colombier mntversion(Chan *c, u32int msize, char *version, usize returnlen)
1019ef1f84bSDavid du Colombier {
1029ef1f84bSDavid du Colombier Fcall f;
1039ef1f84bSDavid du Colombier uchar *msg;
1049ef1f84bSDavid du Colombier Mnt *mnt;
1059ef1f84bSDavid du Colombier char *v;
1069ef1f84bSDavid du Colombier long l, n;
1079ef1f84bSDavid du Colombier usize k;
1089ef1f84bSDavid du Colombier vlong oo;
1099ef1f84bSDavid du Colombier char buf[128];
1109ef1f84bSDavid du Colombier
1119ef1f84bSDavid du Colombier qlock(&c->umqlock); /* make sure no one else does this until we've established ourselves */
1129ef1f84bSDavid du Colombier if(waserror()){
1139ef1f84bSDavid du Colombier qunlock(&c->umqlock);
1149ef1f84bSDavid du Colombier nexterror();
1159ef1f84bSDavid du Colombier }
1169ef1f84bSDavid du Colombier
1179ef1f84bSDavid du Colombier /* defaults */
1189ef1f84bSDavid du Colombier if(msize == 0)
1199ef1f84bSDavid du Colombier msize = MAXRPC;
1209ef1f84bSDavid du Colombier if(msize > c->iounit && c->iounit != 0)
1219ef1f84bSDavid du Colombier msize = c->iounit;
1229ef1f84bSDavid du Colombier v = version;
1239ef1f84bSDavid du Colombier if(v == nil || v[0] == '\0')
1249ef1f84bSDavid du Colombier v = VERSION9P;
1259ef1f84bSDavid du Colombier
1269ef1f84bSDavid du Colombier ///* validity */
1279ef1f84bSDavid du Colombier //if(msize < 0) pointless if msize unsigned, but but should it be?
1289ef1f84bSDavid du Colombier // error("bad iounit in version call");
1299ef1f84bSDavid du Colombier if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0)
1309ef1f84bSDavid du Colombier error("bad 9P version specification");
1319ef1f84bSDavid du Colombier
1329ef1f84bSDavid du Colombier mnt = c->mux;
1339ef1f84bSDavid du Colombier
1349ef1f84bSDavid du Colombier if(mnt != nil){
1359ef1f84bSDavid du Colombier qunlock(&c->umqlock);
1369ef1f84bSDavid du Colombier poperror();
1379ef1f84bSDavid du Colombier
1389ef1f84bSDavid du Colombier strecpy(buf, buf+sizeof buf, mnt->version);
1399ef1f84bSDavid du Colombier k = strlen(buf);
1409ef1f84bSDavid du Colombier if(strncmp(buf, v, k) != 0){
1419ef1f84bSDavid du Colombier snprint(buf, sizeof buf, "incompatible 9P versions %s %s", mnt->version, v);
1429ef1f84bSDavid du Colombier error(buf);
1439ef1f84bSDavid du Colombier }
1449ef1f84bSDavid du Colombier if(returnlen != 0){
1459ef1f84bSDavid du Colombier if(returnlen < k)
1469ef1f84bSDavid du Colombier error(Eshort);
1479ef1f84bSDavid du Colombier memmove(version, buf, k);
1489ef1f84bSDavid du Colombier }
1499ef1f84bSDavid du Colombier return k;
1509ef1f84bSDavid du Colombier }
1519ef1f84bSDavid du Colombier
1529ef1f84bSDavid du Colombier f.type = Tversion;
1539ef1f84bSDavid du Colombier f.tag = NOTAG;
1549ef1f84bSDavid du Colombier f.msize = msize;
1559ef1f84bSDavid du Colombier f.version = v;
156*3ecb1704SDavid du Colombier msg = malloc(MAXCMNRPC);
1579ef1f84bSDavid du Colombier if(msg == nil)
1589ef1f84bSDavid du Colombier exhausted("version memory");
1599ef1f84bSDavid du Colombier if(waserror()){
1609ef1f84bSDavid du Colombier free(msg);
1619ef1f84bSDavid du Colombier nexterror();
1629ef1f84bSDavid du Colombier }
163*3ecb1704SDavid du Colombier k = convS2M(&f, msg, MAXCMNRPC);
1649ef1f84bSDavid du Colombier if(k == 0)
1659ef1f84bSDavid du Colombier error("bad fversion conversion on send");
1669ef1f84bSDavid du Colombier
1679ef1f84bSDavid du Colombier lock(c);
1689ef1f84bSDavid du Colombier oo = c->offset;
1699ef1f84bSDavid du Colombier c->offset += k;
1709ef1f84bSDavid du Colombier unlock(c);
1719ef1f84bSDavid du Colombier
1729ef1f84bSDavid du Colombier l = c->dev->write(c, msg, k, oo);
1739ef1f84bSDavid du Colombier
1749ef1f84bSDavid du Colombier if(l < k){
1759ef1f84bSDavid du Colombier lock(c);
1769ef1f84bSDavid du Colombier c->offset -= k - l;
1779ef1f84bSDavid du Colombier unlock(c);
1789ef1f84bSDavid du Colombier error("short write in fversion");
1799ef1f84bSDavid du Colombier }
1809ef1f84bSDavid du Colombier
1819ef1f84bSDavid du Colombier /* message sent; receive and decode reply */
182*3ecb1704SDavid du Colombier n = c->dev->read(c, msg, MAXCMNRPC, c->offset);
1839ef1f84bSDavid du Colombier if(n <= 0)
1849ef1f84bSDavid du Colombier error("EOF receiving fversion reply");
1859ef1f84bSDavid du Colombier
1869ef1f84bSDavid du Colombier lock(c);
1879ef1f84bSDavid du Colombier c->offset += n;
1889ef1f84bSDavid du Colombier unlock(c);
1899ef1f84bSDavid du Colombier
1909ef1f84bSDavid du Colombier l = convM2S(msg, n, &f);
1919ef1f84bSDavid du Colombier if(l != n)
1929ef1f84bSDavid du Colombier error("bad fversion conversion on reply");
1939ef1f84bSDavid du Colombier if(f.type != Rversion){
1949ef1f84bSDavid du Colombier if(f.type == Rerror)
1959ef1f84bSDavid du Colombier error(f.ename);
1969ef1f84bSDavid du Colombier error("unexpected reply type in fversion");
1979ef1f84bSDavid du Colombier }
1989ef1f84bSDavid du Colombier if(f.msize > msize)
1999ef1f84bSDavid du Colombier error("server tries to increase msize in fversion");
2009ef1f84bSDavid du Colombier if(f.msize<256 || f.msize>1024*1024)
2019ef1f84bSDavid du Colombier error("nonsense value of msize in fversion");
2029ef1f84bSDavid du Colombier k = strlen(f.version);
2039ef1f84bSDavid du Colombier if(strncmp(f.version, v, k) != 0)
2049ef1f84bSDavid du Colombier error("bad 9P version returned from server");
2059ef1f84bSDavid du Colombier
2069ef1f84bSDavid du Colombier /* now build Mnt associated with this connection */
2079ef1f84bSDavid du Colombier lock(&mntalloc);
2089ef1f84bSDavid du Colombier mnt = mntalloc.mntfree;
2099ef1f84bSDavid du Colombier if(mnt != nil)
2109ef1f84bSDavid du Colombier mntalloc.mntfree = mnt->list;
2119ef1f84bSDavid du Colombier else {
2129ef1f84bSDavid du Colombier mnt = malloc(sizeof(Mnt));
2139ef1f84bSDavid du Colombier if(mnt == nil) {
2149ef1f84bSDavid du Colombier unlock(&mntalloc);
2159ef1f84bSDavid du Colombier exhausted("mount devices");
2169ef1f84bSDavid du Colombier }
2179ef1f84bSDavid du Colombier }
2189ef1f84bSDavid du Colombier mnt->list = mntalloc.list;
2199ef1f84bSDavid du Colombier mntalloc.list = mnt;
2209ef1f84bSDavid du Colombier mnt->version = nil;
2219ef1f84bSDavid du Colombier kstrdup(&mnt->version, f.version);
2229ef1f84bSDavid du Colombier mnt->id = mntalloc.id++;
2239ef1f84bSDavid du Colombier mnt->q = qopen(10*MAXRPC, 0, nil, nil);
2249ef1f84bSDavid du Colombier mnt->msize = f.msize;
2259ef1f84bSDavid du Colombier unlock(&mntalloc);
2269ef1f84bSDavid du Colombier
2279ef1f84bSDavid du Colombier if(returnlen != 0){
2289ef1f84bSDavid du Colombier if(returnlen < k)
2299ef1f84bSDavid du Colombier error(Eshort);
2309ef1f84bSDavid du Colombier memmove(version, f.version, k);
2319ef1f84bSDavid du Colombier }
2329ef1f84bSDavid du Colombier
2339ef1f84bSDavid du Colombier poperror(); /* msg */
2349ef1f84bSDavid du Colombier free(msg);
2359ef1f84bSDavid du Colombier
2369ef1f84bSDavid du Colombier lock(mnt);
2379ef1f84bSDavid du Colombier mnt->queue = 0;
2389ef1f84bSDavid du Colombier mnt->rip = 0;
2399ef1f84bSDavid du Colombier
2409ef1f84bSDavid du Colombier c->flag |= CMSG;
2419ef1f84bSDavid du Colombier c->mux = mnt;
2429ef1f84bSDavid du Colombier mnt->c = c;
2439ef1f84bSDavid du Colombier unlock(mnt);
2449ef1f84bSDavid du Colombier
2459ef1f84bSDavid du Colombier poperror(); /* c */
2469ef1f84bSDavid du Colombier qunlock(&c->umqlock);
2479ef1f84bSDavid du Colombier
2489ef1f84bSDavid du Colombier return k;
2499ef1f84bSDavid du Colombier }
2509ef1f84bSDavid du Colombier
2519ef1f84bSDavid du Colombier Chan*
mntauth(Chan * c,char * spec)2529ef1f84bSDavid du Colombier mntauth(Chan *c, char *spec)
2539ef1f84bSDavid du Colombier {
2549ef1f84bSDavid du Colombier Mnt *mnt;
2559ef1f84bSDavid du Colombier Mntrpc *r;
2569ef1f84bSDavid du Colombier
2579ef1f84bSDavid du Colombier mnt = c->mux;
2589ef1f84bSDavid du Colombier
2599ef1f84bSDavid du Colombier if(mnt == nil){
2609ef1f84bSDavid du Colombier mntversion(c, MAXRPC, VERSION9P, 0);
2619ef1f84bSDavid du Colombier mnt = c->mux;
2629ef1f84bSDavid du Colombier if(mnt == nil)
2639ef1f84bSDavid du Colombier error(Enoversion);
2649ef1f84bSDavid du Colombier }
2659ef1f84bSDavid du Colombier
2669ef1f84bSDavid du Colombier c = mntchan();
2679ef1f84bSDavid du Colombier if(waserror()) {
2689ef1f84bSDavid du Colombier /* Close must not be called since it will
2699ef1f84bSDavid du Colombier * call mnt recursively
2709ef1f84bSDavid du Colombier */
2719ef1f84bSDavid du Colombier chanfree(c);
2729ef1f84bSDavid du Colombier nexterror();
2739ef1f84bSDavid du Colombier }
2749ef1f84bSDavid du Colombier
2759ef1f84bSDavid du Colombier r = mntralloc(0, mnt->msize);
2769ef1f84bSDavid du Colombier
2779ef1f84bSDavid du Colombier if(waserror()) {
2789ef1f84bSDavid du Colombier mntfree(r);
2799ef1f84bSDavid du Colombier nexterror();
2809ef1f84bSDavid du Colombier }
2819ef1f84bSDavid du Colombier
2829ef1f84bSDavid du Colombier r->request.type = Tauth;
2839ef1f84bSDavid du Colombier r->request.afid = c->fid;
2849ef1f84bSDavid du Colombier r->request.uname = up->user;
2859ef1f84bSDavid du Colombier r->request.aname = spec;
2869ef1f84bSDavid du Colombier mountrpc(mnt, r);
2879ef1f84bSDavid du Colombier
2889ef1f84bSDavid du Colombier c->qid = r->reply.aqid;
2899ef1f84bSDavid du Colombier c->mchan = mnt->c;
2909ef1f84bSDavid du Colombier incref(mnt->c);
2919ef1f84bSDavid du Colombier c->mqid = c->qid;
2929ef1f84bSDavid du Colombier c->mode = ORDWR;
2939ef1f84bSDavid du Colombier
2949ef1f84bSDavid du Colombier poperror(); /* r */
2959ef1f84bSDavid du Colombier mntfree(r);
2969ef1f84bSDavid du Colombier
2979ef1f84bSDavid du Colombier poperror(); /* c */
2989ef1f84bSDavid du Colombier
2999ef1f84bSDavid du Colombier return c;
3009ef1f84bSDavid du Colombier
3019ef1f84bSDavid du Colombier }
3029ef1f84bSDavid du Colombier
3039ef1f84bSDavid du Colombier static Chan*
mntattach(char * muxattach)3049ef1f84bSDavid du Colombier mntattach(char *muxattach)
3059ef1f84bSDavid du Colombier {
3069ef1f84bSDavid du Colombier Mnt *mnt;
3079ef1f84bSDavid du Colombier Chan *c;
3089ef1f84bSDavid du Colombier Mntrpc *r;
3099ef1f84bSDavid du Colombier struct bogus{
3109ef1f84bSDavid du Colombier Chan *chan;
3119ef1f84bSDavid du Colombier Chan *authchan;
3129ef1f84bSDavid du Colombier char *spec;
3139ef1f84bSDavid du Colombier int flags;
3149ef1f84bSDavid du Colombier }bogus;
3159ef1f84bSDavid du Colombier
3169ef1f84bSDavid du Colombier bogus = *((struct bogus *)muxattach);
3179ef1f84bSDavid du Colombier c = bogus.chan;
3189ef1f84bSDavid du Colombier
3199ef1f84bSDavid du Colombier mnt = c->mux;
3209ef1f84bSDavid du Colombier
3219ef1f84bSDavid du Colombier if(mnt == nil){
3229ef1f84bSDavid du Colombier mntversion(c, 0, nil, 0);
3239ef1f84bSDavid du Colombier mnt = c->mux;
3249ef1f84bSDavid du Colombier if(mnt == nil)
3259ef1f84bSDavid du Colombier error(Enoversion);
3269ef1f84bSDavid du Colombier }
3279ef1f84bSDavid du Colombier
3289ef1f84bSDavid du Colombier c = mntchan();
3299ef1f84bSDavid du Colombier if(waserror()) {
3309ef1f84bSDavid du Colombier /* Close must not be called since it will
3319ef1f84bSDavid du Colombier * call mnt recursively
3329ef1f84bSDavid du Colombier */
3339ef1f84bSDavid du Colombier chanfree(c);
3349ef1f84bSDavid du Colombier nexterror();
3359ef1f84bSDavid du Colombier }
3369ef1f84bSDavid du Colombier
3379ef1f84bSDavid du Colombier r = mntralloc(0, mnt->msize);
3389ef1f84bSDavid du Colombier
3399ef1f84bSDavid du Colombier if(waserror()) {
3409ef1f84bSDavid du Colombier mntfree(r);
3419ef1f84bSDavid du Colombier nexterror();
3429ef1f84bSDavid du Colombier }
3439ef1f84bSDavid du Colombier
3449ef1f84bSDavid du Colombier r->request.type = Tattach;
3459ef1f84bSDavid du Colombier r->request.fid = c->fid;
3469ef1f84bSDavid du Colombier if(bogus.authchan == nil)
3479ef1f84bSDavid du Colombier r->request.afid = NOFID;
3489ef1f84bSDavid du Colombier else
3499ef1f84bSDavid du Colombier r->request.afid = bogus.authchan->fid;
3509ef1f84bSDavid du Colombier r->request.uname = up->user;
3519ef1f84bSDavid du Colombier r->request.aname = bogus.spec;
3529ef1f84bSDavid du Colombier mountrpc(mnt, r);
3539ef1f84bSDavid du Colombier
3549ef1f84bSDavid du Colombier c->qid = r->reply.qid;
3559ef1f84bSDavid du Colombier c->mchan = mnt->c;
3569ef1f84bSDavid du Colombier incref(mnt->c);
3579ef1f84bSDavid du Colombier c->mqid = c->qid;
3589ef1f84bSDavid du Colombier
3599ef1f84bSDavid du Colombier poperror(); /* r */
3609ef1f84bSDavid du Colombier mntfree(r);
3619ef1f84bSDavid du Colombier
3629ef1f84bSDavid du Colombier poperror(); /* c */
3639ef1f84bSDavid du Colombier
3649ef1f84bSDavid du Colombier if(bogus.flags & MCACHE)
3659ef1f84bSDavid du Colombier c->flag |= CCACHE;
3669ef1f84bSDavid du Colombier return c;
3679ef1f84bSDavid du Colombier }
3689ef1f84bSDavid du Colombier
3699ef1f84bSDavid du Colombier Chan*
mntchan(void)3709ef1f84bSDavid du Colombier mntchan(void)
3719ef1f84bSDavid du Colombier {
3729ef1f84bSDavid du Colombier Chan *c;
3739ef1f84bSDavid du Colombier
3749ef1f84bSDavid du Colombier c = devattach('M', 0);
3759ef1f84bSDavid du Colombier lock(&mntalloc);
3769ef1f84bSDavid du Colombier c->devno = mntalloc.id++;
3779ef1f84bSDavid du Colombier unlock(&mntalloc);
3789ef1f84bSDavid du Colombier
3799ef1f84bSDavid du Colombier if(c->mchan)
3809ef1f84bSDavid du Colombier panic("mntchan non-zero %#p", c->mchan);
3819ef1f84bSDavid du Colombier return c;
3829ef1f84bSDavid du Colombier }
3839ef1f84bSDavid du Colombier
3849ef1f84bSDavid du Colombier static Walkqid*
mntwalk(Chan * c,Chan * nc,char ** name,int nname)3859ef1f84bSDavid du Colombier mntwalk(Chan *c, Chan *nc, char **name, int nname)
3869ef1f84bSDavid du Colombier {
3879ef1f84bSDavid du Colombier int i, alloc;
3889ef1f84bSDavid du Colombier Mnt *mnt;
3899ef1f84bSDavid du Colombier Mntrpc *r;
3909ef1f84bSDavid du Colombier Walkqid *wq;
3919ef1f84bSDavid du Colombier
3929ef1f84bSDavid du Colombier if(nc != nil)
3939ef1f84bSDavid du Colombier print("mntwalk: nc != nil\n");
3949ef1f84bSDavid du Colombier if(nname > MAXWELEM)
3959ef1f84bSDavid du Colombier error("devmnt: too many name elements");
3969ef1f84bSDavid du Colombier alloc = 0;
3979ef1f84bSDavid du Colombier wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
3989ef1f84bSDavid du Colombier if(waserror()){
3999ef1f84bSDavid du Colombier if(alloc && wq->clone!=nil)
4009ef1f84bSDavid du Colombier cclose(wq->clone);
4019ef1f84bSDavid du Colombier free(wq);
4029ef1f84bSDavid du Colombier return nil;
4039ef1f84bSDavid du Colombier }
4049ef1f84bSDavid du Colombier
4059ef1f84bSDavid du Colombier alloc = 0;
4069ef1f84bSDavid du Colombier mnt = mntchk(c);
4079ef1f84bSDavid du Colombier r = mntralloc(c, mnt->msize);
4089ef1f84bSDavid du Colombier if(nc == nil){
4099ef1f84bSDavid du Colombier nc = devclone(c);
4109ef1f84bSDavid du Colombier /*
4119ef1f84bSDavid du Colombier * Until the other side accepts this fid,
4129ef1f84bSDavid du Colombier * we can't mntclose it.
4139ef1f84bSDavid du Colombier * nc->dev remains nil for now.
4149ef1f84bSDavid du Colombier */
4159ef1f84bSDavid du Colombier alloc = 1;
4169ef1f84bSDavid du Colombier }
4179ef1f84bSDavid du Colombier wq->clone = nc;
418406c76faSDavid du Colombier nc->flag |= c->flag&CCACHE;
4199ef1f84bSDavid du Colombier
4209ef1f84bSDavid du Colombier if(waserror()) {
4219ef1f84bSDavid du Colombier mntfree(r);
4229ef1f84bSDavid du Colombier nexterror();
4239ef1f84bSDavid du Colombier }
4249ef1f84bSDavid du Colombier r->request.type = Twalk;
4259ef1f84bSDavid du Colombier r->request.fid = c->fid;
4269ef1f84bSDavid du Colombier r->request.newfid = nc->fid;
4279ef1f84bSDavid du Colombier r->request.nwname = nname;
4289ef1f84bSDavid du Colombier memmove(r->request.wname, name, nname*sizeof(char*));
4299ef1f84bSDavid du Colombier
4309ef1f84bSDavid du Colombier mountrpc(mnt, r);
4319ef1f84bSDavid du Colombier
4329ef1f84bSDavid du Colombier if(r->reply.nwqid > nname)
4339ef1f84bSDavid du Colombier error("too many QIDs returned by walk");
4349ef1f84bSDavid du Colombier if(r->reply.nwqid < nname){
4359ef1f84bSDavid du Colombier if(alloc)
4369ef1f84bSDavid du Colombier cclose(nc);
4379ef1f84bSDavid du Colombier wq->clone = nil;
4389ef1f84bSDavid du Colombier if(r->reply.nwqid == 0){
4399ef1f84bSDavid du Colombier free(wq);
4409ef1f84bSDavid du Colombier wq = nil;
4419ef1f84bSDavid du Colombier goto Return;
4429ef1f84bSDavid du Colombier }
4439ef1f84bSDavid du Colombier }
4449ef1f84bSDavid du Colombier
4459ef1f84bSDavid du Colombier /* move new fid onto mnt device and update its qid */
4469ef1f84bSDavid du Colombier if(wq->clone != nil){
4479ef1f84bSDavid du Colombier if(wq->clone != c){
4489ef1f84bSDavid du Colombier wq->clone->dev = c->dev;
4499ef1f84bSDavid du Colombier //if(wq->clone->dev != nil) //XDYNX
4509ef1f84bSDavid du Colombier // devtabincr(wq->clone->dev);
4519ef1f84bSDavid du Colombier wq->clone->mchan = c->mchan;
4529ef1f84bSDavid du Colombier incref(c->mchan);
4539ef1f84bSDavid du Colombier }
4549ef1f84bSDavid du Colombier if(r->reply.nwqid > 0)
4559ef1f84bSDavid du Colombier wq->clone->qid = r->reply.wqid[r->reply.nwqid-1];
4569ef1f84bSDavid du Colombier }
4579ef1f84bSDavid du Colombier wq->nqid = r->reply.nwqid;
4589ef1f84bSDavid du Colombier for(i=0; i<wq->nqid; i++)
4599ef1f84bSDavid du Colombier wq->qid[i] = r->reply.wqid[i];
4609ef1f84bSDavid du Colombier
4619ef1f84bSDavid du Colombier Return:
4629ef1f84bSDavid du Colombier poperror();
4639ef1f84bSDavid du Colombier mntfree(r);
4649ef1f84bSDavid du Colombier poperror();
4659ef1f84bSDavid du Colombier return wq;
4669ef1f84bSDavid du Colombier }
4679ef1f84bSDavid du Colombier
4689ef1f84bSDavid du Colombier static long
mntstat(Chan * c,uchar * dp,long n)4699ef1f84bSDavid du Colombier mntstat(Chan *c, uchar *dp, long n)
4709ef1f84bSDavid du Colombier {
4719ef1f84bSDavid du Colombier Mnt *mnt;
4729ef1f84bSDavid du Colombier Mntrpc *r;
4739ef1f84bSDavid du Colombier usize nstat;
4749ef1f84bSDavid du Colombier
4759ef1f84bSDavid du Colombier if(n < BIT16SZ)
4769ef1f84bSDavid du Colombier error(Eshortstat);
4779ef1f84bSDavid du Colombier mnt = mntchk(c);
4789ef1f84bSDavid du Colombier r = mntralloc(c, mnt->msize);
4799ef1f84bSDavid du Colombier if(waserror()) {
4809ef1f84bSDavid du Colombier mntfree(r);
4819ef1f84bSDavid du Colombier nexterror();
4829ef1f84bSDavid du Colombier }
4839ef1f84bSDavid du Colombier r->request.type = Tstat;
4849ef1f84bSDavid du Colombier r->request.fid = c->fid;
4859ef1f84bSDavid du Colombier mountrpc(mnt, r);
4869ef1f84bSDavid du Colombier
4879ef1f84bSDavid du Colombier if(r->reply.nstat > n){
4889ef1f84bSDavid du Colombier nstat = BIT16SZ;
4899ef1f84bSDavid du Colombier PBIT16(dp, r->reply.nstat-2);
4909ef1f84bSDavid du Colombier }else{
4919ef1f84bSDavid du Colombier nstat = r->reply.nstat;
4929ef1f84bSDavid du Colombier memmove(dp, r->reply.stat, nstat);
4939ef1f84bSDavid du Colombier validstat(dp, nstat);
4949ef1f84bSDavid du Colombier mntdirfix(dp, c);
4959ef1f84bSDavid du Colombier }
4969ef1f84bSDavid du Colombier poperror();
4979ef1f84bSDavid du Colombier mntfree(r);
4989ef1f84bSDavid du Colombier
4999ef1f84bSDavid du Colombier return nstat;
5009ef1f84bSDavid du Colombier }
5019ef1f84bSDavid du Colombier
5029ef1f84bSDavid du Colombier static Chan*
mntopencreate(int type,Chan * c,char * name,int omode,int perm)5039ef1f84bSDavid du Colombier mntopencreate(int type, Chan *c, char *name, int omode, int perm)
5049ef1f84bSDavid du Colombier {
5059ef1f84bSDavid du Colombier Mnt *mnt;
5069ef1f84bSDavid du Colombier Mntrpc *r;
5079ef1f84bSDavid du Colombier
5089ef1f84bSDavid du Colombier mnt = mntchk(c);
5099ef1f84bSDavid du Colombier r = mntralloc(c, mnt->msize);
5109ef1f84bSDavid du Colombier if(waserror()) {
5119ef1f84bSDavid du Colombier mntfree(r);
5129ef1f84bSDavid du Colombier nexterror();
5139ef1f84bSDavid du Colombier }
5149ef1f84bSDavid du Colombier r->request.type = type;
5159ef1f84bSDavid du Colombier r->request.fid = c->fid;
5169ef1f84bSDavid du Colombier r->request.mode = omode;
5179ef1f84bSDavid du Colombier if(type == Tcreate){
5189ef1f84bSDavid du Colombier r->request.perm = perm;
5199ef1f84bSDavid du Colombier r->request.name = name;
5209ef1f84bSDavid du Colombier }
5219ef1f84bSDavid du Colombier mountrpc(mnt, r);
5229ef1f84bSDavid du Colombier
5239ef1f84bSDavid du Colombier c->qid = r->reply.qid;
5249ef1f84bSDavid du Colombier c->offset = 0;
5259ef1f84bSDavid du Colombier c->mode = openmode(omode);
5269ef1f84bSDavid du Colombier c->iounit = r->reply.iounit;
5279ef1f84bSDavid du Colombier if(c->iounit == 0 || c->iounit > mnt->msize-IOHDRSZ)
5289ef1f84bSDavid du Colombier c->iounit = mnt->msize-IOHDRSZ;
5299ef1f84bSDavid du Colombier c->flag |= COPEN;
5309ef1f84bSDavid du Colombier poperror();
5319ef1f84bSDavid du Colombier mntfree(r);
5329ef1f84bSDavid du Colombier
5339ef1f84bSDavid du Colombier if(c->flag & CCACHE)
5349ef1f84bSDavid du Colombier copen(c);
5359ef1f84bSDavid du Colombier
5369ef1f84bSDavid du Colombier return c;
5379ef1f84bSDavid du Colombier }
5389ef1f84bSDavid du Colombier
5399ef1f84bSDavid du Colombier static Chan*
mntopen(Chan * c,int omode)5409ef1f84bSDavid du Colombier mntopen(Chan *c, int omode)
5419ef1f84bSDavid du Colombier {
5429ef1f84bSDavid du Colombier return mntopencreate(Topen, c, nil, omode, 0);
5439ef1f84bSDavid du Colombier }
5449ef1f84bSDavid du Colombier
5459ef1f84bSDavid du Colombier static void
mntcreate(Chan * c,char * name,int omode,int perm)5469ef1f84bSDavid du Colombier mntcreate(Chan *c, char *name, int omode, int perm)
5479ef1f84bSDavid du Colombier {
5489ef1f84bSDavid du Colombier mntopencreate(Tcreate, c, name, omode, perm);
5499ef1f84bSDavid du Colombier }
5509ef1f84bSDavid du Colombier
5519ef1f84bSDavid du Colombier static void
mntclunk(Chan * c,int t)5529ef1f84bSDavid du Colombier mntclunk(Chan *c, int t)
5539ef1f84bSDavid du Colombier {
5549ef1f84bSDavid du Colombier Mnt *mnt;
5559ef1f84bSDavid du Colombier Mntrpc *r;
5569ef1f84bSDavid du Colombier
5579ef1f84bSDavid du Colombier mnt = mntchk(c);
5589ef1f84bSDavid du Colombier r = mntralloc(c, mnt->msize);
5599ef1f84bSDavid du Colombier if(waserror()){
5609ef1f84bSDavid du Colombier mntfree(r);
5619ef1f84bSDavid du Colombier nexterror();
5629ef1f84bSDavid du Colombier }
5639ef1f84bSDavid du Colombier
5649ef1f84bSDavid du Colombier r->request.type = t;
5659ef1f84bSDavid du Colombier r->request.fid = c->fid;
5669ef1f84bSDavid du Colombier mountrpc(mnt, r);
5679ef1f84bSDavid du Colombier mntfree(r);
5689ef1f84bSDavid du Colombier poperror();
5699ef1f84bSDavid du Colombier }
5709ef1f84bSDavid du Colombier
5719ef1f84bSDavid du Colombier void
muxclose(Mnt * mnt)5729ef1f84bSDavid du Colombier muxclose(Mnt *mnt)
5739ef1f84bSDavid du Colombier {
5749ef1f84bSDavid du Colombier Mntrpc *q, *r;
5759ef1f84bSDavid du Colombier
5769ef1f84bSDavid du Colombier for(q = mnt->queue; q; q = r) {
5779ef1f84bSDavid du Colombier r = q->list;
5789ef1f84bSDavid du Colombier mntfree(q);
5799ef1f84bSDavid du Colombier }
5809ef1f84bSDavid du Colombier mnt->id = 0;
5819ef1f84bSDavid du Colombier free(mnt->version);
5829ef1f84bSDavid du Colombier mnt->version = nil;
5839ef1f84bSDavid du Colombier mntpntfree(mnt);
5849ef1f84bSDavid du Colombier }
5859ef1f84bSDavid du Colombier
5869ef1f84bSDavid du Colombier void
mntpntfree(Mnt * mnt)5879ef1f84bSDavid du Colombier mntpntfree(Mnt *mnt)
5889ef1f84bSDavid du Colombier {
5899ef1f84bSDavid du Colombier Mnt *f, **l;
5909ef1f84bSDavid du Colombier Queue *q;
5919ef1f84bSDavid du Colombier
5929ef1f84bSDavid du Colombier lock(&mntalloc);
5939ef1f84bSDavid du Colombier l = &mntalloc.list;
5949ef1f84bSDavid du Colombier for(f = *l; f; f = f->list) {
5959ef1f84bSDavid du Colombier if(f == mnt) {
5969ef1f84bSDavid du Colombier *l = mnt->list;
5979ef1f84bSDavid du Colombier break;
5989ef1f84bSDavid du Colombier }
5999ef1f84bSDavid du Colombier l = &f->list;
6009ef1f84bSDavid du Colombier }
6019ef1f84bSDavid du Colombier mnt->list = mntalloc.mntfree;
6029ef1f84bSDavid du Colombier mntalloc.mntfree = mnt;
6039ef1f84bSDavid du Colombier q = mnt->q;
6049ef1f84bSDavid du Colombier unlock(&mntalloc);
6059ef1f84bSDavid du Colombier
6069ef1f84bSDavid du Colombier qfree(q);
6079ef1f84bSDavid du Colombier }
6089ef1f84bSDavid du Colombier
6099ef1f84bSDavid du Colombier static void
mntclose(Chan * c)6109ef1f84bSDavid du Colombier mntclose(Chan *c)
6119ef1f84bSDavid du Colombier {
6129ef1f84bSDavid du Colombier mntclunk(c, Tclunk);
6139ef1f84bSDavid du Colombier }
6149ef1f84bSDavid du Colombier
6159ef1f84bSDavid du Colombier static void
mntremove(Chan * c)6169ef1f84bSDavid du Colombier mntremove(Chan *c)
6179ef1f84bSDavid du Colombier {
6189ef1f84bSDavid du Colombier mntclunk(c, Tremove);
6199ef1f84bSDavid du Colombier }
6209ef1f84bSDavid du Colombier
6219ef1f84bSDavid du Colombier static long
mntwstat(Chan * c,uchar * dp,long n)6229ef1f84bSDavid du Colombier mntwstat(Chan *c, uchar *dp, long n)
6239ef1f84bSDavid du Colombier {
6249ef1f84bSDavid du Colombier Mnt *mnt;
6259ef1f84bSDavid du Colombier Mntrpc *r;
6269ef1f84bSDavid du Colombier
6279ef1f84bSDavid du Colombier mnt = mntchk(c);
6289ef1f84bSDavid du Colombier r = mntralloc(c, mnt->msize);
6299ef1f84bSDavid du Colombier if(waserror()) {
6309ef1f84bSDavid du Colombier mntfree(r);
6319ef1f84bSDavid du Colombier nexterror();
6329ef1f84bSDavid du Colombier }
6339ef1f84bSDavid du Colombier r->request.type = Twstat;
6349ef1f84bSDavid du Colombier r->request.fid = c->fid;
6359ef1f84bSDavid du Colombier r->request.nstat = n;
6369ef1f84bSDavid du Colombier r->request.stat = dp;
6379ef1f84bSDavid du Colombier mountrpc(mnt, r);
6389ef1f84bSDavid du Colombier poperror();
6399ef1f84bSDavid du Colombier mntfree(r);
6409ef1f84bSDavid du Colombier return n;
6419ef1f84bSDavid du Colombier }
6429ef1f84bSDavid du Colombier
6439ef1f84bSDavid du Colombier static long
mntread(Chan * c,void * buf,long n,vlong off)6449ef1f84bSDavid du Colombier mntread(Chan *c, void *buf, long n, vlong off)
6459ef1f84bSDavid du Colombier {
6469ef1f84bSDavid du Colombier uchar *p, *e;
6479ef1f84bSDavid du Colombier int nc, cache, isdir;
6489ef1f84bSDavid du Colombier usize dirlen;
6499ef1f84bSDavid du Colombier
6509ef1f84bSDavid du Colombier isdir = 0;
6519ef1f84bSDavid du Colombier cache = c->flag & CCACHE;
6529ef1f84bSDavid du Colombier if(c->qid.type & QTDIR) {
6539ef1f84bSDavid du Colombier cache = 0;
6549ef1f84bSDavid du Colombier isdir = 1;
6559ef1f84bSDavid du Colombier }
6569ef1f84bSDavid du Colombier
6579ef1f84bSDavid du Colombier p = buf;
6589ef1f84bSDavid du Colombier if(cache) {
6599ef1f84bSDavid du Colombier nc = cread(c, buf, n, off);
6609ef1f84bSDavid du Colombier if(nc > 0) {
6619ef1f84bSDavid du Colombier n -= nc;
6629ef1f84bSDavid du Colombier if(n == 0)
6639ef1f84bSDavid du Colombier return nc;
6649ef1f84bSDavid du Colombier p += nc;
6659ef1f84bSDavid du Colombier off += nc;
6669ef1f84bSDavid du Colombier }
6679ef1f84bSDavid du Colombier n = mntrdwr(Tread, c, p, n, off);
6689ef1f84bSDavid du Colombier cupdate(c, p, n, off);
6699ef1f84bSDavid du Colombier return n + nc;
6709ef1f84bSDavid du Colombier }
6719ef1f84bSDavid du Colombier
6729ef1f84bSDavid du Colombier n = mntrdwr(Tread, c, buf, n, off);
6739ef1f84bSDavid du Colombier if(isdir) {
6749ef1f84bSDavid du Colombier for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
6759ef1f84bSDavid du Colombier dirlen = BIT16SZ+GBIT16(p);
6769ef1f84bSDavid du Colombier if(p+dirlen > e)
6779ef1f84bSDavid du Colombier break;
6789ef1f84bSDavid du Colombier validstat(p, dirlen);
6799ef1f84bSDavid du Colombier mntdirfix(p, c);
6809ef1f84bSDavid du Colombier }
6819ef1f84bSDavid du Colombier if(p != e)
6829ef1f84bSDavid du Colombier error(Esbadstat);
6839ef1f84bSDavid du Colombier }
6849ef1f84bSDavid du Colombier return n;
6859ef1f84bSDavid du Colombier }
6869ef1f84bSDavid du Colombier
6879ef1f84bSDavid du Colombier static long
mntwrite(Chan * c,void * buf,long n,vlong off)6889ef1f84bSDavid du Colombier mntwrite(Chan *c, void *buf, long n, vlong off)
6899ef1f84bSDavid du Colombier {
6909ef1f84bSDavid du Colombier return mntrdwr(Twrite, c, buf, n, off);
6919ef1f84bSDavid du Colombier }
6929ef1f84bSDavid du Colombier
6939ef1f84bSDavid du Colombier long
mntrdwr(int type,Chan * c,void * buf,long n,vlong off)6949ef1f84bSDavid du Colombier mntrdwr(int type, Chan *c, void *buf, long n, vlong off)
6959ef1f84bSDavid du Colombier {
6969ef1f84bSDavid du Colombier Mnt *mnt;
6979ef1f84bSDavid du Colombier Mntrpc *r;
6989ef1f84bSDavid du Colombier char *uba;
6999ef1f84bSDavid du Colombier int cache;
7009ef1f84bSDavid du Colombier ulong cnt, nr, nreq;
7019ef1f84bSDavid du Colombier
7029ef1f84bSDavid du Colombier mnt = mntchk(c);
7039ef1f84bSDavid du Colombier uba = buf;
7049ef1f84bSDavid du Colombier cnt = 0;
7059ef1f84bSDavid du Colombier cache = c->flag & CCACHE;
7069ef1f84bSDavid du Colombier if(c->qid.type & QTDIR)
7079ef1f84bSDavid du Colombier cache = 0;
7089ef1f84bSDavid du Colombier for(;;) {
7099ef1f84bSDavid du Colombier r = mntralloc(c, mnt->msize);
7109ef1f84bSDavid du Colombier if(waserror()) {
7119ef1f84bSDavid du Colombier mntfree(r);
7129ef1f84bSDavid du Colombier nexterror();
7139ef1f84bSDavid du Colombier }
7149ef1f84bSDavid du Colombier r->request.type = type;
7159ef1f84bSDavid du Colombier r->request.fid = c->fid;
7169ef1f84bSDavid du Colombier r->request.offset = off;
7179ef1f84bSDavid du Colombier r->request.data = uba;
7189ef1f84bSDavid du Colombier nr = n;
7199ef1f84bSDavid du Colombier if(nr > mnt->msize-IOHDRSZ)
7209ef1f84bSDavid du Colombier nr = mnt->msize-IOHDRSZ;
7219ef1f84bSDavid du Colombier r->request.count = nr;
7229ef1f84bSDavid du Colombier mountrpc(mnt, r);
7239ef1f84bSDavid du Colombier nreq = r->request.count;
7249ef1f84bSDavid du Colombier nr = r->reply.count;
7259ef1f84bSDavid du Colombier if(nr > nreq)
7269ef1f84bSDavid du Colombier nr = nreq;
7279ef1f84bSDavid du Colombier
7289ef1f84bSDavid du Colombier if(type == Tread)
7299ef1f84bSDavid du Colombier r->b = bl2mem((uchar*)uba, r->b, nr);
7309ef1f84bSDavid du Colombier else if(cache)
7319ef1f84bSDavid du Colombier cwrite(c, (uchar*)uba, nr, off);
7329ef1f84bSDavid du Colombier
7339ef1f84bSDavid du Colombier poperror();
7349ef1f84bSDavid du Colombier mntfree(r);
7359ef1f84bSDavid du Colombier off += nr;
7369ef1f84bSDavid du Colombier uba += nr;
7379ef1f84bSDavid du Colombier cnt += nr;
7389ef1f84bSDavid du Colombier n -= nr;
7399ef1f84bSDavid du Colombier if(nr != nreq || n == 0 || up->nnote)
7409ef1f84bSDavid du Colombier break;
7419ef1f84bSDavid du Colombier }
7429ef1f84bSDavid du Colombier return cnt;
7439ef1f84bSDavid du Colombier }
7449ef1f84bSDavid du Colombier
7459ef1f84bSDavid du Colombier void
mountrpc(Mnt * mnt,Mntrpc * r)7469ef1f84bSDavid du Colombier mountrpc(Mnt *mnt, Mntrpc *r)
7479ef1f84bSDavid du Colombier {
7489ef1f84bSDavid du Colombier char *sn, *cn;
7499ef1f84bSDavid du Colombier int t;
7509ef1f84bSDavid du Colombier
7519ef1f84bSDavid du Colombier r->reply.tag = 0;
7529ef1f84bSDavid du Colombier r->reply.type = Tmax; /* can't ever be a valid message type */
7539ef1f84bSDavid du Colombier
7549ef1f84bSDavid du Colombier mountio(mnt, r);
7559ef1f84bSDavid du Colombier
7569ef1f84bSDavid du Colombier t = r->reply.type;
7579ef1f84bSDavid du Colombier switch(t) {
7589ef1f84bSDavid du Colombier case Rerror:
7599ef1f84bSDavid du Colombier error(r->reply.ename);
7609ef1f84bSDavid du Colombier case Rflush:
7619ef1f84bSDavid du Colombier error(Eintr);
7629ef1f84bSDavid du Colombier default:
7639ef1f84bSDavid du Colombier if(t == r->request.type+1)
7649ef1f84bSDavid du Colombier break;
7659ef1f84bSDavid du Colombier sn = "?";
7669ef1f84bSDavid du Colombier if(mnt->c->path != nil)
7679ef1f84bSDavid du Colombier sn = mnt->c->path->s;
7689ef1f84bSDavid du Colombier cn = "?";
7699ef1f84bSDavid du Colombier if(r->c != nil && r->c->path != nil)
7709ef1f84bSDavid du Colombier cn = r->c->path->s;
7719ef1f84bSDavid du Colombier print("mnt: proc %s %d: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
7729ef1f84bSDavid du Colombier up->text, up->pid, sn, cn,
7739ef1f84bSDavid du Colombier r, r->request.tag, r->request.fid, r->request.type,
7749ef1f84bSDavid du Colombier r->reply.type, r->reply.tag);
7759ef1f84bSDavid du Colombier error(Emountrpc);
7769ef1f84bSDavid du Colombier }
7779ef1f84bSDavid du Colombier }
7789ef1f84bSDavid du Colombier
7799ef1f84bSDavid du Colombier void
mountio(Mnt * mnt,Mntrpc * r)7809ef1f84bSDavid du Colombier mountio(Mnt *mnt, Mntrpc *r)
7819ef1f84bSDavid du Colombier {
7829ef1f84bSDavid du Colombier int n;
7839ef1f84bSDavid du Colombier
7849ef1f84bSDavid du Colombier while(waserror()) {
7859ef1f84bSDavid du Colombier if(mnt->rip == up)
7869ef1f84bSDavid du Colombier mntgate(mnt);
7879ef1f84bSDavid du Colombier if(strcmp(up->errstr, Eintr) != 0){
7889ef1f84bSDavid du Colombier mntflushfree(mnt, r);
7899ef1f84bSDavid du Colombier nexterror();
7909ef1f84bSDavid du Colombier }
7919ef1f84bSDavid du Colombier r = mntflushalloc(r, mnt->msize);
7929ef1f84bSDavid du Colombier }
7939ef1f84bSDavid du Colombier
7949ef1f84bSDavid du Colombier lock(mnt);
7959ef1f84bSDavid du Colombier r->m = mnt;
7969ef1f84bSDavid du Colombier r->list = mnt->queue;
7979ef1f84bSDavid du Colombier mnt->queue = r;
7989ef1f84bSDavid du Colombier unlock(mnt);
7999ef1f84bSDavid du Colombier
8009ef1f84bSDavid du Colombier /* Transmit a file system rpc */
8019ef1f84bSDavid du Colombier if(mnt->msize == 0)
8029ef1f84bSDavid du Colombier panic("msize");
8039ef1f84bSDavid du Colombier n = convS2M(&r->request, r->rpc, mnt->msize);
8049ef1f84bSDavid du Colombier if(n < 0)
8059ef1f84bSDavid du Colombier panic("bad message type in mountio");
8069ef1f84bSDavid du Colombier if(mnt->c->dev->write(mnt->c, r->rpc, n, 0) != n)
8079ef1f84bSDavid du Colombier error(Emountrpc);
8089ef1f84bSDavid du Colombier r->stime = fastticks(nil);
8099ef1f84bSDavid du Colombier r->reqlen = n;
8109ef1f84bSDavid du Colombier
8119ef1f84bSDavid du Colombier /* Gate readers onto the mount point one at a time */
8129ef1f84bSDavid du Colombier for(;;) {
8139ef1f84bSDavid du Colombier lock(mnt);
8149ef1f84bSDavid du Colombier if(mnt->rip == 0)
8159ef1f84bSDavid du Colombier break;
8169ef1f84bSDavid du Colombier unlock(mnt);
8179ef1f84bSDavid du Colombier sleep(&r->r, rpcattn, r);
8189ef1f84bSDavid du Colombier if(r->done){
8199ef1f84bSDavid du Colombier poperror();
8209ef1f84bSDavid du Colombier mntflushfree(mnt, r);
8219ef1f84bSDavid du Colombier return;
8229ef1f84bSDavid du Colombier }
8239ef1f84bSDavid du Colombier }
8249ef1f84bSDavid du Colombier mnt->rip = up;
8259ef1f84bSDavid du Colombier unlock(mnt);
8269ef1f84bSDavid du Colombier while(r->done == 0) {
8279ef1f84bSDavid du Colombier if(mntrpcread(mnt, r) < 0)
8289ef1f84bSDavid du Colombier error(Emountrpc);
8299ef1f84bSDavid du Colombier mountmux(mnt, r);
8309ef1f84bSDavid du Colombier }
8319ef1f84bSDavid du Colombier mntgate(mnt);
8329ef1f84bSDavid du Colombier poperror();
8339ef1f84bSDavid du Colombier mntflushfree(mnt, r);
8349ef1f84bSDavid du Colombier }
8359ef1f84bSDavid du Colombier
8369ef1f84bSDavid du Colombier static int
doread(Mnt * mnt,int len)8379ef1f84bSDavid du Colombier doread(Mnt *mnt, int len)
8389ef1f84bSDavid du Colombier {
8399ef1f84bSDavid du Colombier Block *b;
8409ef1f84bSDavid du Colombier
8419ef1f84bSDavid du Colombier while(qlen(mnt->q) < len){
8429ef1f84bSDavid du Colombier b = mnt->c->dev->bread(mnt->c, mnt->msize, 0);
8439ef1f84bSDavid du Colombier if(b == nil)
8449ef1f84bSDavid du Colombier return -1;
8459ef1f84bSDavid du Colombier if(blocklen(b) == 0){
8469ef1f84bSDavid du Colombier freeblist(b);
8479ef1f84bSDavid du Colombier return -1;
8489ef1f84bSDavid du Colombier }
8499ef1f84bSDavid du Colombier qaddlist(mnt->q, b);
8509ef1f84bSDavid du Colombier }
8519ef1f84bSDavid du Colombier return 0;
8529ef1f84bSDavid du Colombier }
8539ef1f84bSDavid du Colombier
8549ef1f84bSDavid du Colombier int
mntrpcread(Mnt * mnt,Mntrpc * r)8559ef1f84bSDavid du Colombier mntrpcread(Mnt *mnt, Mntrpc *r)
8569ef1f84bSDavid du Colombier {
8579ef1f84bSDavid du Colombier int i, t, len, hlen;
8589ef1f84bSDavid du Colombier Block *b, **l, *nb;
8599ef1f84bSDavid du Colombier
8609ef1f84bSDavid du Colombier r->reply.type = 0;
8619ef1f84bSDavid du Colombier r->reply.tag = 0;
8629ef1f84bSDavid du Colombier
8639ef1f84bSDavid du Colombier /* read at least length, type, and tag and pullup to a single block */
8649ef1f84bSDavid du Colombier if(doread(mnt, BIT32SZ+BIT8SZ+BIT16SZ) < 0)
8659ef1f84bSDavid du Colombier return -1;
8669ef1f84bSDavid du Colombier nb = pullupqueue(mnt->q, BIT32SZ+BIT8SZ+BIT16SZ);
8679ef1f84bSDavid du Colombier
8689ef1f84bSDavid du Colombier /* read in the rest of the message, avoid ridiculous (for now) message sizes */
8699ef1f84bSDavid du Colombier len = GBIT32(nb->rp);
8709ef1f84bSDavid du Colombier if(len > mnt->msize){
8719ef1f84bSDavid du Colombier qdiscard(mnt->q, qlen(mnt->q));
8729ef1f84bSDavid du Colombier return -1;
8739ef1f84bSDavid du Colombier }
8749ef1f84bSDavid du Colombier if(doread(mnt, len) < 0)
8759ef1f84bSDavid du Colombier return -1;
8769ef1f84bSDavid du Colombier
8779ef1f84bSDavid du Colombier /* pullup the header (i.e. everything except data) */
8789ef1f84bSDavid du Colombier t = nb->rp[BIT32SZ];
8799ef1f84bSDavid du Colombier switch(t){
8809ef1f84bSDavid du Colombier case Rread:
8819ef1f84bSDavid du Colombier hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ;
8829ef1f84bSDavid du Colombier break;
8839ef1f84bSDavid du Colombier default:
8849ef1f84bSDavid du Colombier hlen = len;
8859ef1f84bSDavid du Colombier break;
8869ef1f84bSDavid du Colombier }
8879ef1f84bSDavid du Colombier nb = pullupqueue(mnt->q, hlen);
8889ef1f84bSDavid du Colombier
8899ef1f84bSDavid du Colombier if(convM2S(nb->rp, len, &r->reply) <= 0){
8909ef1f84bSDavid du Colombier /* bad message, dump it */
8919ef1f84bSDavid du Colombier print("mntrpcread: convM2S failed\n");
8929ef1f84bSDavid du Colombier qdiscard(mnt->q, len);
8939ef1f84bSDavid du Colombier return -1;
8949ef1f84bSDavid du Colombier }
8959ef1f84bSDavid du Colombier
8969ef1f84bSDavid du Colombier /* hang the data off of the fcall struct */
8979ef1f84bSDavid du Colombier l = &r->b;
8989ef1f84bSDavid du Colombier *l = nil;
8999ef1f84bSDavid du Colombier do {
9009ef1f84bSDavid du Colombier b = qremove(mnt->q);
9019ef1f84bSDavid du Colombier if(hlen > 0){
9029ef1f84bSDavid du Colombier b->rp += hlen;
9039ef1f84bSDavid du Colombier len -= hlen;
9049ef1f84bSDavid du Colombier hlen = 0;
9059ef1f84bSDavid du Colombier }
9069ef1f84bSDavid du Colombier i = BLEN(b);
9079ef1f84bSDavid du Colombier if(i <= len){
9089ef1f84bSDavid du Colombier len -= i;
9099ef1f84bSDavid du Colombier *l = b;
9109ef1f84bSDavid du Colombier l = &(b->next);
9119ef1f84bSDavid du Colombier } else {
9129ef1f84bSDavid du Colombier /* split block and put unused bit back */
9139ef1f84bSDavid du Colombier nb = allocb(i-len);
9149ef1f84bSDavid du Colombier memmove(nb->wp, b->rp+len, i-len);
9159ef1f84bSDavid du Colombier b->wp = b->rp+len;
9169ef1f84bSDavid du Colombier nb->wp += i-len;
9179ef1f84bSDavid du Colombier qputback(mnt->q, nb);
9189ef1f84bSDavid du Colombier *l = b;
9199ef1f84bSDavid du Colombier return 0;
9209ef1f84bSDavid du Colombier }
9219ef1f84bSDavid du Colombier }while(len > 0);
9229ef1f84bSDavid du Colombier
9239ef1f84bSDavid du Colombier return 0;
9249ef1f84bSDavid du Colombier }
9259ef1f84bSDavid du Colombier
9269ef1f84bSDavid du Colombier void
mntgate(Mnt * mnt)9279ef1f84bSDavid du Colombier mntgate(Mnt *mnt)
9289ef1f84bSDavid du Colombier {
9299ef1f84bSDavid du Colombier Mntrpc *q;
9309ef1f84bSDavid du Colombier
9319ef1f84bSDavid du Colombier lock(mnt);
9329ef1f84bSDavid du Colombier mnt->rip = 0;
9339ef1f84bSDavid du Colombier for(q = mnt->queue; q; q = q->list) {
9349ef1f84bSDavid du Colombier if(q->done == 0)
9359ef1f84bSDavid du Colombier if(wakeup(&q->r))
9369ef1f84bSDavid du Colombier break;
9379ef1f84bSDavid du Colombier }
9389ef1f84bSDavid du Colombier unlock(mnt);
9399ef1f84bSDavid du Colombier }
9409ef1f84bSDavid du Colombier
9419ef1f84bSDavid du Colombier void
mountmux(Mnt * mnt,Mntrpc * r)9429ef1f84bSDavid du Colombier mountmux(Mnt *mnt, Mntrpc *r)
9439ef1f84bSDavid du Colombier {
9449ef1f84bSDavid du Colombier Mntrpc **l, *q;
9459ef1f84bSDavid du Colombier
9469ef1f84bSDavid du Colombier lock(mnt);
9479ef1f84bSDavid du Colombier l = &mnt->queue;
9489ef1f84bSDavid du Colombier for(q = *l; q; q = q->list) {
9499ef1f84bSDavid du Colombier /* look for a reply to a message */
9509ef1f84bSDavid du Colombier if(q->request.tag == r->reply.tag) {
9519ef1f84bSDavid du Colombier *l = q->list;
9529ef1f84bSDavid du Colombier if(q != r) {
9539ef1f84bSDavid du Colombier /*
9549ef1f84bSDavid du Colombier * Completed someone else.
9559ef1f84bSDavid du Colombier * Trade pointers to receive buffer.
9569ef1f84bSDavid du Colombier */
9579ef1f84bSDavid du Colombier q->reply = r->reply;
9589ef1f84bSDavid du Colombier q->b = r->b;
9599ef1f84bSDavid du Colombier r->b = nil;
9609ef1f84bSDavid du Colombier }
9619ef1f84bSDavid du Colombier q->done = 1;
9629ef1f84bSDavid du Colombier unlock(mnt);
9639ef1f84bSDavid du Colombier if(mntstats != nil)
9649ef1f84bSDavid du Colombier (*mntstats)(q->request.type,
9659ef1f84bSDavid du Colombier mnt->c, q->stime,
9669ef1f84bSDavid du Colombier q->reqlen + r->replen);
9679ef1f84bSDavid du Colombier if(q != r)
9689ef1f84bSDavid du Colombier wakeup(&q->r);
9699ef1f84bSDavid du Colombier return;
9709ef1f84bSDavid du Colombier }
9719ef1f84bSDavid du Colombier l = &q->list;
9729ef1f84bSDavid du Colombier }
9739ef1f84bSDavid du Colombier unlock(mnt);
9749ef1f84bSDavid du Colombier print("unexpected reply tag %ud; type %d\n", r->reply.tag, r->reply.type);
9759ef1f84bSDavid du Colombier }
9769ef1f84bSDavid du Colombier
9779ef1f84bSDavid du Colombier /*
9789ef1f84bSDavid du Colombier * Create a new flush request and chain the previous
9799ef1f84bSDavid du Colombier * requests from it
9809ef1f84bSDavid du Colombier */
9819ef1f84bSDavid du Colombier Mntrpc*
mntflushalloc(Mntrpc * r,ulong iounit)9829ef1f84bSDavid du Colombier mntflushalloc(Mntrpc *r, ulong iounit)
9839ef1f84bSDavid du Colombier {
9849ef1f84bSDavid du Colombier Mntrpc *fr;
9859ef1f84bSDavid du Colombier
9869ef1f84bSDavid du Colombier fr = mntralloc(0, iounit);
9879ef1f84bSDavid du Colombier
9889ef1f84bSDavid du Colombier fr->request.type = Tflush;
9899ef1f84bSDavid du Colombier if(r->request.type == Tflush)
9909ef1f84bSDavid du Colombier fr->request.oldtag = r->request.oldtag;
9919ef1f84bSDavid du Colombier else
9929ef1f84bSDavid du Colombier fr->request.oldtag = r->request.tag;
9939ef1f84bSDavid du Colombier fr->flushed = r;
9949ef1f84bSDavid du Colombier
9959ef1f84bSDavid du Colombier return fr;
9969ef1f84bSDavid du Colombier }
9979ef1f84bSDavid du Colombier
9989ef1f84bSDavid du Colombier /*
9999ef1f84bSDavid du Colombier * Free a chain of flushes. Remove each unanswered
10009ef1f84bSDavid du Colombier * flush and the original message from the unanswered
10019ef1f84bSDavid du Colombier * request queue. Mark the original message as done
10029ef1f84bSDavid du Colombier * and if it hasn't been answered set the reply to to
10039ef1f84bSDavid du Colombier * Rflush.
10049ef1f84bSDavid du Colombier */
10059ef1f84bSDavid du Colombier void
mntflushfree(Mnt * mnt,Mntrpc * r)10069ef1f84bSDavid du Colombier mntflushfree(Mnt *mnt, Mntrpc *r)
10079ef1f84bSDavid du Colombier {
10089ef1f84bSDavid du Colombier Mntrpc *fr;
10099ef1f84bSDavid du Colombier
10109ef1f84bSDavid du Colombier while(r){
10119ef1f84bSDavid du Colombier fr = r->flushed;
10129ef1f84bSDavid du Colombier if(!r->done){
10139ef1f84bSDavid du Colombier r->reply.type = Rflush;
10149ef1f84bSDavid du Colombier mntqrm(mnt, r);
10159ef1f84bSDavid du Colombier }
10169ef1f84bSDavid du Colombier if(fr)
10179ef1f84bSDavid du Colombier mntfree(r);
10189ef1f84bSDavid du Colombier r = fr;
10199ef1f84bSDavid du Colombier }
10209ef1f84bSDavid du Colombier }
10219ef1f84bSDavid du Colombier
10229ef1f84bSDavid du Colombier int
alloctag(void)10239ef1f84bSDavid du Colombier alloctag(void)
10249ef1f84bSDavid du Colombier {
10259ef1f84bSDavid du Colombier int i, j;
10269ef1f84bSDavid du Colombier ulong v;
10279ef1f84bSDavid du Colombier
10289ef1f84bSDavid du Colombier for(i = 0; i < NMASK; i++){
10299ef1f84bSDavid du Colombier v = mntalloc.tagmask[i];
10309ef1f84bSDavid du Colombier if(v == ~0UL)
10319ef1f84bSDavid du Colombier continue;
10329ef1f84bSDavid du Colombier for(j = 0; j < 1<<TAGSHIFT; j++)
10339ef1f84bSDavid du Colombier if((v & (1<<j)) == 0){
10349ef1f84bSDavid du Colombier mntalloc.tagmask[i] |= 1<<j;
10359ef1f84bSDavid du Colombier return (i<<TAGSHIFT) + j;
10369ef1f84bSDavid du Colombier }
10379ef1f84bSDavid du Colombier }
10389ef1f84bSDavid du Colombier panic("no friggin tags left");
10399ef1f84bSDavid du Colombier return NOTAG;
10409ef1f84bSDavid du Colombier }
10419ef1f84bSDavid du Colombier
10429ef1f84bSDavid du Colombier void
freetag(int t)10439ef1f84bSDavid du Colombier freetag(int t)
10449ef1f84bSDavid du Colombier {
10459ef1f84bSDavid du Colombier mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK));
10469ef1f84bSDavid du Colombier }
10479ef1f84bSDavid du Colombier
10489ef1f84bSDavid du Colombier Mntrpc*
mntralloc(Chan * c,ulong msize)10499ef1f84bSDavid du Colombier mntralloc(Chan *c, ulong msize)
10509ef1f84bSDavid du Colombier {
10519ef1f84bSDavid du Colombier Mntrpc *new;
10529ef1f84bSDavid du Colombier
10539ef1f84bSDavid du Colombier lock(&mntalloc);
10549ef1f84bSDavid du Colombier new = mntalloc.rpcfree;
10559ef1f84bSDavid du Colombier if(new == nil){
10569ef1f84bSDavid du Colombier new = malloc(sizeof(Mntrpc));
10579ef1f84bSDavid du Colombier if(new == nil) {
10589ef1f84bSDavid du Colombier unlock(&mntalloc);
10599ef1f84bSDavid du Colombier exhausted("mount rpc header");
10609ef1f84bSDavid du Colombier }
10619ef1f84bSDavid du Colombier /*
10629ef1f84bSDavid du Colombier * The header is split from the data buffer as
10639ef1f84bSDavid du Colombier * mountmux may swap the buffer with another header.
10649ef1f84bSDavid du Colombier */
10659ef1f84bSDavid du Colombier new->rpc = mallocz(msize, 0);
10669ef1f84bSDavid du Colombier if(new->rpc == nil){
10679ef1f84bSDavid du Colombier free(new);
10689ef1f84bSDavid du Colombier unlock(&mntalloc);
10699ef1f84bSDavid du Colombier exhausted("mount rpc buffer");
10709ef1f84bSDavid du Colombier }
10719ef1f84bSDavid du Colombier new->rpclen = msize;
10729ef1f84bSDavid du Colombier new->request.tag = alloctag();
10739ef1f84bSDavid du Colombier }
10749ef1f84bSDavid du Colombier else {
10759ef1f84bSDavid du Colombier mntalloc.rpcfree = new->list;
10769ef1f84bSDavid du Colombier mntalloc.nrpcfree--;
10779ef1f84bSDavid du Colombier if(new->rpclen < msize){
10789ef1f84bSDavid du Colombier free(new->rpc);
10799ef1f84bSDavid du Colombier new->rpc = mallocz(msize, 0);
10809ef1f84bSDavid du Colombier if(new->rpc == nil){
10819ef1f84bSDavid du Colombier free(new);
10829ef1f84bSDavid du Colombier mntalloc.nrpcused--;
10839ef1f84bSDavid du Colombier unlock(&mntalloc);
10849ef1f84bSDavid du Colombier exhausted("mount rpc buffer");
10859ef1f84bSDavid du Colombier }
10869ef1f84bSDavid du Colombier new->rpclen = msize;
10879ef1f84bSDavid du Colombier }
10889ef1f84bSDavid du Colombier }
10899ef1f84bSDavid du Colombier mntalloc.nrpcused++;
10909ef1f84bSDavid du Colombier unlock(&mntalloc);
10919ef1f84bSDavid du Colombier new->c = c;
10929ef1f84bSDavid du Colombier new->done = 0;
10939ef1f84bSDavid du Colombier new->flushed = nil;
10949ef1f84bSDavid du Colombier new->b = nil;
10959ef1f84bSDavid du Colombier return new;
10969ef1f84bSDavid du Colombier }
10979ef1f84bSDavid du Colombier
10989ef1f84bSDavid du Colombier void
mntfree(Mntrpc * r)10999ef1f84bSDavid du Colombier mntfree(Mntrpc *r)
11009ef1f84bSDavid du Colombier {
11019ef1f84bSDavid du Colombier if(r->b != nil)
11029ef1f84bSDavid du Colombier freeblist(r->b);
11039ef1f84bSDavid du Colombier lock(&mntalloc);
11049ef1f84bSDavid du Colombier if(mntalloc.nrpcfree >= 10){
11059ef1f84bSDavid du Colombier free(r->rpc);
11069ef1f84bSDavid du Colombier freetag(r->request.tag);
11079ef1f84bSDavid du Colombier free(r);
11089ef1f84bSDavid du Colombier }
11099ef1f84bSDavid du Colombier else{
11109ef1f84bSDavid du Colombier r->list = mntalloc.rpcfree;
11119ef1f84bSDavid du Colombier mntalloc.rpcfree = r;
11129ef1f84bSDavid du Colombier mntalloc.nrpcfree++;
11139ef1f84bSDavid du Colombier }
11149ef1f84bSDavid du Colombier mntalloc.nrpcused--;
11159ef1f84bSDavid du Colombier unlock(&mntalloc);
11169ef1f84bSDavid du Colombier }
11179ef1f84bSDavid du Colombier
11189ef1f84bSDavid du Colombier void
mntqrm(Mnt * mnt,Mntrpc * r)11199ef1f84bSDavid du Colombier mntqrm(Mnt *mnt, Mntrpc *r)
11209ef1f84bSDavid du Colombier {
11219ef1f84bSDavid du Colombier Mntrpc **l, *f;
11229ef1f84bSDavid du Colombier
11239ef1f84bSDavid du Colombier lock(mnt);
11249ef1f84bSDavid du Colombier r->done = 1;
11259ef1f84bSDavid du Colombier
11269ef1f84bSDavid du Colombier l = &mnt->queue;
11279ef1f84bSDavid du Colombier for(f = *l; f; f = f->list) {
11289ef1f84bSDavid du Colombier if(f == r) {
11299ef1f84bSDavid du Colombier *l = r->list;
11309ef1f84bSDavid du Colombier break;
11319ef1f84bSDavid du Colombier }
11329ef1f84bSDavid du Colombier l = &f->list;
11339ef1f84bSDavid du Colombier }
11349ef1f84bSDavid du Colombier unlock(mnt);
11359ef1f84bSDavid du Colombier }
11369ef1f84bSDavid du Colombier
11379ef1f84bSDavid du Colombier Mnt*
mntchk(Chan * c)11389ef1f84bSDavid du Colombier mntchk(Chan *c)
11399ef1f84bSDavid du Colombier {
11409ef1f84bSDavid du Colombier Mnt *mnt;
11419ef1f84bSDavid du Colombier
11429ef1f84bSDavid du Colombier /* This routine is mostly vestiges of prior lives; now it's just sanity checking */
11439ef1f84bSDavid du Colombier
11449ef1f84bSDavid du Colombier if(c->mchan == nil)
11459ef1f84bSDavid du Colombier panic("mntchk 1: nil mchan c %s\n", chanpath(c));
11469ef1f84bSDavid du Colombier
11479ef1f84bSDavid du Colombier mnt = c->mchan->mux;
11489ef1f84bSDavid du Colombier
11499ef1f84bSDavid du Colombier if(mnt == nil)
11509ef1f84bSDavid du Colombier print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));
11519ef1f84bSDavid du Colombier
11529ef1f84bSDavid du Colombier /*
11539ef1f84bSDavid du Colombier * Was it closed and reused (was error(Eshutdown); now, it cannot happen)
11549ef1f84bSDavid du Colombier */
11559ef1f84bSDavid du Colombier if(mnt->id == 0 || mnt->id >= c->devno)
11569ef1f84bSDavid du Colombier panic("mntchk 3: can't happen");
11579ef1f84bSDavid du Colombier
11589ef1f84bSDavid du Colombier return mnt;
11599ef1f84bSDavid du Colombier }
11609ef1f84bSDavid du Colombier
11619ef1f84bSDavid du Colombier /*
11629ef1f84bSDavid du Colombier * Rewrite channel type and dev for in-flight data to
11639ef1f84bSDavid du Colombier * reflect local values. These entries are known to be
11649ef1f84bSDavid du Colombier * the first two in the Dir encoding after the count.
11659ef1f84bSDavid du Colombier */
11669ef1f84bSDavid du Colombier void
mntdirfix(uchar * dirbuf,Chan * c)11679ef1f84bSDavid du Colombier mntdirfix(uchar *dirbuf, Chan *c)
11689ef1f84bSDavid du Colombier {
11699ef1f84bSDavid du Colombier uint r;
11709ef1f84bSDavid du Colombier
11719ef1f84bSDavid du Colombier r = c->dev->dc;
11729ef1f84bSDavid du Colombier dirbuf += BIT16SZ; /* skip count */
11739ef1f84bSDavid du Colombier PBIT16(dirbuf, r);
11749ef1f84bSDavid du Colombier dirbuf += BIT16SZ;
11759ef1f84bSDavid du Colombier PBIT32(dirbuf, c->devno);
11769ef1f84bSDavid du Colombier }
11779ef1f84bSDavid du Colombier
11789ef1f84bSDavid du Colombier int
rpcattn(void * v)11799ef1f84bSDavid du Colombier rpcattn(void *v)
11809ef1f84bSDavid du Colombier {
11819ef1f84bSDavid du Colombier Mntrpc *r;
11829ef1f84bSDavid du Colombier
11839ef1f84bSDavid du Colombier r = v;
11849ef1f84bSDavid du Colombier return r->done || r->m->rip == 0;
11859ef1f84bSDavid du Colombier }
11869ef1f84bSDavid du Colombier
11879ef1f84bSDavid du Colombier Dev mntdevtab = {
11889ef1f84bSDavid du Colombier 'M',
11899ef1f84bSDavid du Colombier "mnt",
11909ef1f84bSDavid du Colombier
11919ef1f84bSDavid du Colombier mntreset,
11929ef1f84bSDavid du Colombier devinit,
11939ef1f84bSDavid du Colombier devshutdown,
11949ef1f84bSDavid du Colombier mntattach,
11959ef1f84bSDavid du Colombier mntwalk,
11969ef1f84bSDavid du Colombier mntstat,
11979ef1f84bSDavid du Colombier mntopen,
11989ef1f84bSDavid du Colombier mntcreate,
11999ef1f84bSDavid du Colombier mntclose,
12009ef1f84bSDavid du Colombier mntread,
12019ef1f84bSDavid du Colombier devbread,
12029ef1f84bSDavid du Colombier mntwrite,
12039ef1f84bSDavid du Colombier devbwrite,
12049ef1f84bSDavid du Colombier mntremove,
12059ef1f84bSDavid du Colombier mntwstat,
12069ef1f84bSDavid du Colombier };
1207