plan 9 kernel history: overview | file list | diff list

2001/0819/port/devmnt.c (diff list | history)

2001/0808/sys/src/9/port/devmnt.c:5,102001/0819/sys/src/9/port/devmnt.c:5,21 (short | long | prev | next)
1990/0227    
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
2001/0819    
/* 
 * References are managed as follows: 
 * The channel to the server - a network connection or pipe - has one 
 * reference for every Chan open on the server.  The server channel has 
 * c->mux set to the Mnt used for muxing control to that server.  Mnts 
 * have no reference count; they go away when c goes away. 
 * Each channel derived from the mount point has mchan set to c, 
 * and increfs/decrefs mchan to manage references on the server 
 * connection. 
 */ 
 
2001/0527    
#define MAXRPC (IOHDRSZ+8192) 
 
1991/0911    
struct Mntrpc 
2001/0808/sys/src/9/port/devmnt.c:16,212001/0819/sys/src/9/port/devmnt.c:27,33
1995/0107    
	Mnt*	m;		/* Mount device during rpc */ 
1991/0911    
	Rendez	r;		/* Place to hang out */ 
2001/0527    
	uchar*	rpc;		/* I/O Data buffer */ 
2001/0819    
	uint		rpclen;	/* len of buffer */ 
2001/0619    
	Block	*b;		/* reply blocks */ 
1991/0911    
	char	done;		/* Rpc completed */ 
1998/0917    
	uvlong	stime;		/* start time for mnt statistics */ 
2001/0808/sys/src/9/port/devmnt.c:37,432001/0819/sys/src/9/port/devmnt.c:49,54
1991/0911    
}mntalloc; 
1990/0227    
 
2001/0527    
void	mattach(Mnt*, Chan*, char*); 
2001/0808    
void	mntauth(Mnt*, Mntrpc*, char*, ushort); 
2001/0527    
Mnt*	mntchk(Chan*); 
void	mntdirfix(uchar*, Chan*); 
Mntrpc*	mntflushalloc(Mntrpc*, ulong); 
2001/0808/sys/src/9/port/devmnt.c:53,622001/0819/sys/src/9/port/devmnt.c:64,73
2001/0527    
void	mountmux(Mnt*, Mntrpc*); 
void	mountrpc(Mnt*, Mntrpc*); 
int	rpcattn(void*); 
void	mclose(Mnt*, Chan*); 
Chan*	mntchan(void); 
1990/0227    
 
2001/0527    
char	Esbadstat[] = "invalid directory entry received from server"; 
2001/0819    
char Enoversion[] = "version not established for mount channel"; 
2001/0527    
 
1998/0917    
void (*mntstats)(int, Chan*, uvlong, ulong); 
1994/0513    
 
2001/0808/sys/src/9/port/devmnt.c:77,1192001/0819/sys/src/9/port/devmnt.c:88,201
1993/1015    
	cinit(); 
1990/0604    
} 
 
1997/0327    
static Chan* 
1991/0911    
mntattach(char *muxattach) 
2001/0819    
/* 
 * Version is not multiplexed: message sent only once per connection. 
 */ 
long 
mntversion(Chan *c, char *version, int msize, int returnlen) 
1990/0227    
{ 
2001/0819    
	Fcall f; 
	uchar *msg; 
1992/0620    
	Mnt *m; 
2001/0601    
	Chan *c; 
1990/0227    
	struct bogus{ 
		Chan	*chan; 
		char	*spec; 
1993/1015    
		int	flags; 
1990/0227    
	}bogus; 
2001/0819    
	char *v; 
	long k, l; 
	uvlong oo; 
	char buf[128]; 
1990/0227    
 
1991/0911    
	bogus = *((struct bogus *)muxattach); 
1992/0620    
	c = bogus.chan; 
2001/0819    
	qlock(&c->umqlock);	/* make sure no one else does this until we've established ourselves */ 
	if(waserror()){ 
		qunlock(&c->umqlock); 
		nexterror(); 
	} 
1992/0620    
 
	lock(&mntalloc); 
	for(m = mntalloc.list; m; m = m->list) { 
1993/1016    
		if(m->c == c && m->id) { 
1991/0911    
			lock(m); 
1992/0620    
			if(m->id && m->ref > 0 && m->c == c) { 
1991/0911    
				m->ref++; 
				unlock(m); 
1997/1205    
				unlock(&mntalloc); 
1993/0501    
				c = mntchan(); 
				if(waserror()) { 
2001/0527    
					chanfree(c); 
1993/0501    
					nexterror(); 
				} 
				mattach(m, c, bogus.spec); 
				poperror(); 
1993/1016    
				if(bogus.flags&MCACHE) 
					c->flag |= CCACHE; 
1993/0501    
				return c; 
1991/0911    
			} 
1998/0512    
			unlock(m); 
2001/0819    
	/* defaults */ 
	if(msize == 0) 
		msize = MAXRPC-IOHDRSZ; 
	v = version; 
	if(v == nil || v[0] == '\0') 
		v = VERSION9P; 
 
	/* validity */ 
	if(msize < 0) 
		error("bad iounit in version call"); 
	if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0) 
		error("bad 9P version specification"); 
 
	m = c->mux; 
 
	if(m != nil){ 
		qunlock(&c->umqlock); 
		poperror(); 
 
		strecpy(buf, buf+sizeof buf, m->version); 
		k = strlen(buf); 
		if(strncmp(buf, v, k) != 0){ 
			snprint(buf, sizeof buf, "incompatible 9P versions %s %s", m->version, v); 
			error(buf); 
1991/0911    
		} 
2001/0819    
		if(returnlen > 0){ 
			if(returnlen < k) 
				error(Eshort); 
			memmove(version, buf, k); 
		} 
		return k; 
1991/0901    
	} 
1993/1015    
 
2001/0819    
	f.type = Tversion; 
	f.tag = NOTAG; 
	f.msize = msize; 
	f.version = v; 
	msg = malloc(8192+IOHDRSZ); 
	if(msg == nil) 
		exhausted("version memory"); 
	if(waserror()){ 
		free(msg); 
		nexterror(); 
	} 
	k = convS2M(&f, msg, 8192+IOHDRSZ); 
	if(k == 0) 
		error("bad fversion conversion on send"); 
 
	lock(c); 
	oo = c->offset; 
	c->offset += k; 
	unlock(c); 
 
	l = devtab[c->type]->write(c, msg, k, oo); 
 
	if(l < k){ 
		lock(c); 
		c->offset -= k - l; 
		unlock(c); 
		error("short write in fversion"); 
	} 
 
	/* message sent; receive and decode reply */ 
	k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset); 
	if(k <= 0) 
		error("EOF receiving fversion reply"); 
 
	lock(c); 
	c->offset += k; 
	unlock(c); 
 
	l = convM2S(msg, k, &f); 
	if(l != k) 
		error("bad fversion conversion on reply"); 
	if(f.type != Rversion) 
		error("unexpected reply type in fversion"); 
	if(f.msize > msize) 
		error("server tries to increase msize in fversion"); 
	if(f.msize<256 || f.msize>1024*1024) 
		error("nonsense value of msize in fversion"); 
	if(strncmp(f.version, v, strlen(f.version)) != 0) 
		error("bad 9P version returned from server"); 
	c->iounit = f.msize; 
	if(c->iounit == 0) 
		c->iounit = MAXRPC; 
 
	/* now build Mnt associated with this connection */ 
	lock(&mntalloc); 
1991/0911    
	m = mntalloc.mntfree; 
1992/0620    
	if(m != 0) 
1998/0512    
		mntalloc.mntfree = m->list; 
2001/0808/sys/src/9/port/devmnt.c:126,1522001/0819/sys/src/9/port/devmnt.c:208,260
1992/0620    
	} 
	m->list = mntalloc.list; 
	mntalloc.list = m; 
2001/0819    
	kstrdup(&m->version, f.version); 
1991/0911    
	m->id = mntalloc.id++; 
2001/0619    
	m->q = qopen(10*MAXRPC, 0, nil, nil); 
1991/0911    
	unlock(&mntalloc); 
1992/0620    
 
2001/0819    
	poperror();	/* msg */ 
	free(msg); 
 
1997/1205    
	lock(m); 
1991/0904    
	m->ref = 1; 
1991/0911    
	m->queue = 0; 
	m->rip = 0; 
2001/0819    
 
	c->flag |= CMSG; 
	c->mux = m; 
1992/0620    
	m->c = c; 
1991/1011    
	m->c->flag |= CMSG; 
2001/0527    
	if(m->c->iounit == 0) 
		m->c->iounit = MAXRPC; 
1993/1016    
	m->flags = bogus.flags & ~MCACHE; 
2001/0819    
	unlock(m); 
1991/0911    
 
	incref(m->c); 
2001/0819    
	poperror();	/* c */ 
	qunlock(&c->umqlock); 
1993/0501    
 
1990/0227    
	unlock(m); 
2001/0819    
	k = strlen(f.version); 
	if(returnlen > 0){ 
		if(returnlen < k) 
			error(Eshort); 
		memmove(version, f.version, k); 
	} 
1990/0604    
 
2001/0819    
	return k; 
} 
 
Chan* 
mntauth(Chan *c, char *spec) 
{ 
	Mnt *m; 
	Mntrpc *r; 
 
	m = c->mux; 
 
	if(m == nil){ 
		mntversion(c, VERSION9P, MAXRPC, 0); 
		m = c->mux; 
		if(m == nil) 
			error(Enoversion); 
	} 
 
1993/0501    
	c = mntchan(); 
1992/0320    
	if(waserror()) { 
1993/0501    
		mclose(m, c); 
2001/0527    
		/* Close must not be called since it will 
		 * call mnt recursively 
		 */ 
2001/0808/sys/src/9/port/devmnt.c:154,1882001/0819/sys/src/9/port/devmnt.c:262,330
1992/0320    
		nexterror(); 
	} 
 
1993/0501    
	mattach(m, c, bogus.spec); 
	poperror(); 
2001/0819    
	r = mntralloc(0, m->c->iounit); 
1993/0321    
 
1993/1016    
	if(bogus.flags & MCACHE) 
		c->flag |= CCACHE; 
2001/0819    
	if(waserror()) { 
		mntfree(r); 
		nexterror(); 
	} 
1993/1016    
 
1992/0320    
	return c; 
1991/0911    
} 
2001/0819    
	r->request.type = Tauth; 
	r->request.afid = c->fid; 
	r->request.uname = up->user; 
	r->request.aname = spec; 
	mountrpc(m, r); 
1990/0604    
 
2001/0527    
Chan* 
1993/0501    
mntchan(void) 
1991/0911    
{ 
	Chan *c; 
2001/0819    
	c->qid = r->reply.aqid; 
	c->mchan = m->c; 
	incref(m->c); 
	c->mqid = c->qid; 
	c->mode = ORDWR; 
1991/0911    
 
2001/0527    
	c = devattach('M', 0); 
1991/0918    
	lock(&mntalloc); 
	c->dev = mntalloc.id++; 
	unlock(&mntalloc); 
2001/0819    
	poperror();	/* r */ 
	mntfree(r); 
1993/0501    
 
2001/0819    
	poperror();	/* c */ 
 
1993/0501    
	return c; 
2001/0819    
 
1993/0501    
} 
 
2001/0527    
void 
1993/0501    
mattach(Mnt *m, Chan *c, char *spec) 
2001/0819    
static Chan* 
mntattach(char *muxattach) 
1993/0501    
{ 
2001/0819    
	Mnt *m; 
	Chan *c; 
1993/0501    
	Mntrpc *r; 
2001/0819    
	struct bogus{ 
		Chan	*chan; 
		Chan	*authchan; 
		char	*spec; 
		int	flags; 
	}bogus; 
1993/0501    
 
2001/0819    
	bogus = *((struct bogus *)muxattach); 
	c = bogus.chan; 
 
	m = c->mux; 
 
	if(m == nil){ 
		mntversion(c, nil, 0, 0); 
		m = c->mux; 
		if(m == nil) 
			error(Enoversion); 
	} 
 
	c = mntchan(); 
	if(waserror()) { 
		/* Close must not be called since it will 
		 * call mnt recursively 
		 */ 
		chanfree(c); 
		nexterror(); 
	} 
 
2001/0527    
	r = mntralloc(0, m->c->iounit); 
1992/0620    
	c->mntptr = m; 
1991/0911    
 
1994/1212    
	if(waserror()) { 
1992/0314    
		mntfree(r); 
2001/0808/sys/src/9/port/devmnt.c:191,2102001/0819/sys/src/9/port/devmnt.c:333,376
1992/0314    
 
1991/0911    
	r->request.type = Tattach; 
	r->request.fid = c->fid; 
2001/0819    
	if(bogus.authchan == nil) 
		r->request.afid = NOFID; 
	else 
		r->request.afid = bogus.authchan->fid; 
2001/0527    
	r->request.uname = up->user; 
	r->request.aname = spec; 
2001/0808    
	r->request.nauth = 0; 
	r->request.auth = (uchar*)""; 
2001/0819    
	r->request.aname = bogus.spec; 
1991/0911    
	mountrpc(m, r); 
 
	c->qid = r->reply.qid; 
	c->mchan = m->c; 
2001/0819    
	incref(m->c); 
1990/0303    
	c->mqid = c->qid; 
1993/0501    
 
1990/0227    
	poperror(); 
2001/0819    
	poperror();	/* r */ 
1991/0911    
	mntfree(r); 
2001/0819    
 
	poperror();	/* c */ 
 
	if(bogus.flags&MCACHE) 
		c->flag |= CCACHE; 
	return c; 
1992/0318    
} 
 
2001/0819    
Chan* 
mntchan(void) 
{ 
	Chan *c; 
 
	c = devattach('M', 0); 
	lock(&mntalloc); 
	c->dev = mntalloc.id++; 
	unlock(&mntalloc); 
 
	if(c->mchan) 
		panic("mntchan non-zero %p", c->mchan); 
	return c; 
} 
 
2001/0527    
static Walkqid* 
mntwalk(Chan *c, Chan *nc, char **name, int nname) 
1990/0227    
{ 
2001/0808/sys/src/9/port/devmnt.c:213,2182001/0819/sys/src/9/port/devmnt.c:379,386
1991/0911    
	Mntrpc *r; 
2001/0527    
	Walkqid *wq; 
2001/0601    
 
2001/0819    
	if(nc != nil) 
		print("mntwalk: nc != nil\n"); 
2001/0527    
	if(nname > MAXWELEM) 
		error("devmnt: too many name elements"); 
	alloc = 0; 
2001/0808/sys/src/9/port/devmnt.c:268,2742001/0819/sys/src/9/port/devmnt.c:436,443
2001/0527    
	if(wq->clone != nil){ 
		if(wq->clone != c){ 
			wq->clone->type = c->type; 
			incref(m); 
2001/0819    
			wq->clone->mchan = c->mchan; 
			incref(c->mchan); 
2001/0527    
		} 
		if(r->reply.nwqid > 0) 
			wq->clone->qid = r->reply.wqid[r->reply.nwqid-1]; 
2001/0808/sys/src/9/port/devmnt.c:377,3832001/0819/sys/src/9/port/devmnt.c:546,551
2001/0527    
	r = mntralloc(c, m->c->iounit); 
1991/0911    
	if(waserror()){ 
1993/0501    
		mntfree(r); 
		mclose(m, c); 
1991/1004    
		nexterror(); 
1991/0911    
	} 
1990/0227    
 
2001/0808/sys/src/9/port/devmnt.c:385,4082001/0819/sys/src/9/port/devmnt.c:553,571
1991/0911    
	r->request.fid = c->fid; 
	mountrpc(m, r); 
1993/0501    
	mntfree(r); 
	mclose(m, c); 
1991/1004    
	poperror(); 
} 
 
2001/0527    
void 
1999/0714    
mclose(Mnt *m, Chan*) 
2001/0819    
muxclose(Mnt *m) 
1991/1004    
{ 
1993/0321    
	Mntrpc *q, *r; 
1991/1004    
 
1993/0321    
	if(decref(m) != 0) 
		return; 
                 
	for(q = m->queue; q; q = r) { 
		r = q->list; 
		mntfree(q); 
	} 
	m->id = 0; 
1997/0327    
	cclose(m->c); 
1993/0321    
	mntpntfree(m); 
} 
 
2001/0808/sys/src/9/port/devmnt.c:853,8632001/0819/sys/src/9/port/devmnt.c:1016,1038
1999/0212    
			unlock(&mntalloc); 
1992/0620    
			exhausted("mount rpc buffer"); 
1991/0911    
		} 
2001/0819    
		new->rpclen = iounit; 
1992/0620    
		new->request.tag = mntalloc.rpctag++; 
1991/0904    
	} 
1999/0212    
	else { 
		mntalloc.rpcfree = new->list; 
		mntalloc.nrpcfree--; 
2001/0819    
		if(new->rpclen < iounit){ 
			free(new->rpc); 
			new->rpc = mallocz(iounit, 0); 
			if(new->rpc == nil){ 
				free(new); 
				mntalloc.nrpcused--; 
				unlock(&mntalloc); 
				exhausted("mount rpc buffer"); 
			} 
			new->rpclen = iounit; 
		} 
1999/0212    
	} 
	mntalloc.nrpcused++; 
1992/0620    
	unlock(&mntalloc); 
2001/0808/sys/src/9/port/devmnt.c:911,9232001/0819/sys/src/9/port/devmnt.c:1086,1106
1991/0911    
{ 
	Mnt *m; 
 
1992/0620    
	m = c->mntptr; 
2001/0819    
	/* This routine is mostly vestiges of prior lives; now it's just sanity checking */ 
1993/0501    
 
2001/0819    
	if(c->mchan == nil) 
		panic("mntchk 1: nil mchan c %s\n", c2name(c)); 
 
	m = c->mchan->mux; 
 
	if(m == nil) 
		print("mntchk 2: nil mux c %s c->mchan %s \n", c2name(c), c2name(c->mchan)); 
 
1993/0501    
	/* 
	 * Was it closed and reused 
2001/0819    
	 * Was it closed and reused (was error(Eshutdown); now, it can't happen) 
1993/0501    
	 */ 
	if(m->id == 0 || m->id >= c->dev) 
1990/11211    
		error(Eshutdown); 
2001/0819    
		panic("mntchk 3: can't happen"); 
1993/0501    
 
1991/0911    
	return m; 
1990/0717    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)