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

1991/0904/port/devmnt.c (diff list | history)

1991/0901/sys/src/9/port/devmnt.c:4,1221991/0904/sys/src/9/port/devmnt.c:4,286 (short | long | prev | next)
1990/0227    
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1991/0904    
 
1990/0227    
#include	"devtab.h" 
1991/0904    
 
1990/0227    
#include	"fcall.h" 
 
1991/0901    
typedef struct Mntrpc Mntrpc; 
typedef struct Mnt Mnt; 
1991/0904    
#define		NTAG	65536	/*  1 <= tag < NTAG */ 
1991/0812    
 
1991/0901    
struct Mntrpc 
1991/0904    
typedef struct Mnt	Mnt; 
typedef struct Mnthdr	Mnthdr; 
typedef struct MntQ	MntQ; 
 
struct Mnt 
1990/0227    
{ 
1991/0901    
	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	bfree;		/* Buffer may be freed after flush */ 
	char	flushed;	/* Flush was sent */ 
	ushort	flushtag;	/* Tag to send flush on */ 
	ushort	flushbase;	/* Base tag of flush window for this buffer */ 
	char	flush[MAXMSG];	/* Somewhere to build flush */ 
1991/0904    
	Ref;			/* for number of chans, incl. mntpt but not msg */ 
	ulong	mntid;		/* serial # */ 
	Chan	*mntpt;		/* channel in user's name space */ 
	MntQ	*q; 
1990/0227    
}; 
 
1991/0901    
struct Mnt 
1991/0904    
struct MntQ 
1990/0604    
{ 
1991/0901    
	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/0904    
	Ref; 
	QLock;			/* for access */ 
	MntQ	*next;		/* for allocation */ 
	Chan	*msg;		/* for reading and writing messages */ 
	Proc	*reader;	/* process reading response */ 
	Mnthdr	*writer;	/* queue of headers of written messages */ 
1990/0604    
}; 
 
1991/0901    
struct Mntalloc 
1991/0904    
#define	BITROUND 256 
#define	BUFSIZE	(MAXFDATA+MAXMSG) 
typedef struct Mntbuf Mntbuf; 
struct Mntbuf 
1990/0227    
{ 
1991/0904    
	Mntbuf	*next; 
	char	buf[BUFSIZE+BITROUND]; 	/* BUG */ 
}; 
 
struct 
{ 
1990/0227    
	Lock; 
1991/0901    
	Mnt	*mntfree; 
	Mnt	*mntarena; 
	Mntrpc	*rpcfree; 
	int	id; 
}mntalloc; 
1991/0904    
	Mntbuf	*free; 
}mntbufalloc; 
1990/0227    
 
1991/0901    
#define BITBOTCH	256 
#define MAXRPC		(MAXFDATA+MAXMSG+BITBOTCH) 
#define limit(n, max)	(n > max ? max : n) 
1991/0904    
struct Mnthdr 
{ 
	Mnthdr	*next;		/* in free list or writers list */ 
	Mnthdr	*prev;		/* in writers list only */ 
	char	active; 
	char	flushing;	/* a Tflush has been sent */ 
	short	seq; 
	Fcall	thdr; 
	Fcall	rhdr; 
	Rendez	r; 
	Proc	*p; 
	Mntbuf	*mbr; 
	int	readreply;	/* true if we are reader or our reply has come */ 
}; 
1990/0227    
 
1991/0901    
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/0904    
struct 
{ 
	Lock; 
	Mnthdr	*arena; 
	Mnthdr	*head; 
	Mnthdr	*tail; 
}mnthdralloc; 
1990/0227    
 
1991/0901    
enum 
1991/0904    
struct 
1990/0303    
{ 
1991/0901    
	Tagspace = 1, 
	Flushspace = 64, 
	Flushtag = 512, 
}; 
1991/0904    
	Lock; 
	QLock; 
	MntQ	*arena; 
	MntQ	*free; 
}mntqalloc; 
1990/0604    
 
1991/0904    
struct 
{ 
	Lock; 
	long	id; 
}mntid; 
 
Mnt	*mnt; 
void	mntxmit(Mnt*, Mnthdr*); 
 
Mntbuf* 
mballoc(void) 
{ 
	Mntbuf *mb; 
 
loop: 
	lock(&mntbufalloc); 
	if(mb = mntbufalloc.free){		/* assign = */ 
		mntbufalloc.free = mb->next; 
		unlock(&mntbufalloc); 
		return mb; 
	} 
	unlock(&mntbufalloc); 
	print("no mntbufs\n"); 
	if(u == 0) 
		panic("mballoc"); 
	u->p->state = Wakeme; 
	alarm(1000, wakeme, u->p); 
	sched(); 
	goto loop; 
} 
 
1990/0227    
void 
1991/0901    
mntreset(void) 
1991/0904    
mbfree(Mntbuf *mb) 
1990/0227    
{ 
1991/0901    
	Mnt *me, *md; 
	Mntrpc *re, *rd; 
	ushort tag, ftag; 
1991/0904    
	lock(&mntbufalloc); 
	mb->next = mntbufalloc.free; 
	mntbufalloc.free = mb; 
	unlock(&mntbufalloc); 
} 
1990/0227    
 
1991/0901    
	mntalloc.mntarena = ialloc(conf.nmntdev*sizeof(Mnt), 0); 
	mntalloc.mntfree = mntalloc.mntarena; 
	me = &mntalloc.mntfree[conf.nmntdev]; 
	for(md = mntalloc.mntfree; md < me; md++) 
		md->list = md+1; 
	me[-1].list = 0; 
1991/0904    
Mnthdr* 
mhalloc(Mnt *m) 
{ 
	Mnthdr *mh; 
	int seq; 
1990/0227    
 
1991/0901    
	if(conf.nmntbuf > Flushtag) { 
		print("devmnt: buffers limited to %d\n", Flushtag); 
		conf.nmntbuf = Flushtag; 
1991/0904    
loop: 
	lock(&mnthdralloc); 
	if(mh = mnthdralloc.head){		/* assign = */ 
		mnthdralloc.head = mh->next; 
		if(mnthdralloc.head) 
			mnthdralloc.head->prev = 0; 
		else 
			mnthdralloc.tail = 0; 
		unlock(&mnthdralloc); 
		mh->mbr = 0; 
		seq = ++mh->seq; 
		if(seq == (1<<7)){ 
			mh->seq = 1; 
			seq = 1; 
		} 
		mh->thdr.tag = (((mh-mnthdralloc.arena)<<7)|seq) & (NTAG-1); 
		return mh; 
1990/0227    
	} 
1991/0904    
	unlock(&mnthdralloc); 
	print("no mnthdrs\n"); 
	if(u == 0) 
		panic("mhalloc"); 
	u->p->state = Wakeme; 
	alarm(1000, wakeme, u->p); 
	sched(); 
	goto loop; 
} 
1990/0227    
 
1991/0901    
	tag = Tagspace; 
	ftag = Flushtag; 
	mntalloc.rpcfree = ialloc(conf.nmntbuf*sizeof(Mntrpc), 0); 
	re = &mntalloc.rpcfree[conf.nmntbuf]; 
	for(rd = mntalloc.rpcfree; rd < re; rd++) { 
		rd->list = rd+1; 
		rd->request.tag = tag++; 
		rd->flushbase = ftag; 
		rd->flushtag = ftag; 
		ftag += Flushspace; 
		rd->rpc = ialloc(MAXRPC, 0); 
1991/0904    
void 
mhfree(Mnthdr *mh) 
{ 
	if(mh->flushing) 
		return; 
	lock(&mnthdralloc); 
	mh->active = 0; 
	mh->thdr.tag = 0; 
	mh->next = 0; 
	mh->prev = mnthdralloc.tail; 
	if(mnthdralloc.tail) 
		mnthdralloc.tail->next = mh; 
	else 
		mnthdralloc.head = mh; 
	mnthdralloc.tail = mh; 
	unlock(&mnthdralloc); 
} 
 
MntQ* 
mqalloc(Chan *msg)	/* mntqalloc is qlocked */ 
{ 
	MntQ *q; 
 
	if(q = mntqalloc.free){		/* assign = */ 
		mntqalloc.free = q->next; 
		lock(q); 
		q->ref = 1; 
		q->msg = msg; 
		unlock(q); 
		incref(msg); 
		q->writer = 0; 
		q->reader = 0; 
		return q; 
1990/0604    
	} 
1991/0901    
	re[-1].list = 0; 
1991/0904    
	panic("no mntqs\n");			/* there MUST be enough */ 
} 
1990/0604    
 
1991/0901    
	mntalloc.id = 1; 
1991/0904    
void 
mqfree(MntQ *mq) 
{ 
	Chan *msg = 0; 
 
	lock(mq); 
	if(--mq->ref == 0){ 
		msg = mq->msg; 
		mq->msg = 0; 
		lock(&mntqalloc); 
		mq->next = mntqalloc.free; 
		mntqalloc.free = mq; 
		unlock(&mntqalloc); 
	} 
	unlock(mq); 
	if(msg)		/* after locks are down */ 
		close(msg); 
1990/0604    
} 
 
1991/0904    
Mnt* 
mntdev(Chan *c, int noerr) 
{ 
	Mnt *m; 
	int i; 
 
	m = &mnt[c->mntindex]; 
	if(m->mntid==c->dev && m->q!=0) 
		return m; 
	if(noerr) 
		return 0; 
	print("mntdev shutdown %d %d %d %lux\n", c->dev, c->mntindex, 
			m->mntid, m->q); 
	error(Eshutdown); 
} 
 
1990/0227    
void 
1991/0904    
mntreset(void) 
{ 
	int i; 
	Mntbuf *mb; 
	Mnthdr *mh; 
	MntQ *mq; 
 
	if(conf.nmnthdr > 512){ 
		print("conf.nmnthdr is %d set to 512\n", conf.nmnthdr); 
		conf.nmnthdr = 512; 
	} 
	mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0); 
 
	mb = ialloc(conf.nmntbuf*sizeof(Mntbuf), 0); 
	mntbufalloc.free = mb; 
	for(i=0; i<conf.nmntbuf; i++,mb++) 
		mb->next = mb+1; 
	--mb; 
	mb->next = 0; 
 
	mh = ialloc(conf.nmnthdr*sizeof(Mnthdr), 0); 
	mnthdralloc.arena = mh; 
	mnthdralloc.head = mh; 
	for(i=0; i<conf.nmnthdr; i++,mh++){ 
		mh->seq = 0; 
		mh->next = mh+1; 
		mh->prev = mh-1; 
	} 
	--mh; 
	mnthdralloc.tail = mh; 
	mh->next = 0; 
	mnthdralloc.head->prev = 0; 
 
	mq = ialloc(conf.nmntdev*sizeof(MntQ), 0); 
	mntqalloc.arena = mq; 
	mntqalloc.free = mq; 
	for(i=0; i<conf.nmntdev; i++,mq++) 
		mq->next = mq+1; 
	--mq; 
	mq->next = 0; 
} 
 
void 
1990/0227    
mntinit(void) 
{ 
} 
 
Chan* 
1991/0901    
mntattach(char *muxattach) 
1991/0904    
mntattach(char *crud) 
1990/0227    
{ 
1991/0901    
	Mnt *m, *e; 
1991/0904    
	int i; 
	Mnt *m, *mm; 
	Mnthdr *mh; 
	MntQ *q; 
	Chan *c, *cm; 
1990/0227    
	struct bogus{ 
		Chan	*chan; 
		char	*spec; 
1991/0901/sys/src/9/port/devmnt.c:123,1991991/0904/sys/src/9/port/devmnt.c:287,352
1990/11211    
		char	*auth; 
1990/0227    
	}bogus; 
 
1991/0901    
	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); 
				return mattach(m, bogus.spec, bogus.auth); 
			} 
			unlock(m);	 
		} 
1990/0227    
	} 
1991/0901    
	lock(&mntalloc); 
	if(mntalloc.mntfree == 0) { 
		unlock(&mntalloc); 
		error(Enomntdev); 
	} 
	m = mntalloc.mntfree; 
	mntalloc.mntfree = m->list;	 
	m->id = mntalloc.id++; 
	lock(m); 
	unlock(&mntalloc); 
1990/0227    
	m->ref = 1; 
1991/0901    
	m->queue = 0; 
	m->rip = 0; 
	m->c = bogus.chan; 
1991/0904    
	bogus = *((struct bogus *)crud); 
1991/0901    
 
	switch(devchar[m->c->type]) { 
	case 'H':			/* Hotrod */ 
	case '3':			/* BIT3 */ 
		m->mux = 1; 
		break; 
	default: 
		m->mux = 0; 
1991/0904    
	m = mnt; 
	for(i=0; i<conf.nmntdev; i++,m++){ 
		lock(m); 
		if(m->ref == 0) 
			goto Found; 
		unlock(m); 
1991/0901    
	} 
	incref(m->c); 
1991/0904    
	error(Enomntdev); 
 
    Found: 
	m->ref = 1; 
1990/0227    
	unlock(m); 
1991/0904    
	lock(&mntid); 
	m->mntid = ++mntid.id; 
	unlock(&mntid); 
	c = devattach('M', bogus.spec); 
	c->dev = m->mntid; 
	c->mntindex = m-mnt; 
	m->mntpt = c; 
	cm = bogus.chan; 
1990/0604    
 
1991/0901    
	return mattach(m, bogus.spec, bogus.auth); 
} 
1991/0904    
	/* 
	 * Look for queue to same msg channel 
	 */ 
	q = mntqalloc.arena; 
	qlock(&mntqalloc); 
	for(i=0; i<conf.nmntdev; i++,q++) 
		if(q->msg==cm){ 
			lock(q); 
			if(q->ref && q->msg==cm){ 
				m->q = q; 
				q->ref++; 
				unlock(q); 
				goto out; 
			} 
			unlock(q); 
		} 
	m->q = mqalloc(cm); 
1990/0604    
 
1991/0901    
Chan * 
mattach(Mnt *m, char *spec, char *auth) 
{ 
	Chan *c; 
	Mntrpc *r; 
                 
	r = mntralloc(); 
                 
	c = devattach('M', spec); 
	c->dev = m->id; 
	c->mntindex = m-mntalloc.mntarena; 
                 
1991/0904    
    out: 
	qunlock(&mntqalloc); 
	mh = mhalloc(m); 
1990/0227    
	if(waserror()){ 
1991/0901    
		mntfree(r); 
1991/0904    
		mhfree(mh); 
1990/0227    
		close(c); 
		nexterror(); 
	} 
1991/0901    
	r->request.type = Tattach; 
	r->request.fid = c->fid; 
	memmove(r->request.uname, u->p->pgrp->user, NAMELEN); 
	strncpy(r->request.aname, spec, NAMELEN); 
	strncpy(r->request.auth, auth, NAMELEN); 
	mountrpc(m, r); 
                 
	c->qid = r->reply.qid; 
	c->mchan = m->c; 
1991/0904    
	mh->thdr.type = Tattach; 
	mh->thdr.fid = c->fid; 
	memmove(mh->thdr.uname, u->p->pgrp->user, NAMELEN); 
	strcpy(mh->thdr.aname, bogus.spec); 
	strcpy(mh->thdr.auth, bogus.auth); 
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
	c->mchan = m->q->msg; 
1990/0303    
	c->mqid = c->qid; 
1991/0904    
	mhfree(mh); 
1990/0227    
	poperror(); 
1991/0901    
	mntfree(r); 
1990/0227    
	return c; 
} 
 
1991/0901/sys/src/9/port/devmnt.c:201,2271991/0904/sys/src/9/port/devmnt.c:354,381
1990/0227    
mntclone(Chan *c, Chan *nc) 
{ 
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
	int alloc = 0; 
1991/0904    
	Mnthdr *mh; 
	int new; 
1990/0227    
 
1991/0901    
	m = mntchk(c); 
	r = mntralloc(); 
	if(nc == 0) { 
1991/0904    
	new = 0; 
	if(nc == 0){ 
1990/0227    
		nc = newchan(); 
1991/0901    
		alloc = 1; 
1991/0904    
		new = 1; 
		if(waserror()){ 
			close(nc); 
			nexterror(); 
		} 
1990/0227    
	} 
1991/0904    
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
1990/0227    
	if(waserror()){ 
1991/0901    
		mntfree(r); 
		if(alloc) 
			close(nc); 
1991/0904    
		mhfree(mh); 
1990/0227    
		nexterror(); 
	} 
1991/0901    
                 
	r->request.type = Tclone; 
	r->request.fid = c->fid; 
	r->request.newfid = nc->fid; 
	mountrpc(m, r); 
                 
1991/0904    
	mh->thdr.type = Tclone; 
	mh->thdr.fid = c->fid; 
	mh->thdr.newfid = nc->fid; 
	mntxmit(m, mh); 
1990/0227    
	nc->type = c->type; 
	nc->dev = c->dev; 
	nc->qid = c->qid; 
1991/0901/sys/src/9/port/devmnt.c:231,2421991/0904/sys/src/9/port/devmnt.c:385,398
1990/0227    
	nc->mnt = c->mnt; 
1991/0427    
	nc->mountid = c->mountid; 
1991/0421    
	nc->aux = c->aux; 
1991/0904    
	nc->mntindex = c->mntindex; 
1990/0303    
	nc->mchan = c->mchan; 
	nc->mqid = c->qid; 
1990/0227    
	incref(m); 
1991/0901    
                 
1991/0904    
	mhfree(mh); 
1991/0901    
	poperror(); 
	mntfree(r); 
1991/0904    
	if(new) 
		poperror(); 
	incref(m); 
1990/0227    
	return nc; 
} 
 
1991/0901/sys/src/9/port/devmnt.c:244,2671991/0904/sys/src/9/port/devmnt.c:400,424
1990/0227    
mntwalk(Chan *c, char *name) 
{ 
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
1991/0904    
	Mnthdr *mh; 
	int found; 
1990/0227    
 
1991/0901    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
		return 0; 
1991/0904    
	found = 1; 
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	mh->thdr.type = Twalk; 
	mh->thdr.fid = c->fid; 
	strcpy(mh->thdr.name, name); 
	if(waserror()){	/* BUG: can check type of error? */ 
		found = 0; 
		goto Out; 
1990/0227    
	} 
1991/0901    
	r->request.type = Twalk; 
	r->request.fid = c->fid; 
	strncpy(r->request.name, name, NAMELEN); 
	mountrpc(m, r); 
                 
	c->qid = r->reply.qid; 
                 
1991/0904    
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
1990/0227    
	poperror(); 
1991/0901    
	mntfree(r); 
	return 1; 
1991/0904    
    Out: 
	mhfree(mh); 
	return found; 
1990/0227    
} 
 
void	  
1991/0901/sys/src/9/port/devmnt.c:268,2891991/0904/sys/src/9/port/devmnt.c:425,448
1990/0227    
mntstat(Chan *c, char *dp) 
{ 
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
1991/0904    
	Mnthdr *mh; 
1990/0227    
 
1991/0901    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1991/0904    
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	if(waserror()){ 
		mhfree(mh); 
1990/0227    
		nexterror(); 
	} 
1991/0901    
	r->request.type = Tstat; 
	r->request.fid = c->fid; 
	mountrpc(m, r); 
                 
	memmove(dp, r->reply.stat, DIRLEN); 
	mntdirfix((uchar*)dp, c); 
1991/0904    
	mh->thdr.type = Tstat; 
	mh->thdr.fid = c->fid; 
	mntxmit(m, mh); 
	memmove(dp, mh->rhdr.stat, DIRLEN); 
	dp[DIRLEN-4] = devchar[c->type]; 
	dp[DIRLEN-3] = 0; 
	dp[DIRLEN-2] = c->dev; 
	dp[DIRLEN-1] = c->dev>>8; 
	mhfree(mh); 
1990/0227    
	poperror(); 
1991/0901    
	mntfree(r); 
1990/0227    
} 
 
Chan* 
1991/0901/sys/src/9/port/devmnt.c:290,3141991/0904/sys/src/9/port/devmnt.c:449,472
1990/0227    
mntopen(Chan *c, int omode) 
{ 
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
1991/0904    
	Mnthdr *mh; 
1990/0227    
 
1991/0901    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1991/0904    
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	if(waserror()){ 
		mhfree(mh); 
1990/0227    
		nexterror(); 
	} 
1991/0901    
	r->request.type = Topen; 
	r->request.fid = c->fid; 
	r->request.mode = omode; 
	mountrpc(m, r); 
                 
	c->qid = r->reply.qid; 
1991/0904    
	mh->thdr.type = Topen; 
	mh->thdr.fid = c->fid; 
	mh->thdr.mode = omode; 
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
	mhfree(mh); 
	poperror(); 
1990/0227    
	c->offset = 0; 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
1991/0901    
	poperror(); 
	mntfree(r); 
1990/0227    
	return c; 
} 
 
1991/0901/sys/src/9/port/devmnt.c:316,3411991/0904/sys/src/9/port/devmnt.c:474,499
1990/0227    
mntcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
1991/0904    
	Mnthdr *mh; 
1990/0227    
 
1991/0901    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1991/0904    
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	if(waserror()){ 
		mhfree(mh); 
1990/0227    
		nexterror(); 
	} 
1991/0901    
	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; 
1991/0904    
	mh->thdr.type = Tcreate; 
	mh->thdr.fid = c->fid; 
	strcpy(mh->thdr.name, name); 
	mh->thdr.mode = omode; 
	mh->thdr.perm = perm; 
	mntxmit(m, mh); 
	c->qid = mh->rhdr.qid; 
	mhfree(mh); 
	poperror(); 
1990/0227    
	c->flag |= COPEN; 
	c->mode = openmode(omode); 
1991/0901    
	poperror(); 
	mntfree(r); 
1991/0904    
	c->qid = mh->rhdr.qid; 
1990/0227    
} 
 
void	  
1991/0901/sys/src/9/port/devmnt.c:342,3731991/0904/sys/src/9/port/devmnt.c:500,533
1990/0604    
mntclunk(Chan *c, int t) 
1990/0227    
{ 
	Mnt *m; 
1991/0901    
	Mntrpc *r, *n, *q; 
		                 
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()){ 
		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); 
		} 
		return; 
	} 
1991/0904    
	Mnthdr *mh; 
	MntQ *q; 
	int waserr; 
1990/0227    
 
1991/0901    
	r->request.type = t; 
	r->request.fid = c->fid; 
	mountrpc(m, r); 
	nexterror(); 
1991/0904    
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	mh->thdr.type = t; 
	mh->thdr.fid = c->fid; 
	waserr = 0; 
	if(waserror())		/* gotta clean up as if there wasn't */ 
		waserr = 1; 
	else 
		mntxmit(m, mh); 
	mhfree(mh); 
	if(c == m->mntpt) 
		m->mntpt = 0; 
	lock(m); 
	if(--m->ref == 0){		/* BUG: need to hang up all pending i/o */ 
		q = m->q; 
		m->q = 0; 
		m->mntid = 0; 
		unlock(m);		/* mqfree can take time */ 
		mqfree(q); 
	}else 
		unlock(m); 
	if(waserr) 
		nexterror(); 
	poperror(); 
1990/0227    
} 
 
1990/0604    
void 
1991/0901/sys/src/9/port/devmnt.c:376,4171991/0904/sys/src/9/port/devmnt.c:536,596
1990/0604    
	mntclunk(c, Tclunk); 
} 
 
1991/0901    
void	  
mntremove(Chan *c) 
1991/0904    
long 
mntreadwrite(Chan *c, void *vbuf, long n, int type, ulong offset) 
1990/0227    
{ 
1991/0901    
	mntclunk(c, Tremove); 
} 
                 
void 
mntwstat(Chan *c, char *dp) 
{ 
1990/0227    
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
1991/0904    
	Mnthdr *mh; 
	long nt, nr, count; 
	char *buf; 
1990/0227    
 
1991/0901    
	m = mntchk(c); 
	r = mntralloc(); 
	if(waserror()) { 
		mntfree(r); 
1991/0904    
	buf = vbuf; 
	count = 0; 
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	if(waserror()){ 
		mhfree(mh); 
1990/0227    
		nexterror(); 
	} 
1991/0901    
	r->request.type = Twstat; 
	r->request.fid = c->fid; 
	memmove(r->request.stat, dp, DIRLEN); 
	mountrpc(m, r); 
1991/0904    
	mh->thdr.type = type; 
	mh->thdr.fid = c->fid; 
    Loop: 
	nt = n; 
	if(nt > MAXFDATA) 
		nt = MAXFDATA; 
	mh->thdr.offset = offset; 
	mh->thdr.count = nt; 
	mh->thdr.data = buf; 
	mntxmit(m, mh); 
	nr = mh->rhdr.count; 
	offset += nr; 
	count += nr; 
	buf += nr; 
	n -= nr; 
	if(n && nr==nt) 
		goto Loop; 
	mhfree(mh); 
1990/0227    
	poperror(); 
1991/0901    
	mntfree(r); 
1991/0904    
	return count; 
1990/0227    
} 
 
long	  
1991/0411    
mntread(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1991/0901    
	uchar *p, *e; 
1991/0904    
	long i; 
	uchar *b; 
1990/0227    
 
1991/0901    
	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); 
                 
1991/0904    
	n = mntreadwrite(c, buf, n, Tread, offset); 
	if(c->qid.path & CHDIR){ 
		b = (uchar*)buf; 
		for(i=n-DIRLEN; i>=0; i-=DIRLEN){ 
			b[DIRLEN-4] = devchar[c->type]; 
			b[DIRLEN-3] = 0; 
			b[DIRLEN-2] = c->dev; 
			b[DIRLEN-1] = c->dev>>8; 
			b += DIRLEN; 
		} 
	} 
1990/0227    
	return n; 
} 
 
1991/0901/sys/src/9/port/devmnt.c:418,7321991/0904/sys/src/9/port/devmnt.c:597,968
1990/0227    
long	  
1991/0411    
mntwrite(Chan *c, void *buf, long n, ulong offset) 
1990/0227    
{ 
1991/0901    
	return mntrdwr(Twrite, c, buf, n, offset);	 
1991/0904    
	return mntreadwrite(c, buf, n, Twrite, offset); 
1990/0227    
} 
 
1991/0901    
long 
mntrdwr(int type, Chan *c, void *buf, long n, ulong offset) 
1991/0904    
void	  
mntremove(Chan *c) 
1990/0227    
{ 
1991/0904    
	mntclunk(c, Tremove); 
} 
 
void 
mntwstat(Chan *c, char *dp) 
{ 
1990/0227    
	Mnt *m; 
1991/0901    
	Mntrpc *r; 
	ulong cnt, nr; 
	char *uba; 
1991/0904    
	Mnthdr *mh; 
1990/0227    
 
1991/0901    
	r = mntralloc(); 
	m = mntchk(c); 
	if(waserror()) { 
		mntfree(r); 
1991/0904    
	m = mntdev(c, 0); 
	mh = mhalloc(m); 
	if(waserror()){ 
		mhfree(mh); 
1990/0227    
		nexterror(); 
	} 
1991/0901    
	r->request.type = type; 
	r->request.fid = c->fid; 
	r->request.offset = offset; 
	uba = buf; 
	for(cnt = 0; n; n -= nr) { 
		r->request.data = uba; 
		r->request.count = limit(n, MAXFDATA); 
		mountrpc(m, r); 
		nr = r->reply.count; 
		if(type == Tread) 
			memmove(uba, r->reply.data, nr); 
		r->request.offset += nr; 
		uba += nr; 
		cnt += nr; 
		if(nr != r->request.count) 
			break; 
	} 
1991/0904    
	mh->thdr.type = Twstat; 
	mh->thdr.fid = c->fid; 
	memmove(mh->thdr.stat, dp, DIRLEN); 
	mntxmit(m, mh); 
	mhfree(mh); 
1990/0227    
	poperror(); 
1991/0901    
	mntfree(r); 
	return cnt; 
1990/0227    
} 
 
void 
1991/0901    
mountrpc(Mnt *m, Mntrpc *r) 
1991/0904    
mntwunlink(MntQ *q, Mnthdr *w)		/* queue is locked and w is a writer */ 
1990/0604    
{ 
1991/0901    
	mountio(m, r); 
	if(r->reply.type == Rerror) 
		errors(r->reply.ename); 
	if(r->reply.type != r->request.type+1) { 
		print("devmnt: mismatched reply T%d R%d tags req %d fls %d rep %d\n", 
		r->request.type, r->reply.type, r->request.tag, r->flushtag, r->reply.tag);
			errors("protocol error"); 
1991/0904    
	if(w->next) 
		w->next->prev = w->prev; 
	if(w->prev) 
		w->prev->next = w->next; 
	else{ 
		q->writer = w->next; 
		if(q->writer) 
			q->writer->prev = 0; 
1990/1123    
	} 
} 
 
1991/0904    
/* 
 * m->q is unlocked.  Send Tflush message to flush omh->tag. 
 * Cut off all errors.   Caller will free omh 
 */ 
1990/1123    
void 
1991/0901    
mountio(Mnt *m, Mntrpc *r) 
1991/0904    
mntflush(Mnt *m, Mnthdr *omh)	/* queue is unlocked */ 
1990/1123    
{ 
1991/0901    
	int n; 
1991/0904    
	Mnthdr *mh; 
1990/1124    
 
1991/0901    
	lock(m); 
	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()) { 
		mntqrm(m, r); 
		nexterror(); 
	} 
	if((*devtab[m->c->type].write)(m->c, r->rpc, n, 0) != n) 
		error(Eshortmsg); 
	poperror(); 
                 
	if(m->mux) { 
		mntrpcread(m, r); 
1991/0904    
	if(omh->thdr.type == Tflush){ 
		omh->flushing = 0; 
1990/1124    
		return; 
1991/0808    
	} 
1990/1124    
 
1991/0901    
	/* 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; 
1991/0904    
	mh = mhalloc(m); 
	if(waserror()){ 
		omh->flushing = 0; 
		mhfree(mh); 
		return;		/* no more errors please */ 
1990/1124    
	} 
1991/0901    
	m->rip = u->p; 
	unlock(m); 
                 
	while(r->done == 0) { 
		mntrpcread(m, r); 
		mountmux(m, r); 
	} 
	mntgate(m); 
1991/0904    
	mh->thdr.type = Tflush; 
	mh->thdr.oldtag = omh->thdr.tag; 
	mntxmit(m, mh); 
	omh->flushing = 0; 
	mhfree(mh); 
	poperror(); 
1990/1124    
} 
 
void 
1991/0901    
mntrpcread(Mnt *m, Mntrpc *r) 
1991/0904    
mnterrdequeue(Mnt *m, Mnthdr *mh)	/* queue is unlocked */ 
1990/1124    
{ 
1991/0901    
	int n; 
1991/0904    
	Mnthdr *w; 
	MntQ *q; 
1990/0604    
 
1991/0901    
	for(;;) { 
		if(waserror()) { 
			if(mntflush(m, r) == 0) { 
				if(m->mux == 0) 
					mntgate(m); 
				nexterror(); 
			} 
			continue; 
1991/0904    
	mh->flushing = 1; 
	q = m->q; 
	qlock(q); 
	mh->readreply = 0; 
	/* take self from queue if necessary */ 
	if(q->reader == u->p){	/* advance a writer to reader */ 
		w = q->writer; 
		if(w){ 
			mntwunlink(q, w); 
			q->reader = w->p; 
			wakeup(&w->r); 
		}else{ 
			q->reader = 0; 
			q->writer = 0; 
1990/0604    
		} 
1991/0901    
		n = (*devtab[m->c->type].read)(m->c, r->rpc, MAXRPC, 0); 
		poperror(); 
		if(n == 0) 
			continue; 
		if(convM2S(r->rpc, &r->reply, n) != 0) 
			break; 
	} 
1991/0904    
	}else 
		mntwunlink(q, mh); 
	qunlock(q); 
	mntflush(m, mh); 
1990/0604    
} 
1990/11211    
 
1991/0901    
void 
mntgate(Mnt *m) 
1991/0904    
int 
mntreadreply(void *a) 
1990/0717    
{ 
1991/0901    
	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); 
1991/0904    
	return ((Mnthdr *)a)->readreply; 
1990/0717    
} 
1990/11211    
 
1990/0604    
void 
1991/0901    
mountmux(Mnt *m, Mntrpc *r) 
1991/0904    
mntxmit(Mnt *m, Mnthdr *mh) 
1990/0227    
{ 
1991/0901    
	Mntrpc **l, *q; 
	int done; 
	char *dp; 
1991/0904    
	ulong n; 
	Mntbuf *mbw; 
	Mnthdr *w, *ow, *h; 
	MntQ *q; 
	int qlocked, tag, written; 
1990/0227    
 
1991/0901    
	lock(m); 
	l = &m->queue; 
	for(q = *l; q; q = q->list) { 
		if(q->request.tag == r->reply.tag) { 
			if(q->flushed == 0) 
				*l = q->list; 
			q->done = 1; 
			unlock(m); 
			goto dispatch; 
1991/0904    
	if(&qlocked);	/* force qlocked not to be registerized */ 
	mh->mbr = 0; 
	mbw = mballoc(); 
	if(waserror()){			/* 1 */ 
		if(mh->mbr){ 
			mbfree(mh->mbr); 
			mh->mbr = 0; 
1991/0808    
		} 
1991/0901    
		if(q->flushtag == r->reply.tag) { 
			*l = q->list; 
			q->flushed = 0; 
			done = q->done; 
			q->done = 1; 
			unlock(m); 
			if(done == 0) { 
				r->reply.type = Rerror; 
				strcpy(r->reply.ename, errstrtab[Eintr]); 
				goto dispatch; 
			} 
			if(q->bfree) 
				mntfree(q); 
			return; 
		} 
		l = &q->list; 
1991/0904    
		mbfree(mbw); 
		nexterror(); 
1990/0227    
	} 
1991/0901    
	unlock(m); 
	return; 
1991/0904    
	n = convS2M(&mh->thdr, mbw->buf); 
	q = m->q; 
	if(q == 0) 
		error(Eshutdown); 
#ifdef	BIT3 
	/* 
	 * Bit3 and Hotrod do their own multiplexing.  (Well, the file server does.) 
	 * The code is different enough that it's broken out separately here. 
	 */ 
	if(devchar[q->msg->type]!='3' && devchar[q->msg->type]!='H') 
		goto Normal; 
1990/0604    
 
1991/0901    
dispatch: 
	if(q != r) {		/* Completed someone else */ 
		dp = q->rpc; 
		q->rpc = r->rpc; 
		r->rpc = dp; 
		memmove(&q->reply, &r->reply, sizeof(Fcall)); 
		wakeup(&q->r);					 
1991/0904    
	incref(q); 
	if(waserror()){		/* 2 */ 
		mqfree(q); 
		nexterror(); 
1990/0227    
	} 
1991/0904    
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n, 0) != n){ 
		print("short write in mntxmit\n"); 
		error(Eshortmsg); 
	} 
1990/0227    
 
1991/0901    
} 
1991/0904    
	/* 
	 * Read response 
	 */ 
	if(waserror()){		/* 3 */ 
		mntflush(m, mh); 
		nexterror(); 
	} 
	mh->mbr = mballoc(); 
	n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE, 0); 
	poperror();		/* 3 */ 
	mqfree(q); 
	poperror();		/* 2 */ 
1990/0511    
 
1991/0901    
int 
mntflush(Mnt *m, Mntrpc *r) 
{ 
	Fcall flush; 
	int n; 
1990/0511    
                 
1991/0901    
	r->flushtag++; 
	if((r->flushtag-r->flushbase) == Flushspace) 
		r->flushtag -= Flushspace; 
                 
	flush.type = Tflush; 
	flush.tag = r->flushtag; 
	flush.oldtag = r->request.tag; 
	n = convS2M(&flush, r->flush); 
                 
	if(waserror()) { 
		if(strcmp(u->error, errstrtab[Eintr]) == 0) 
			return 1; 
		mntqrm(m, r); 
		return 0; 
1991/0904    
	if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
		print("format error in mntxmit\n"); 
		error(Ebadmsg); 
1990/11211    
	} 
1991/0901    
	(*devtab[m->c->type].write)(m->c, r->flush, n, 0); 
	poperror(); 
	lock(m); 
	if(!r->done) 
		r->flushed = 1; 
	unlock(m); 
	return 1; 
} 
1990/0511    
 
1991/0901    
Mntrpc * 
mntralloc(void) 
{ 
	Mntrpc *new; 
1990/0511    
                 
1991/0901    
	for(;;) { 
		lock(&mntalloc); 
		if(new = mntalloc.rpcfree) { 
			mntalloc.rpcfree = new->list; 
			unlock(&mntalloc); 
			new->done = 0; 
			new->bfree = 0; 
			return new; 
		} 
		unlock(&mntalloc); 
		resrcwait("no mount buffers"); 
1991/0904    
	/* 
	 * Various checks 
	 */ 
	if(mh->rhdr.tag != mh->thdr.tag){ 
		print("tag mismatch %d %d\n", mh->rhdr.tag, mh->thdr.tag); 
		error(Ebadmsg); 
1990/03081    
	} 
1991/0901    
} 
1991/0904    
	if(mh->rhdr.type == Rerror){ 
		if(m->mntpt) 
			errors(mh->rhdr.ename); 
		error(Eshutdown); 
	} 
	if(mh->rhdr.type != mh->thdr.type+1){ 
		print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1); 
		error(Ebadmsg); 
	} 
	if(mh->rhdr.fid != mh->thdr.fid){ 
		print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type); 
		error(Ebadmsg); 
	} 
1991/0901    
 
void 
mntfree(Mntrpc *r) 
{ 
	Mntrpc *q; 
	Mnt *m, *e; 
	int i; 
1991/0904    
	/* 
	 * Copy out on read 
	 */ 
	if(mh->thdr.type == Tread) 
		memmove(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
	mbfree(mh->mbr); 
	mh->mbr = 0; 
	mbfree(mbw); 
	poperror();		/* 1 */ 
	return; 
1991/0901    
 
	r->bfree = 1; 
	if(r->flushed) 
		return; 
                 
	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; 
1991/0904    
    Normal: 
#endif 
	incref(q); 
	qlock(q); 
	qlocked = 1; 
	if(waserror()){		/* 2 */ 
		if(qlocked) 
			qunlock(q); 
		mqfree(q); 
		nexterror(); 
	} 
	mh->readreply = 0; 
	mh->active = 1; 
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n, 0) != n){ 
		print("short write in mntxmit\n"); 
		error(Eshortmsg); 
	} 
	if(q->reader == 0){		/* i will read */ 
		q->reader = u->p; 
    Read: 
		USED(qlocked); 
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* 3 */ 
			mnterrdequeue(m, mh); 
			nexterror(); 
1990/0703    
		} 
1991/0901    
		l = &f->list; 
1991/0904    
		mh->mbr = mballoc(); 
		do{ 
			n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE, 0); 
		}while(n == 0); 
		poperror();		/* 3 */ 
		if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ 
			/* BUG? IS THIS RIGHT? IGNORE AND RETRY */ 
			print(" MR "); 
			qlock(q); 
			qlocked = 1; 
			goto FreeRead; 
		} 
		/* 
		 * Response might not be mine 
		 */ 
		USED(qlocked); 
		qlock(q); 
		qlocked = 1; 
		tag = mh->rhdr.tag; 
		if(tag == mh->thdr.tag){	/* it's mine */ 
			if(mh->rhdr.type != Rerror) 
			if(mh->rhdr.type != mh->thdr.type+1){ 
				print("mail rob: '%s xxT(%d)%c %d %d'\n", u->p->text, 
					tag, devchar[m->q->msg->type], 
					mh->rhdr.type, mh->thdr.type+1); 
				goto FreeRead; 
			} 
			q->reader = 0; 
			if(w = q->writer){	/* advance a writer to reader */ 
				mntwunlink(q, w); 
				q->reader = w->p; 
				w->readreply = 1; 
				wakeup(&w->r); 
			} 
			mh->active = 0; 
			USED(qlocked); 
			qunlock(q); 
			qlocked = 0; 
			goto Respond; 
		} 
		/* 
		 * Hand response to correct recipient 
		 */ 
		if(tag==0 || tag>=NTAG){ 
			print("unknown tag %d\n", tag); 
	FreeRead: 
			mbfree(mh->mbr); 
			mh->mbr = 0; 
			goto Read; 
		} 
		/* 
		 * Find writer in queue 
		 */ 
		for(w=q->writer; w; w=w->next) 
			if(w->thdr.tag == tag) 
				goto Inqueue; 
		goto FreeRead; 
	Inqueue: 
		if(w->flushing || !w->active)	/* nothing to do; mntflush will clean up */ 
			goto FreeRead; 
		if(mh->rhdr.type != Rerror) 
		if(mh->rhdr.type != w->thdr.type+1){ 
			print("mail rob: '%s xxw(%d)%c %d %d'\n", 
				u->p->text, tag, devchar[m->q->msg->type], 
				mh->rhdr.type, w->thdr.type+1); 
			goto FreeRead; 
		} 
		w->mbr = mh->mbr; 
		mh->mbr = 0; 
		memmove(&w->rhdr, &mh->rhdr, sizeof mh->rhdr); 
		mntwunlink(q, w); 
		w->readreply = 1; 
		wakeup(&w->r); 
		goto Read; 
	}else{ 
		mh->p = u->p; 
		/* put self in queue */ 
		mh->next = q->writer; 
		mh->prev = 0; 
		if(q->writer) 
			q->writer->prev = mh; 
		q->writer = mh; 
		qunlock(q); 
		qlocked = 0; 
		if(waserror()){		/* interrupted sleep */ 
			mnterrdequeue(m, mh); 
			nexterror(); 
		} 
		sleep(&mh->r, mntreadreply, mh); 
		poperror(); 
		USED(qlocked); 
		qlock(q); 
		qlocked = 1; 
		mh->readreply = 0; 
		if(q->reader == u->p)	/* i got promoted */ 
			goto Read; 
		mh->active = 0; 
		USED(qlocked); 
		qunlock(q); 
		qlocked = 0; 
		goto Respond; 
1990/0227    
	} 
1991/0901    
	unlock(m); 
} 
1990/0227    
 
1991/0901    
Mnt * 
mntchk(Chan *c) 
{ 
	Mnt *m; 
                 
	m = &mntalloc.mntarena[c->mntindex]; 
	if(m->id != c->dev) 
1991/0904    
    Respond: 
	mqfree(q); 
	poperror();		/* 2 */ 
	if(mh->rhdr.type == Rerror){ 
		if(m->mntpt) 
			errors(mh->rhdr.ename); 
1990/11211    
		error(Eshutdown); 
1991/0901    
	return m; 
1991/0904    
	} 
	/* 
	 * Copy out on read 
	 */ 
	if(mh->thdr.type == Tread){ 
		if(mh->rhdr.count > mh->thdr.count) 
			error(Ebadcnt); 
		memmove(mh->thdr.data, mh->rhdr.data, mh->rhdr.count); 
	} 
	mbfree(mh->mbr); 
	mh->mbr = 0; 
	mbfree(mbw); 
	USED(qlocked); 
	poperror();		/* 1 */ 
1990/0717    
} 
 
1990/1220    
void 
1991/0901    
mntdirfix(uchar *dirbuf, Chan *c) 
1990/0717    
{ 
1991/0901    
	dirbuf[DIRLEN-4] = devchar[c->type]; 
	dirbuf[DIRLEN-3] = 0; 
	dirbuf[DIRLEN-2] = c->dev; 
	dirbuf[DIRLEN-1] = c->dev>>8; 
} 
1990/0717    
                 
1991/0901    
int 
rpcattn(Mntrpc *r) 
{ 
	return r->done || r->m->rip == 0; 
1990/0227    
} 
1991/0901    
                 
void 
mntdump(void) 
{ 
} 
1991/0904    
	int i; 
	MntQ *q; 
	Mnthdr *h; 
	Proc *p; 
1991/0901    
 
1991/0904    
	for(i=0; i<conf.nmntdev; i++){ 
		q = &mntqalloc.arena[i]; 
		if(!q->msg) 
			continue; 
		p = q->reader; 
		print("q rdr %d wrtr ", p? p->pid : 0); 
		for(h=q->writer; h; h=h->next) 
			print("(%lux %lux %d %d)", h, &h->r, h->thdr.tag, 
				(p=h->p)? p->pid : 0); 
		print("\n"); 
	} 
} 


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