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

1993/0501/port/devmnt.c (diff list | history)

1993/0417/sys/src/9/port/devmnt.c:6,141993/0501/sys/src/9/port/devmnt.c:6,14 (short | long | prev | next)
1992/0111    
#include	"../port/error.h" 
1990/0227    
#include	"devtab.h" 
 
1991/0911    
typedef struct Mntrpc Mntrpc; 
struct Mntrpc 
1990/0227    
{ 
1993/0501    
	Chan	*c;		/* Channel for whom we are working */ 
1991/0911    
	Mntrpc	*list;		/* Free/pending list */ 
	Fcall	request;	/* Outgoing file system protocol message */ 
	Fcall	reply;		/* Incoming reply */ 
1993/0417/sys/src/9/port/devmnt.c:21,441993/0501/sys/src/9/port/devmnt.c:21,30
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 */ 
1993/0321    
	char	mux;		/* Set if the device 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; 
1992/0620    
	Mnt	*list;		/* Mount devices in used */ 
1993/0501    
	Mnt	*list;		/* Mount devices in use */ 
1992/0620    
	Mnt	*mntfree;	/* Free list */ 
1991/0911    
	Mntrpc	*rpcfree; 
	int	id; 
1993/0417/sys/src/9/port/devmnt.c:48,631993/0501/sys/src/9/port/devmnt.c:34,49
1992/0613    
#define MAXRPC		(MAXFDATA+MAXMSG) 
1991/0911    
#define limit(n, max)	(n > max ? max : n) 
1990/0227    
 
1993/0330    
Chan*	mattach(Mnt*, char*); 
1993/0501    
void	mattach(Mnt*, Chan*, char*); 
void	mntauth(Mnt *, Mntrpc *, char *, ushort); 
1992/0825    
Mnt*	mntchk(Chan*); 
1991/0911    
void	mntdirfix(uchar*, Chan*); 
1991/1004    
void	mntdoclunk(Mnt *, Mntrpc *); 
1992/0825    
int	mntflush(Mnt*, Mntrpc*); 
void	mntfree(Mntrpc*); 
void	mntgate(Mnt*); 
1992/0320    
void	mntpntfree(Mnt*); 
1992/0825    
void	mntqrm(Mnt*, Mntrpc*); 
Mntrpc*	mntralloc(void); 
1993/0501    
Mntrpc*	mntralloc(Chan*); 
1992/0825    
long	mntrdwr(int , Chan*, void*,long , ulong); 
void	mntrpcread(Mnt*, Mntrpc*); 
void	mountio(Mnt*, Mntrpc*); 
1993/0417/sys/src/9/port/devmnt.c:64,701993/0501/sys/src/9/port/devmnt.c:50,58
1992/0825    
void	mountmux(Mnt*, Mntrpc*); 
void	mountrpc(Mnt*, Mntrpc*); 
int	rpcattn(Mntrpc*); 
1993/0321    
void	mclose(Mnt*); 
1993/0501    
void	mclose(Mnt*, Chan*); 
void	mntrecover(Mnt*, Mntrpc*); 
Chan*	mntchan(void); 
1990/0227    
 
1991/0911    
enum 
1990/0303    
{ 
1993/0417/sys/src/9/port/devmnt.c:92,1001993/0501/sys/src/9/port/devmnt.c:80,90
1990/0227    
{ 
1992/0620    
	Mnt *m; 
1993/0321    
	Chan *c, *mc; 
1993/0501    
	char buf[NAMELEN]; 
1990/0227    
	struct bogus{ 
		Chan	*chan; 
		char	*spec; 
1993/0501    
		char	recov; 
1990/0227    
	}bogus; 
 
1991/0911    
	bogus = *((struct bogus *)muxattach); 
1993/0417/sys/src/9/port/devmnt.c:108,1191993/0501/sys/src/9/port/devmnt.c:98,115
1992/0620    
				unlock(&mntalloc); 
1991/0911    
				m->ref++; 
				unlock(m); 
1993/0330    
				return mattach(m, bogus.spec); 
1993/0501    
				c = mntchan(); 
				if(waserror()) { 
					chanfree(c); 
					nexterror(); 
				} 
				mattach(m, c, bogus.spec); 
				poperror(); 
				return c; 
1991/0911    
			} 
			unlock(m);	 
		} 
1991/0901    
	} 
1993/0321    
                 
1991/0911    
	m = mntalloc.mntfree; 
1992/0620    
	if(m != 0) 
		mntalloc.mntfree = m->list;	 
1993/0417/sys/src/9/port/devmnt.c:137,1431993/0501/sys/src/9/port/devmnt.c:133,140
1991/0911    
	m->rip = 0; 
1992/0620    
	m->c = c; 
1991/1011    
	m->c->flag |= CMSG; 
1992/0915    
	m->blocksize = MAXFDATA;/**/ 
1993/0501    
	m->blocksize = MAXFDATA;	/**/ 
	m->recov = bogus.recov; 
1991/0911    
 
	switch(devchar[m->c->type]) { 
	default: 
1993/0417/sys/src/9/port/devmnt.c:148,2081993/0501/sys/src/9/port/devmnt.c:145,214
1992/0317    
		break; 
1991/0911    
	} 
	incref(m->c); 
1993/0501    
 
	sprint(buf, "#M%d", m->id); 
	m->tree.root = ptenter(&m->tree, 0, buf); 
 
1990/0227    
	unlock(m); 
1990/0604    
 
1993/0501    
	c = mntchan(); 
1992/0320    
	if(waserror()) { 
1993/0321    
		mclose(m); 
1993/0501    
		mclose(m, c); 
		/* Close must not be called since it will 
		 * call mnt recursively 
		 */ 
		chanfree(c); 
1992/0320    
		nexterror(); 
	} 
 
1993/0330    
	c = mattach(m, bogus.spec); 
1993/0501    
	mattach(m, c, bogus.spec); 
	poperror(); 
1993/0321    
 
1993/0330    
	/* 
	 *  If exportfs mounts on behalf of a local devmnt, the mount 
	 *  point is folded onto the original channel to preserve a single 
	 *  fid/tag space.  CHDIR is cleared by exportfs to indicate it 
	 *  is supplying the mount. 
	 */ 
1993/0321    
	mc = m->c; 
1993/0323    
	if(mc->type == devno('M', 0) && (c->qid.path&CHDIR) == 0) { 
1993/0501    
		mclose(m, c); 
1993/0323    
		c->qid.path |= CHDIR; 
1993/0321    
		c->mntptr = mc->mntptr; 
1993/0323    
		c->mchan = mc->mntptr->c; 
1993/0501    
		c->mchan = c->mntptr->c; 
1993/0321    
		c->mqid = c->qid; 
1993/0501    
		c->path = c->mntptr->tree.root; 
		incref(c->path); 
1993/0321    
		incref(c->mntptr); 
		mclose(m); 
	} 
 
1992/0320    
	poperror(); 
	return c; 
1991/0911    
} 
1990/0604    
 
1991/0911    
Chan * 
1993/0330    
mattach(Mnt *m, char *spec) 
1993/0501    
Chan* 
mntchan(void) 
1991/0911    
{ 
	Chan *c; 
	Mntrpc *r; 
1993/0330    
	ulong id; 
1991/0911    
 
	r = mntralloc(); 
	c = devattach('M', spec); 
1993/0501    
	c = devattach('M', 0); 
1991/0918    
	lock(&mntalloc); 
	c->dev = mntalloc.id++; 
	unlock(&mntalloc); 
1993/0501    
 
	return c; 
} 
 
void 
mattach(Mnt *m, Chan *c, char *spec) 
{ 
	ulong id; 
	Mntrpc *r; 
 
	r = mntralloc(0); 
1992/0620    
	c->mntptr = m; 
1991/0911    
 
1992/0314    
	if(waserror()){ 
		mntfree(r); 
1993/0403    
		/* Close must not be called since 
		 * it will call mnt recursively 
		 */ 
1992/0320    
		chanfree(c); 
1992/0314    
		nexterror(); 
	} 
 
1991/0911    
	r->request.type = Tattach; 
	r->request.fid = c->fid; 
1993/0404    
	memmove(r->request.uname, u->p->user, NAMELEN); 
1993/0501    
	memmove(r->request.uname, up->user, NAMELEN); 
1991/0911    
	strncpy(r->request.aname, spec, NAMELEN); 
1993/0330    
	id = authrequest(m->c->session, &r->request); 
1991/0911    
	mountrpc(m, r); 
1993/0417/sys/src/9/port/devmnt.c:211,2191993/0501/sys/src/9/port/devmnt.c:217,227
1991/0911    
	c->qid = r->reply.qid; 
	c->mchan = m->c; 
1990/0303    
	c->mqid = c->qid; 
1993/0501    
	c->path = m->tree.root; 
	incref(c->path); 
 
1990/0227    
	poperror(); 
1991/0911    
	mntfree(r); 
1990/0227    
	return c; 
1992/0318    
} 
 
1990/0227    
Chan* 
1993/0417/sys/src/9/port/devmnt.c:224,2301993/0501/sys/src/9/port/devmnt.c:232,238
1991/0911    
	int alloc = 0; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(nc == 0) { 
1990/0227    
		nc = newchan(); 
1991/0911    
		alloc = 1; 
1993/0417/sys/src/9/port/devmnt.c:255,2641993/0501/sys/src/9/port/devmnt.c:263,273
1990/0227    
mntwalk(Chan *c, char *name) 
{ 
	Mnt *m; 
1993/0501    
	Path *op; 
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(waserror()) { 
		mntfree(r); 
		return 0; 
1993/0417/sys/src/9/port/devmnt.c:269,2741993/0501/sys/src/9/port/devmnt.c:278,292
1991/0911    
	mountrpc(m, r); 
 
	c->qid = r->reply.qid; 
1993/0501    
	op = c->path; 
	c->path = ptenter(&m->tree, op, name); 
/* ASSERT */ 
if(op->ref == 0) { 
	char buf[128]; 
	ptpath(op, buf, sizeof(buf)); 
	print("PATH: '%s' walking %s\n", op, name); 
} 
	decref(op); 
1991/0911    
 
1990/0227    
	poperror(); 
1991/0911    
	mntfree(r); 
1993/0417/sys/src/9/port/devmnt.c:282,2881993/0501/sys/src/9/port/devmnt.c:300,306
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
1993/0417/sys/src/9/port/devmnt.c:304,3101993/0501/sys/src/9/port/devmnt.c:322,328
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
1993/0417/sys/src/9/port/devmnt.c:330,3361993/0501/sys/src/9/port/devmnt.c:348,354
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
1993/0417/sys/src/9/port/devmnt.c:356,3641993/0501/sys/src/9/port/devmnt.c:374,383
1991/1004    
	Mntrpc *r; 
1991/0911    
		 
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(waserror()){ 
1991/1004    
		mntdoclunk(m, r); 
1993/0501    
		mntfree(r); 
		mclose(m, c); 
1991/1004    
		nexterror(); 
1991/0911    
	} 
1990/0227    
 
1993/0417/sys/src/9/port/devmnt.c:365,3761993/0501/sys/src/9/port/devmnt.c:384,396
1991/0911    
	r->request.type = t; 
	r->request.fid = c->fid; 
	mountrpc(m, r); 
1991/1004    
	mntdoclunk(m, r); 
1993/0501    
	mntfree(r); 
	mclose(m, c); 
1991/1004    
	poperror(); 
} 
 
void 
1993/0321    
mclose(Mnt *m) 
1993/0501    
mclose(Mnt *m, Chan *c) 
1991/1004    
{ 
1993/0321    
	Mntrpc *q, *r; 
1991/1004    
 
1993/0417/sys/src/9/port/devmnt.c:377,3821993/0501/sys/src/9/port/devmnt.c:397,405
1993/0321    
	if(decref(m) != 0) 
		return; 
 
1993/0501    
	c->path = 0; 
	ptclose(&m->tree); 
 
1993/0321    
	for(q = m->queue; q; q = r) { 
		r = q->list; 
		q->flushed = 0; 
1993/0417/sys/src/9/port/devmnt.c:388,4001993/0501/sys/src/9/port/devmnt.c:411,416
1993/0321    
} 
 
void 
mntdoclunk(Mnt *m, Mntrpc *r) 
{ 
	mntfree(r); 
	mclose(m); 
1992/0320    
} 
                 
void 
mntpntfree(Mnt *m) 
{ 
1992/0620    
	Mnt *f, **l; 
1993/0417/sys/src/9/port/devmnt.c:433,4391993/0501/sys/src/9/port/devmnt.c:449,455
1991/0911    
	Mntrpc *r; 
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	r = mntralloc(); 
1993/0501    
	r = mntralloc(c); 
1991/0911    
	if(waserror()) { 
		mntfree(r); 
1990/0227    
		nexterror(); 
1993/0417/sys/src/9/port/devmnt.c:475,4831993/0501/sys/src/9/port/devmnt.c:491,498
1990/0227    
 
1991/0911    
	m = mntchk(c); 
	uba = buf; 
1993/0417    
	cnt = 0; 
	for(;;) { 
1991/0911    
		r = mntralloc(); 
1993/0501    
	for(cnt = 0; n; n -= nr) { 
		r = mntralloc(c); 
1991/0911    
		if(waserror()) { 
			mntfree(r); 
			nexterror(); 
1993/0417/sys/src/9/port/devmnt.c:496,5031993/0501/sys/src/9/port/devmnt.c:511,517
1991/0911    
		offset += nr; 
		uba += nr; 
		cnt += nr; 
1993/0417    
		n -= nr; 
		if(nr != r->request.count || n == 0) 
1993/0501    
		if(nr != r->request.count) 
1991/0911    
			break; 
1990/0227    
	} 
1991/0911    
	return cnt; 
1993/0417/sys/src/9/port/devmnt.c:506,5261993/0501/sys/src/9/port/devmnt.c:520,550
1990/0227    
void 
1991/0911    
mountrpc(Mnt *m, Mntrpc *r) 
1990/0604    
{ 
1992/0620    
	r->reply.tag = 0;		/* poison the old values */ 
1993/0501    
	int t; 
 
	r->reply.tag = 0; 
1992/0613    
	r->reply.type = 4; 
1992/0620    
 
1993/0501    
	while(waserror()) { 
		if(m->recov == 0) 
			nexterror(); 
		mntrecover(m, r); 
	} 
1991/0911    
	mountio(m, r); 
	if(r->reply.type == Rerror) 
1992/0112    
		error(r->reply.ename); 
1993/0501    
	poperror(); 
1992/0620    
 
1991/0911    
	if(r->reply.type == Rflush) 
1993/0501    
	t = r->reply.type; 
	switch(t) { 
	case Rerror: 
		error(r->reply.ename); 
	case Rflush: 
1992/0111    
		error(Eintr); 
1991/0911    
                 
	if(r->reply.type != r->request.type+1) { 
1992/0620    
		print("mnt: mismatched reply 0x%lux T%d R%d tags req %d fls %d rep %d\n", 
				r, r->request.type, r->reply.type, r->request.tag,  
				r->flushtag, r->reply.tag); 
                 
1993/0501    
	default: 
		if(t == r->request.type+1) 
			break; 
		print("mnt: mismatch rep 0x%lux T%d R%d rq %d fls %d rp %d\n", 
			r, t, r->reply.type, r->request.tag,  
			r->flushtag, r->reply.tag); 
1992/0113    
		error(Emountrpc); 
1990/1123    
	} 
} 
1993/0417/sys/src/9/port/devmnt.c:570,5761993/0501/sys/src/9/port/devmnt.c:594,600
1991/0911    
		if(r->done) 
			return; 
1990/1124    
	} 
1991/0911    
	m->rip = u->p; 
1993/0501    
	m->rip = up; 
1991/0911    
	unlock(m); 
	while(r->done == 0) { 
		mntrpcread(m, r); 
1993/0417/sys/src/9/port/devmnt.c:612,6181993/0501/sys/src/9/port/devmnt.c:636,642
1991/0911    
 
	lock(m); 
	m->rip = 0; 
	for(q = m->queue; q; q = q->list) 
1993/0501    
	for(q = m->queue; q; q = q->list) { 
1991/0911    
		if(q->done == 0) { 
			lock(&q->r); 
			if(q->r.p) { 
1993/0417/sys/src/9/port/devmnt.c:623,6281993/0501/sys/src/9/port/devmnt.c:647,653
1991/0911    
			} 
			unlock(&q->r); 
		} 
1993/0501    
	} 
1991/0911    
	unlock(m); 
1990/0717    
} 
1990/11211    
 
1993/0417/sys/src/9/port/devmnt.c:643,6491993/0501/sys/src/9/port/devmnt.c:668,674
1992/0305    
				dp = q->rpc; 
				q->rpc = r->rpc; 
				r->rpc = dp; 
				memmove(&q->reply, &r->reply, sizeof(Fcall)); 
1993/0501    
				q->reply = r->reply; 
1992/0305    
				q->done = 1; 
				wakeup(&q->r); 
			}else 
1993/0417/sys/src/9/port/devmnt.c:674,6801993/0501/sys/src/9/port/devmnt.c:699,705
1991/0911    
	n = convS2M(&flush, r->flush); 
 
	if(waserror()) { 
1992/0111    
		if(strcmp(u->error, Eintr) == 0) 
1993/0501    
		if(strcmp(up->error, Eintr) == 0) 
1991/0911    
			return 1; 
		mntqrm(m, r); 
		return 0; 
1993/0417/sys/src/9/port/devmnt.c:685,6911993/0501/sys/src/9/port/devmnt.c:710,716
1991/0911    
} 
1991/0901    
 
1991/0911    
Mntrpc * 
mntralloc(void) 
1993/0501    
mntralloc(Chan *c) 
1991/0911    
{ 
	Mntrpc *new; 
1991/0901    
 
1993/0417/sys/src/9/port/devmnt.c:703,7081993/0501/sys/src/9/port/devmnt.c:728,734
1992/0620    
		new->request.tag = mntalloc.rpctag++; 
1991/0904    
	} 
1992/0620    
	unlock(&mntalloc); 
1993/0501    
	new->c = c; 
1992/0620    
	new->done = 0; 
	new->flushed = 0; 
	return new; 
1993/0417/sys/src/9/port/devmnt.c:737,7421993/0501/sys/src/9/port/devmnt.c:763,820
1991/0911    
	unlock(m); 
} 
1990/0227    
 
1993/0501    
void 
recoverchan(Mnt *m, Chan *c) 
{ 
	int i, n, flg; 
	Path *safe, *p, **pav; 
 
	if(m->c == 0) 
		error(Eshutdown); 
 
	flg = c->flag; 
	/* Don't recursively recover */ 
	c->flag &= ~(COPEN|CRECOV); 
 
	n = 0; 
	for(p = c->path; p; p = p->parent) 
		n++; 
	pav = smalloc(sizeof(Path*)*n); 
	i = n; 
	for(p = c->path; p; p = p->parent) 
		pav[--i] = p; 
 
	safe = c->path; 
 
	if(waserror()) { 
		c->flag = flg; 
		free(pav); 
		nexterror(); 
	} 
 
	/* Attach the fid onto the file server (sets c->path to #Mxxx) */ 
	mattach(m, c, c->xmnt->spec); 
	poperror(); 
 
	/* 
	 * c is now at the root so we free where 
	 * the chan was before the server connection was lost 
	 */ 
	decref(safe); 
 
	for(i = 1; i < n; i++) { 
		if(mntwalk(c, pav[i]->elem) == 0) { 
			free(pav); 
			/* Shut down the channel */ 
			c->dev = m->id-1; 
			error(Erecover); 
		} 
	} 
	free(pav); 
	if(flg&COPEN) 
		mntopen(c, c->mode); 
} 
 
1991/0911    
Mnt * 
mntchk(Chan *c) 
{ 
1993/0417/sys/src/9/port/devmnt.c:743,7511993/0501/sys/src/9/port/devmnt.c:821,839
1991/0911    
	Mnt *m; 
 
1992/0620    
	m = c->mntptr; 
1991/0918    
	/* Was it closed and reused ? */ 
1992/0620    
	if(m->id == 0 || m->id >= c->dev)	/* Sanity check */ 
1993/0501    
 
	/* 
	 * Was it closed and reused 
	 */ 
	if(m->id == 0 || m->id >= c->dev) 
1990/11211    
		error(Eshutdown); 
1993/0501    
 
	/* 
	 * Try and get the channel back 
	 */ 
	if((c->flag&CRECOV) && m->recprog == 0) 
		recoverchan(m, c); 
 
1991/0911    
	return m; 
1990/0717    
} 
 
1993/0417/sys/src/9/port/devmnt.c:762,7651993/0501/sys/src/9/port/devmnt.c:850,954
1991/0911    
rpcattn(Mntrpc *r) 
{ 
	return r->done || r->m->rip == 0; 
1993/0501    
} 
 
int 
recdone(Mnt *m) 
{ 
	return m->recprog == 0; 
} 
 
void 
mntrecdel(Mnt *m, Mntrpc *r) 
{ 
	Mntrpc *f, **l; 
 
	lock(m); 
	l = &m->recwait; 
	for(f = *l; f; f = f->list) { 
		if(f == r) { 
			*l = r->list; 
			break; 
		} 
	} 
	unlock(m); 
} 
 
void 
mntrecover(Mnt *m, Mntrpc *r) 
{ 
	char *ps; 
 
	lock(m); 
	if(m->recprog == 0) { 
		m->recprog = 1; 
		unlock(m); 
		chanrec(m); 
		/* 
		 * Send a message to boot via #/recover 
		 */ 
		rootrecover(m->c->path, m->tree.root->elem); 
		lock(m); 
	} 
	r->list = m->recwait; 
	m->recwait = r; 
	unlock(m); 
 
	pprint("lost server connection, wait...\n"); 
 
	ps = up->psstate; 
	up->psstate = "Recover"; 
 
	if(waserror()) { 
		up->psstate = ps; 
		mntrecdel(m, r); 
		nexterror(); 
	} 
	sleep(&r->r, recdone, m); 
	poperror(); 
 
	r->done = 0; 
	mntrecdel(m, r); 
	recoverchan(m, r->c); 
 
	up->psstate = ps; 
} 
 
void 
mntrepl(char *buf) 
{ 
	int fd; 
	Mnt *m; 
	char *p; 
	Chan *c1; 
	Mntrpc *r; 
 
	/* reply from boot is 'fd #M23' */ 
	fd = strtoul(buf, &p, 0); 
 
	p++; 
	lock(&mntalloc); 
	for(m = mntalloc.list; m; m = m->list) { 
		if(strcmp(p, m->tree.root->elem) == 0) 
			break; 
	} 
	unlock(&mntalloc); 
	if(m == 0) 
		error(Eunmount); 
 
	c1 = fdtochan(fd, ORDWR, 0, 1);	/* error check and inc ref */ 
 
	/* If the channel was posted fix it up */ 
	srvrecover(m->c, c1); 
 
	lock(m); 
	close(m->c); 
	m->c = c1; 
	m->recprog = 0; 
 
	/* Wakeup partially complete rpc */ 
	for(r = m->recwait; r; r = r->list) 
		wakeup(&r->r); 
 
	unlock(m); 
1991/0911    
} 


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