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

1992/0315/port/devmnt.c (diff list | history)

1992/0315/sys/src/9/port/devmnt.c:1,8071992/0317/sys/src/9/port/devmnt.c:1,806 (short | long | prev | next)
1990/0227    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
#include	"devtab.h" 
#include	"fcall.h" 
 
1991/0911    
typedef struct Mntrpc Mntrpc; 
typedef struct Mnt Mnt; 
1991/0904    
 
1991/0911    
struct Mntrpc 
1990/0227    
{ 
1991/0911    
	Mntrpc	*list;		/* Free/pending list */ 
	Fcall	request;	/* Outgoing file system protocol message */ 
	Fcall	reply;		/* Incoming reply */ 
	Mnt	*m;		/* Mount device during rpc */ 
	Rendez	r;		/* Place to hang out */ 
	char	*rpc;		/* I/O Data buffer */ 
	char	done;		/* Rpc completed */ 
	char	flushed;	/* Flush was sent */ 
1992/0305    
	ushort	flushtag;	/* Tag flush sent on */ 
1991/0911    
	char	flush[MAXMSG];	/* Somewhere to build flush */ 
1990/0227    
}; 
 
1991/0911    
struct Mnt 
1990/0604    
{ 
1991/0911    
	Ref;			/* Count of attached channels */ 
	Chan	*c;		/* Channel to file service */ 
	Proc	*rip;		/* Reader in progress */ 
	Mntrpc	*queue;		/* Queue of pending requests on this channel */ 
	int	id;		/* Multiplexor id for channel check */ 
	Mnt	*list;		/* Free list */ 
	char	mux;		/* Set if the device aleady does the multiplexing */ 
1991/0926    
	int	blocksize;	/* read/write block size */ 
1992/0305    
	ushort	flushtag;	/* Tag to send flush on */ 
	ushort	flushbase;	/* Base tag of flush window for this buffer */ 
1990/0604    
}; 
 
1991/0911    
struct Mntalloc 
1990/0227    
{ 
	Lock; 
1991/0911    
	Mnt	*mntfree; 
	Mnt	*mntarena; 
	Mntrpc	*rpcfree; 
	Mntrpc	*rpcarena; 
	int	id; 
}mntalloc; 
1990/0227    
 
1991/0911    
#define BITBOTCH	256 
#define MAXRPC		(MAXFDATA+MAXMSG+BITBOTCH) 
#define limit(n, max)	(n > max ? max : n) 
1990/0227    
 
1991/0911    
Chan 	*mattach(Mnt*, char*, char*); 
Mntrpc	*mntralloc(void); 
void	mntfree(Mntrpc*); 
int	rpcattn(Mntrpc*); 
void	mountrpc(Mnt*, Mntrpc*); 
void	mountio(Mnt*, Mntrpc*); 
Mnt	*mntchk(Chan*); 
void	mountmux(Mnt*, Mntrpc*); 
long	mntrdwr(int , Chan*, void*,long , ulong); 
int	mntflush(Mnt*, Mntrpc*); 
void	mntqrm(Mnt*, Mntrpc*); 
void	mntdirfix(uchar*, Chan*); 
void	mntgate(Mnt*); 
void	mntrpcread(Mnt*, Mntrpc*); 
1991/1004    
void	mntdoclunk(Mnt *, Mntrpc *); 
1990/0227    
 
1991/0911    
enum 
1990/0303    
{ 
1991/0911    
	Tagspace = 1, 
1992/0305    
	Tagend = 0xfffe, 
1992/0301    
 
	ALIGN = 256,		/* Vme block mode alignment */ 
1991/0911    
}; 
1990/0604    
 
1990/0227    
void 
1991/0911    
mntreset(void) 
1990/0227    
{ 
1991/0911    
	Mnt *me, *md; 
	Mntrpc *re, *rd; 
1992/0305    
	ushort tag; 
1992/0301    
	ulong p; 
	int i; 
1990/0227    
 
1991/0911    
	mntalloc.mntarena = ialloc(conf.nmntdev*sizeof(Mnt), 0); 
	mntalloc.mntfree = mntalloc.mntarena; 
	me = &mntalloc.mntfree[conf.nmntdev]; 
1990/0227    
 
1991/0911    
	mntalloc.rpcfree = ialloc(conf.nmntbuf*sizeof(Mntrpc), 0); 
	mntalloc.rpcarena = mntalloc.rpcfree; 
	re = &mntalloc.rpcfree[conf.nmntbuf]; 
1992/0301    
 
1992/0315    
	/* 
	 *  Align mount buffers to 256 byte boundaries 
	 *  so we can use burst mode vme transfers 
	 */ 
1992/0305    
	tag = Tagspace; 
1991/0911    
	for(rd = mntalloc.rpcfree; rd < re; rd++) { 
		rd->list = rd+1; 
		rd->request.tag = tag++; 
1992/0315    
		rd->rpc = iallocspan(MAXRPC, ALIGN, 0); 
1990/0604    
	} 
1991/0911    
	re[-1].list = 0; 
1992/0305    
	for(md = mntalloc.mntfree; md < me; md++){ 
		md->list = md+1; 
		md->flushbase = tag; 
		md->flushtag = tag; 
	} 
	me[-1].list = 0; 
1990/0604    
 
1991/0911    
	mntalloc.id = 1; 
1990/0604    
} 
 
1990/0227    
void 
mntinit(void) 
{ 
} 
 
Chan* 
1991/0911    
mntattach(char *muxattach) 
1990/0227    
{ 
1991/0911    
	Mnt *m, *e; 
1990/0227    
	struct bogus{ 
		Chan	*chan; 
		char	*spec; 
1992/0312    
		char	*serv; 
1990/0227    
	}bogus; 
 
1991/0911    
	bogus = *((struct bogus *)muxattach); 
	e = &mntalloc.mntarena[conf.nmntdev]; 
	for(m = mntalloc.mntarena; m < e; m++) { 
		if(m->c == bogus.chan && m->id) { 
			lock(m); 
			if(m->ref > 0 && m->id && m->c == bogus.chan) { 
				m->ref++; 
				unlock(m); 
1992/0312    
				return mattach(m, bogus.spec, bogus.serv); 
1991/0911    
			} 
			unlock(m);	 
		} 
1991/0901    
	} 
1991/0911    
	lock(&mntalloc); 
	if(mntalloc.mntfree == 0) { 
		unlock(&mntalloc); 
1992/0114    
		exhausted("mount devices"); 
1991/0911    
	} 
	m = mntalloc.mntfree; 
	mntalloc.mntfree = m->list;	 
	m->id = mntalloc.id++; 
	lock(m); 
	unlock(&mntalloc); 
1991/0904    
	m->ref = 1; 
1991/0911    
	m->queue = 0; 
	m->rip = 0; 
	m->c = bogus.chan; 
1991/1011    
	m->c->flag |= CMSG; 
1991/0926    
	m->blocksize = MAXFDATA; 
1991/0911    
 
	switch(devchar[m->c->type]) { 
	case 'H':			/* Hotrod */ 
	case '3':			/* BIT3 */ 
		m->mux = 1; 
		break; 
	default: 
		m->mux = 0; 
1992/0317    
	case 'H':			/* Cyclone */ 
		m->mux = 1; 
		break; 
1991/0911    
	} 
	incref(m->c); 
1990/0227    
	unlock(m); 
1990/0604    
 
1992/0312    
	return mattach(m, bogus.spec, bogus.serv); 
1991/0911    
} 
1990/0604    
 
1991/0911    
Chan * 
1992/0312    
mattach(Mnt *m, char *spec, char *serv) 
1991/0911    
{ 
	Chan *c; 
	Mntrpc *r; 
1992/0312    
	char chal[8]; 
	int i; 
1991/0911    
 
	r = mntralloc(); 
	c = devattach('M', spec); 
1991/0918    
	lock(&mntalloc); 
	c->dev = mntalloc.id++; 
	unlock(&mntalloc); 
1991/0911    
	c->mntindex = m-mntalloc.mntarena; 
 
1992/0314    
	if(waserror()){ 
		mntfree(r); 
		close(c); 
		nexterror(); 
	} 
 
	if(*serv){ 
1992/0312    
		r->request.type = Tauth; 
		r->request.fid = c->fid; 
		memmove(r->request.uname, u->p->user, NAMELEN); 
		chal[0] = 1; 
		for(i = 1; i < sizeof chal; i++) 
			chal[i++] = nrand(256); 
		memmove(r->request.chal, chal, 8); 
		strncpy(r->request.chal+8, serv, NAMELEN); 
		encrypt(u->p->pgrp->crypt->key, r->request.chal, 8+NAMELEN); 
1992/0314    
		if(waserror()) 
			memset(r->request.auth, 0, sizeof r->request.auth); 
		else{ 
			mountrpc(m, r); 
			poperror(); 
			decrypt(u->p->pgrp->crypt->key, r->reply.chal, 2*8+2*DESKEYLEN); 
			chal[0] = 4; 
			if(memcmp(chal, r->reply.chal, 8) != 0) 
				error(Eperm); 
			memmove(r->request.auth, r->reply.chal+8+DESKEYLEN, 8+DESKEYLEN); 
		} 
		r->done = 0; 
		r->flushed = 0; 
1992/0312    
	}else 
		memset(r->request.auth, 0, sizeof r->request.auth); 
 
1991/0911    
	r->request.type = Tattach; 
	r->request.fid = c->fid; 
1991/1105    
	memmove(r->request.uname, u->p->user, NAMELEN); 
1991/0911    
	strncpy(r->request.aname, spec, NAMELEN); 
	mountrpc(m, r); 
 
	c->qid = r->reply.qid; 
	c->mchan = m->c; 
1990/0303    
	c->mqid = c->qid; 
1990/0227    
	poperror(); 
1991/0911    
	mntfree(r); 
1990/0227    
	return c; 
} 
 
Chan* 
mntclone(Chan *c, Chan *nc) 
{ 
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
	int alloc = 0; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
	if(nc == 0) { 
1990/0227    
		nc = newchan(); 
1991/0911    
		alloc = 1; 
1990/0227    
	} 
	if(waserror()){ 
1991/0911    
		mntfree(r); 
		if(alloc) 
			close(nc); 
1990/0227    
		nexterror(); 
	} 
1991/0911    
 
	r->request.type = Tclone; 
	r->request.fid = c->fid; 
	r->request.newfid = nc->fid; 
	mountrpc(m, r); 
 
1990/0227    
	nc->type = c->type; 
	nc->dev = c->dev; 
	nc->qid = c->qid; 
	nc->mode = c->mode; 
	nc->flag = c->flag; 
	nc->offset = c->offset; 
	nc->mnt = c->mnt; 
1991/0427    
	nc->mountid = c->mountid; 
1991/0421    
	nc->aux = c->aux; 
1990/0303    
	nc->mchan = c->mchan; 
	nc->mqid = c->qid; 
1991/0904    
	incref(m); 
1991/0911    
 
1992/0312    
	USED(alloc); 
1991/0911    
	poperror(); 
	mntfree(r); 
1990/0227    
	return nc; 
} 
 
int	  
mntwalk(Chan *c, char *name) 
{ 
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
		return 0; 
1990/0227    
	} 
1991/0911    
	r->request.type = Twalk; 
	r->request.fid = c->fid; 
	strncpy(r->request.name, name, NAMELEN); 
	mountrpc(m, r); 
 
	c->qid = r->reply.qid; 
 
1990/0227    
	poperror(); 
1991/0911    
	mntfree(r); 
	return 1; 
1990/0227    
} 
 
void	  
mntstat(Chan *c, char *dp) 
{ 
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
	} 
1991/0911    
	r->request.type = Tstat; 
	r->request.fid = c->fid; 
	mountrpc(m, r); 
 
	memmove(dp, r->reply.stat, DIRLEN); 
	mntdirfix((uchar*)dp, c); 
1990/0227    
	poperror(); 
1991/0911    
	mntfree(r); 
1990/0227    
} 
 
Chan* 
mntopen(Chan *c, int omode) 
{ 
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
	} 
1991/0911    
	r->request.type = Topen; 
	r->request.fid = c->fid; 
	r->request.mode = omode; 
	mountrpc(m, r); 
 
	c->qid = r->reply.qid; 
1990/0227    
	c->offset = 0; 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
1991/0911    
	poperror(); 
	mntfree(r); 
1990/0227    
	return c; 
} 
 
void	  
mntcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
	} 
1991/0911    
	r->request.type = Tcreate; 
	r->request.fid = c->fid; 
	r->request.mode = omode; 
	r->request.perm = perm; 
	strncpy(r->request.name, name, NAMELEN); 
	mountrpc(m, r); 
 
	c->qid = r->reply.qid; 
1990/0227    
	c->flag |= COPEN; 
	c->mode = openmode(omode); 
1991/0911    
	poperror(); 
	mntfree(r); 
1990/0227    
} 
 
void	  
1990/0604    
mntclunk(Chan *c, int t) 
1990/0227    
{ 
	Mnt *m; 
1991/1004    
	Mntrpc *r; 
1991/0911    
		 
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()){ 
1991/1004    
		mntdoclunk(m, r); 
		nexterror(); 
1991/0911    
	} 
1990/0227    
 
1991/0911    
	r->request.type = t; 
	r->request.fid = c->fid; 
	mountrpc(m, r); 
1991/1004    
	mntdoclunk(m, r); 
	poperror(); 
} 
 
void 
mntdoclunk(Mnt *m, Mntrpc *r) 
{ 
	Mntrpc *q; 
 
	mntfree(r); 
	if(decref(m) == 0) { 
		for(q = m->queue; q; q = r) { 
			r = q->list; 
			q->flushed = 0; 
			mntfree(q); 
		} 
		m->id = 0; 
		close(m->c); 
		lock(&mntalloc); 
		m->list = mntalloc.mntfree; 
		mntalloc.mntfree = m; 
		unlock(&mntalloc); 
	} 
1990/0227    
} 
 
1990/0604    
void 
mntclose(Chan *c) 
{ 
	mntclunk(c, Tclunk); 
} 
 
1991/0911    
void	  
mntremove(Chan *c) 
1990/0227    
{ 
1991/0911    
	mntclunk(c, Tremove); 
} 
 
void 
mntwstat(Chan *c, char *dp) 
{ 
1990/0227    
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
	} 
1991/0911    
	r->request.type = Twstat; 
	r->request.fid = c->fid; 
	memmove(r->request.stat, dp, DIRLEN); 
	mountrpc(m, r); 
1990/0227    
	poperror(); 
1991/0911    
	mntfree(r); 
1990/0227    
} 
 
long	  
1991/0411    
mntread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1991/0911    
	uchar *p, *e; 
1990/0227    
 
1991/0911    
	n = mntrdwr(Tread, c, buf, n, offset); 
	if(c->qid.path & CHDIR)  
		for(p = (uchar*)buf, e = &p[n]; p < e; p += DIRLEN) 
			mntdirfix(p, c); 
 
1990/0227    
	return n; 
} 
 
long	  
1991/0411    
mntwrite(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1991/0911    
	return mntrdwr(Twrite, c, buf, n, offset);	 
1990/0227    
} 
 
1991/0911    
long 
mntrdwr(int type, Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
	Mnt *m; 
1991/0911    
	Mntrpc *r; 
	ulong cnt, nr; 
	char *uba; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	uba = buf; 
	for(cnt = 0; n; n -= nr) { 
		r = mntralloc(); 
		if(waserror()) { 
			mntfree(r); 
			nexterror(); 
		} 
		r->request.type = type; 
		r->request.fid = c->fid; 
		r->request.offset = offset; 
		r->request.data = uba; 
1991/0926    
		r->request.count = limit(n, m->blocksize); 
1991/0911    
		mountrpc(m, r); 
		nr = r->reply.count; 
		if(type == Tread) 
			memmove(uba, r->reply.data, nr); 
		poperror(); 
		mntfree(r); 
		offset += nr; 
		uba += nr; 
		cnt += nr; 
		if(nr != r->request.count) 
			break; 
1990/0227    
	} 
1991/0911    
	return cnt; 
1990/0227    
} 
 
void 
1991/0911    
mountrpc(Mnt *m, Mntrpc *r) 
1990/0604    
{ 
1991/0911    
	r->reply.tag = 0;		/* safety check */ 
1992/0305    
	r->reply.type = 4;		/* safety check */ 
1991/0911    
	mountio(m, r); 
	if(r->reply.type == Rerror) 
1992/0112    
		error(r->reply.ename); 
1991/0911    
	if(r->reply.type == Rflush) 
1992/0111    
		error(Eintr); 
1991/0911    
 
	if(r->reply.type != r->request.type+1) { 
		print("devmnt: mismatched reply 0x%lux T%d R%d tags req %d fls %d rep %d\n", 
1991/0912    
		r, r->request.type, r->reply.type, r->request.tag, r->flushtag, r->reply.tag); 
1992/0113    
		error(Emountrpc); 
1990/1123    
	} 
} 
 
void 
1991/0911    
mountio(Mnt *m, Mntrpc *r) 
1990/1123    
{ 
1991/0911    
	int n; 
1990/1124    
 
1991/0911    
	lock(m); 
1992/0305    
	r->flushed = 0; 
1991/0911    
	r->m = m; 
	r->list = m->queue; 
	m->queue = r; 
	unlock(m); 
 
	/* Transmit a file system rpc */ 
	n = convS2M(&r->request, r->rpc); 
	if(waserror()) { 
1991/1011    
		if(!m->mux) 
			qunlock(&m->c->wrl); 
1991/0925    
		if(mntflush(m, r) == 0) 
			nexterror(); 
1991/0911    
	} 
1991/0925    
	else { 
1991/1011    
		if(m->mux) { 
			if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n) 
1992/0113    
				error(Emountrpc); 
1991/1011    
		} 
		else { 
			qlock(&m->c->wrl); 
			if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n) 
1992/0113    
				error(Emountrpc); 
1991/1011    
			qunlock(&m->c->wrl); 
		} 
1991/0925    
		poperror(); 
	} 
1991/0911    
	if(m->mux) { 
		mntqrm(m, r); 
		mntrpcread(m, r); 
1990/1124    
		return; 
1991/0808    
	} 
1990/1124    
 
1991/0911    
	/* Gate readers onto the mount point one at a time */ 
	for(;;) { 
		lock(m); 
		if(m->rip == 0) 
			break; 
		unlock(m); 
		if(waserror()) { 
			if(mntflush(m, r) == 0) 
				nexterror(); 
			continue; 
		} 
		sleep(&r->r, rpcattn, r); 
		poperror(); 
		if(r->done) 
			return; 
1990/1124    
	} 
1991/0911    
	m->rip = u->p; 
	unlock(m); 
	while(r->done == 0) { 
		mntrpcread(m, r); 
		mountmux(m, r); 
	} 
	mntgate(m); 
1990/1124    
} 
 
void 
1991/0911    
mntrpcread(Mnt *m, Mntrpc *r) 
1990/1124    
{ 
1991/0911    
	int n; 
1990/0604    
 
1991/0911    
	for(;;) { 
		if(waserror()) { 
1991/1011    
			if(!m->mux) 
				qunlock(&m->c->rdl); 
1991/0911    
			if(mntflush(m, r) == 0) { 
				if(m->mux == 0) 
					mntgate(m); 
				nexterror(); 
			} 
			continue; 
1990/0604    
		} 
1991/0911    
		r->reply.type = 0; 
		r->reply.tag = 0; 
1991/1011    
		if(m->mux)  
			n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0); 
		else { 
			qlock(&m->c->rdl); 
			n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0); 
			qunlock(&m->c->rdl); 
		} 
1991/0911    
		poperror(); 
		if(n == 0) 
			continue; 
		if(convM2S(r->rpc, &r->reply, n) != 0) 
			return; 
	} 
1990/0604    
} 
1990/11211    
 
1991/0911    
void 
mntgate(Mnt *m) 
1990/0717    
{ 
1991/0911    
	Mntrpc *q; 
 
	lock(m); 
	m->rip = 0; 
	for(q = m->queue; q; q = q->list) 
		if(q->done == 0) { 
			lock(&q->r); 
			if(q->r.p) { 
				unlock(&q->r); 
				unlock(m); 
				wakeup(&q->r); 
				return; 
			} 
			unlock(&q->r); 
		} 
	unlock(m); 
1990/0717    
} 
1990/11211    
 
1990/0604    
void 
1991/0911    
mountmux(Mnt *m, Mntrpc *r) 
1990/0227    
{ 
1991/0911    
	Mntrpc **l, *q; 
	char *dp; 
1990/0227    
 
1991/0911    
	lock(m); 
	l = &m->queue; 
	for(q = *l; q; q = q->list) { 
1992/0305    
		if(q->request.tag == r->reply.tag 
		|| q->flushed && q->flushtag == r->reply.tag) { 
1991/0911    
			*l = q->list; 
			unlock(m); 
1992/0305    
			if(q != r) {		/* Completed someone else */ 
				dp = q->rpc; 
				q->rpc = r->rpc; 
				r->rpc = dp; 
				memmove(&q->reply, &r->reply, sizeof(Fcall)); 
				q->done = 1; 
				wakeup(&q->r); 
			}else 
				q->done = 1; 
1991/0911    
			return; 
		} 
		l = &q->list; 
1990/0227    
	} 
1991/0911    
	unlock(m); 
} 
1990/0227    
 
1991/0911    
int 
mntflush(Mnt *m, Mntrpc *r) 
{ 
	Fcall flush; 
	int n; 
1990/0511    
 
1992/0305    
	lock(m); 
	r->flushtag = m->flushtag++; 
	if(m->flushtag == Tagend) 
		m->flushtag = m->flushbase; 
	r->flushed = 1; 
	unlock(m); 
1990/0511    
 
1991/0911    
	flush.type = Tflush; 
	flush.tag = r->flushtag; 
	flush.oldtag = r->request.tag; 
	n = convS2M(&flush, r->flush); 
 
	if(waserror()) { 
1991/1011    
		if(!m->mux) 
			qunlock(&m->c->wrl); 
1992/0111    
		if(strcmp(u->error, Eintr) == 0) 
1991/0911    
			return 1; 
		mntqrm(m, r); 
		return 0; 
1990/03081    
	} 
1991/1011    
	if(m->mux) 
		(*devtab[m->c->type].write)(m->c, r->flush, n, 0); 
	else { 
		qlock(&m->c->wrl); 
		(*devtab[m->c->type].write)(m->c, r->flush, n, 0); 
		qunlock(&m->c->wrl); 
	} 
1991/0911    
	poperror(); 
	return 1; 
} 
1991/0901    
 
1991/0911    
Mntrpc * 
mntralloc(void) 
{ 
	Mntrpc *new; 
1991/0901    
 
1991/0911    
	for(;;) { 
		lock(&mntalloc); 
		if(new = mntalloc.rpcfree) { 
			mntalloc.rpcfree = new->list; 
			unlock(&mntalloc); 
			new->done = 0; 
1992/0305    
			new->flushed = 0; 
1991/0911    
			return new; 
		} 
		unlock(&mntalloc); 
		resrcwait("no mount buffers"); 
1991/0904    
	} 
1991/0911    
} 
 
void 
mntfree(Mntrpc *r) 
{ 
	lock(&mntalloc); 
	r->list = mntalloc.rpcfree; 
	mntalloc.rpcfree = r; 
	unlock(&mntalloc); 
} 
 
void 
mntqrm(Mnt *m, Mntrpc *r) 
{ 
	Mntrpc **l, *f; 
 
	lock(m); 
	r->done = 1; 
	r->flushed = 0; 
 
	l = &m->queue; 
	for(f = *l; f; f = f->list) { 
		if(f == r) { 
			*l = r->list; 
			break; 
1990/0703    
		} 
1991/0911    
		l = &f->list; 
1990/0227    
	} 
1991/0911    
	unlock(m); 
} 
1990/0227    
 
1991/0911    
Mnt * 
mntchk(Chan *c) 
{ 
	Mnt *m; 
 
	m = &mntalloc.mntarena[c->mntindex]; 
1991/0918    
	/* Was it closed and reused ? */ 
	if(m->id == 0 || m->id >= c->dev) 
1990/11211    
		error(Eshutdown); 
1991/0911    
	return m; 
1990/0717    
} 
 
1990/1220    
void 
1991/0911    
mntdirfix(uchar *dirbuf, Chan *c) 
{ 
	dirbuf[DIRLEN-4] = devchar[c->type]; 
	dirbuf[DIRLEN-3] = 0; 
	dirbuf[DIRLEN-2] = c->dev; 
	dirbuf[DIRLEN-1] = c->dev>>8; 
} 
 
int 
rpcattn(Mntrpc *r) 
{ 
	return r->done || r->m->rip == 0; 
} 
 
void 
1991/0901    
mntdump(void) 
{ 
1991/0911    
	Mnt *me, *m; 
	Mntrpc *re, *r; 
1991/0901    
 
1991/0911    
	me = &mntalloc.mntarena[conf.nmntdev]; 
	for(m = mntalloc.mntarena; m < me; m++) { 
		if(m->ref == 0) 
1991/0904    
			continue; 
1991/0911    
		print("mount %d: mux %d queue %lux rip 0x%lux %d %s\n", m->id, m->mux, m->queue, 
			m->rip, 
			m->rip ? m->rip->pid : 0, m->rip ? m->rip->text : "no"); 
1991/0904    
	} 
1991/0911    
	print("rpcfree 0x%lux\n", mntalloc.rpcfree); 
	re = &mntalloc.rpcarena[conf.nmntbuf]; 
	for(r = mntalloc.rpcarena; r < re; r++)  
1992/0305    
		print("%.8lux %.8lux T%d R%d tags req %d fls %d rep %d d %d f %d\n", 
1991/0911    
			r, r->list, r->request.type, r->reply.type, 
			r->request.tag, r->flushtag, r->reply.tag,  
1992/0305    
			r->done, r->flushed); 
1991/0911    
 
1991/0904    
} 
1991/0911    
 


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