Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/filsys.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/filsys.c 1990/1210
## diff -e /dev/null /n/bootesdump/1990/1210/sys/src/9/port/filsys.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#include	"devtab.h"

#include	"fcall.h"

#define PRINT print

enum {
	Rreadhlen = 8,	/* number of chars in Rread message hdr */
};

typedef struct Ftrans Ftrans;

struct Ftrans{
	long	fid;
	Chan	*c;
	Chan	*pc;
};

static	Ftrans	*fsyshash;
static	Lock	fsyslock;

static	void	fsysnewchan(Chan *, long, Chan *);
static	Chan	*fsyschan(Chan *, long);
static	int	fsyserr(void);

void
filsysinit(void)
{
	fsyshash = ialloc(conf.nfsyschan * sizeof(Ftrans), 0);
}

void
filsys(Chan *protoc, char *msg, long msgn)
{
	Fcall r, t, *rf, *tf;
	Chan *c, *c0;
	long fid, n;

	if(!convM2S(msg, &r, msgn)){
		error(Ebadmsg);
	}
	rf = &r;
	tf = &t;
	if(waserror()){
		tf->type = Rerror;
		strncpy(tf->ename, u->error, sizeof(tf->ename));
		goto Errret;
	}
	fid = rf->fid;
	if(rf->type != Tattach)
		c = fsyschan(protoc, fid);
	switch(rf->type){
	case Tattach:
		c = clone(u->slash, 0);
		fsysnewchan(protoc, fid, c);
		break;
	case Tclone:
		c0 = clone(c, 0);
		c0 = domount(c0);
		fsysnewchan(protoc, rf->newfid, c0);
		break;
	case Twalk:
		if((c0 = walk(c, rf->name, 1)) == 0)
			error(Enonexist);
		if(c != c0)
			fsysnewchan(protoc, fid, c0);
		tf->qid = c0->qid;
		break;
	case Topen:
		c0 = (*devtab[c->type].open)(c, rf->mode);
		if(c != c0)
			fsysnewchan(protoc, fid, c0);
		if(rf->mode & OCEXEC)
			c0->flag |= CCEXEC;
		break;
	case Tcreate:
		if((c->flag&(CMOUNT|CCREATE)) == CMOUNT)
			c0 = createdir(c);
		(*devtab[c->type].create)(c, rf->name, rf->mode, rf->perm);
		if(rf->mode & OCEXEC)
			c->flag |= CCEXEC;
		break;
	case Tread:
		qlock(c);
		if(waserror()){
			qunlock(c);
			nexterror();
		}
		n = rf->count;
		tf->count = 0;
		/* overwrite the input msg -- assumes buffer is big enough */
		tf->data = msg+Rreadhlen;
		if(c->qid.path&CHDIR){
			n -= n%DIRLEN;
			if(c->offset%DIRLEN || n==0)
				error(Ebaddirread);
		}
		if((c->qid.path&CHDIR) && (c->flag&CMOUNT))
			n = unionread(c, tf->data, n);
		else
			n = (*devtab[c->type].read)(c, tf->data, n);
		c->offset += n;
		qunlock(c);
		poperror();
		tf->count = n;
		break;
	case Twrite:
		qlock(c);
		if(waserror()){
			qunlock(c);
			nexterror();
		}
		if(c->qid.path & CHDIR)
			error(Eisdir);
		n = rf->count;
		tf->count = 0;
		n = (*devtab[c->type].write)(c, rf->data, n);
		c->offset += n;
		qunlock(c);
		poperror();
		tf->count = n;
		break;
	case Tclunk:
		close(c);
		fsysnewchan(protoc, rf->fid, 0);
		break;
	case Tremove:
		(*devtab[c->type].remove)(c);
		break;
	case Tstat:
		(*devtab[c->type].stat)(c, tf->stat);
		break;
	case Twstat:
		(*devtab[c->type].wstat)(c, rf->stat);
		break;
	case Tflush:
		/* really, this message has to be handled by caller */
		break;
	default:
		error(Ebadmsg);
	}
	poperror();
	tf->type = rf->type+1;
   Errret:
	tf->fid = rf->fid;
	tf->tag = rf->tag;
	/* assume can reuse msg buf */
	n = convS2M(tf, msg);
	qlock(protoc);
	if(waserror()){
		qunlock(protoc);
		nexterror();
	}
	(*devtab[protoc->type].write)(protoc, msg, n);
	qunlock(protoc);
	poperror();
}

/*
 * hash table discipline: linear probe
 *    a fid of 0 means 'free'; a fid of -1 means 'deleted'
 *    use a function as per Knuth
 *    only a function of fid, but protoc checked for match
 */
static int
fhash(long fid)
{
	long x;

	x = fid*29128;
	if(x < 0)
		x = -x;
	x %= 262143;
	return x % conf.nfsyschan;
}

/*
 * Register channel c for fid (if c!= 0).
 * If c==0, unregister.
 * The protoc argument is used to disambiguate
 * identical fids from different attaches.
 */
static void
fsysnewchan(Chan *protoc, long fid, Chan *c)
{
	int i, m;
	Ftrans *f, *fstop, *fend;

	i = fhash(fid);
	f = fsyshash+i;
	m = conf.nfsyschan;
	fstop = f+(i+m-1)%m;
	fend = fsyshash+m;
	lock(&fsyslock);
	while(f != fstop){
		if(f->fid == fid && f->pc == protoc){
			if(c)
				f->c = c;
			else
				f->fid = -1;
			break;
		}
		if(f->fid <= 0){
			f->c = c;
			f->fid = fid;
			f->pc = protoc;
			break;
		}
		if(++f == fend)
			f = fsyshash;	
	}
	unlock(&fsyslock);
	if(f == fstop)
		error(Enofilsys);
}

/* Return the channel registered for fid */
static Chan*
fsyschan(Chan *protoc, long fid)
{
	int i, m;
	Ftrans *f, *fstop, *fend;

	i = fhash(fid);
	f = fsyshash+i;
	if(f->fid == fid && f->pc == protoc)
		return f->c;
	m = conf.nfsyschan;
	fstop = f;
	if(++f == fend)
		f = fsyshash;
	fend = fsyshash+m;
	while(f != fstop){
		if(f->fid == fid && f->pc == protoc)
			return f->c;
		if(f->fid == 0)
			break;
		if(++f == fend)
			f = fsyshash;	
	}
	error(Egreg);
}

.
## diffname port/filsys.c 1991/0828 # deleted
## diff -e /n/bootesdump/1990/1210/sys/src/9/port/filsys.c /n/bootesdump/1991/0828/sys/src/9/port/filsys.c
1,250d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.