## 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
|