kernel: devskel: use RWlock
This commit is contained in:
parent
176206fb02
commit
96cc6335db
1 changed files with 66 additions and 64 deletions
|
@ -9,15 +9,15 @@
|
||||||
|
|
||||||
typedef struct Skel Skel;
|
typedef struct Skel Skel;
|
||||||
struct Skel {
|
struct Skel {
|
||||||
|
RWlock;
|
||||||
int ref;
|
int ref;
|
||||||
QLock lk;
|
|
||||||
char name[KNAMELEN];
|
char name[KNAMELEN];
|
||||||
char mode;
|
char mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
QLock lk;
|
QLock;
|
||||||
ulong path;
|
ulong path;
|
||||||
} skelalloc;
|
} skelalloc;
|
||||||
|
|
||||||
|
@ -36,19 +36,26 @@ skelattach(char *spec)
|
||||||
|
|
||||||
c = devattach('z', spec);
|
c = devattach('z', spec);
|
||||||
|
|
||||||
f = smalloc(sizeof *f);
|
f = mallocz(sizeof *f, 1);
|
||||||
if(spec != nil && spec[0] != '\0' && strchr("de", spec[0]) != nil)
|
if(f == nil)
|
||||||
f->mode = spec[0];
|
exhausted("memory");
|
||||||
else
|
if(waserror()){
|
||||||
|
free(f);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(spec == nil)
|
||||||
f->mode = 'f';
|
f->mode = 'f';
|
||||||
|
else
|
||||||
|
f->mode = spec[0];
|
||||||
|
|
||||||
f->ref = 1;
|
eqlock(&skelalloc);
|
||||||
|
|
||||||
qlock(&skelalloc.lk);
|
|
||||||
path = skelalloc.path++;
|
path = skelalloc.path++;
|
||||||
qunlock(&skelalloc.lk);
|
qunlock(&skelalloc);
|
||||||
|
|
||||||
mkqid(&c->qid, NETQID(path, Qroot), 0, QTDIR);
|
poperror();
|
||||||
|
mkqid(&c->qid, NETQID(path, Qroot), path, QTDIR);
|
||||||
|
f->ref = 1;
|
||||||
c->aux = f;
|
c->aux = f;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -59,19 +66,25 @@ step(Chan *c, Dir *dp, int direction)
|
||||||
Skel *f;
|
Skel *f;
|
||||||
Qid qid;
|
Qid qid;
|
||||||
ulong perm;
|
ulong perm;
|
||||||
uvlong path;
|
int path;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
perm = 0555|DMDIR;
|
perm = 0555|DMDIR;
|
||||||
path = NETTYPE(c->qid.path);
|
path = NETTYPE(c->qid.path);
|
||||||
f = c->aux;
|
f = c->aux;
|
||||||
|
rlock(f);
|
||||||
|
if(waserror()){
|
||||||
|
runlock(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
name = f->name;
|
name = f->name;
|
||||||
|
|
||||||
path += direction;
|
path += direction;
|
||||||
if(!f->name[0] && path != Qroot)
|
if(!f->name[0] && path > Qroot)
|
||||||
return -1;
|
error(Enonexist);
|
||||||
|
|
||||||
switch(path){
|
switch(path){
|
||||||
|
case Qroot-1:
|
||||||
case Qroot:
|
case Qroot:
|
||||||
mkqid(&qid, Qroot, 0, QTDIR);
|
mkqid(&qid, Qroot, 0, QTDIR);
|
||||||
name = "#z";
|
name = "#z";
|
||||||
|
@ -92,27 +105,39 @@ step(Chan *c, Dir *dp, int direction)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
error(Enonexist);
|
||||||
}
|
}
|
||||||
|
|
||||||
qid.path = NETQID(NETID(c->qid.path), qid.path);
|
qid.vers = NETID(c->qid.path);
|
||||||
|
qid.path = NETQID(qid.vers, qid.path);
|
||||||
devdir(c, qid, name, 0, eve, perm, dp);
|
devdir(c, qid, name, 0, eve, perm, dp);
|
||||||
|
runlock(f);
|
||||||
|
poperror();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
skelgen(Chan *c, char *name, Dirtab *, int, int s, Dir *dp)
|
skelgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
|
||||||
{
|
{
|
||||||
Skel *f;
|
Skel *f;
|
||||||
|
|
||||||
f = c->aux;
|
switch(s){
|
||||||
//First walk away from root
|
case DEVDOTDOT:
|
||||||
if(name && !f->name[0] && f->mode != 'e' && NETTYPE(c->qid.path) == Qroot)
|
break;
|
||||||
utfecpy(f->name, &f->name[sizeof f->name-1], name);
|
case 0:
|
||||||
|
|
||||||
if(s != DEVDOTDOT)
|
|
||||||
s++;
|
s++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
f = c->aux;
|
||||||
|
if(name && NETTYPE(c->qid.path) == Qroot){
|
||||||
|
wlock(f);
|
||||||
|
if(!f->name[0] && f->mode != 'e')
|
||||||
|
utfecpy(f->name, &f->name[sizeof f->name-1], name);
|
||||||
|
wunlock(f);
|
||||||
|
}
|
||||||
|
|
||||||
return step(c, dp, s);
|
return step(c, dp, s);
|
||||||
}
|
}
|
||||||
|
@ -123,21 +148,16 @@ skelwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||||
Walkqid *wq;
|
Walkqid *wq;
|
||||||
Skel *f;
|
Skel *f;
|
||||||
|
|
||||||
f = c->aux;
|
|
||||||
qlock(&f->lk);
|
|
||||||
if(waserror()){
|
|
||||||
qunlock(&f->lk);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
|
|
||||||
wq = devwalk(c, nc, name, nname, nil, 0, skelgen);
|
wq = devwalk(c, nc, name, nname, nil, 0, skelgen);
|
||||||
if(wq != nil && wq->clone != nil && wq->clone != c){
|
if(wq == nil || wq->clone == nil)
|
||||||
if(f->ref <= 0)
|
return wq;
|
||||||
panic("devskel ref");
|
|
||||||
f->ref++;
|
f = c->aux;
|
||||||
}
|
wlock(f);
|
||||||
qunlock(&f->lk);
|
if(f->ref <= 0)
|
||||||
poperror();
|
panic("devskel ref");
|
||||||
|
f->ref++;
|
||||||
|
wunlock(f);
|
||||||
return wq;
|
return wq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,53 +181,35 @@ skelclose(Chan *c)
|
||||||
Skel *f;
|
Skel *f;
|
||||||
|
|
||||||
f = c->aux;
|
f = c->aux;
|
||||||
qlock(&f->lk);
|
wlock(f);
|
||||||
f->ref--;
|
f->ref--;
|
||||||
if(f->ref == 0){
|
if(f->ref == 0){
|
||||||
qunlock(&f->lk);
|
wunlock(f);
|
||||||
free(f);
|
free(f);
|
||||||
} else
|
} else
|
||||||
qunlock(&f->lk);
|
wunlock(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
skelread(Chan *c, void *va, long n, vlong)
|
skelread(Chan *c, void *va, long n, vlong)
|
||||||
{
|
{
|
||||||
Skel *f;
|
return devdirread(c, va, n, nil, 0, skelgen);
|
||||||
long nout;
|
|
||||||
|
|
||||||
if(!(c->qid.type & QTDIR))
|
|
||||||
error(Eperm);
|
|
||||||
|
|
||||||
f = c->aux;
|
|
||||||
qlock(&f->lk);
|
|
||||||
if(waserror()){
|
|
||||||
qunlock(&f->lk);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
nout = devdirread(c, va, n, nil, 0, skelgen);
|
|
||||||
qunlock(&f->lk);
|
|
||||||
poperror();
|
|
||||||
return nout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
skelwrite(Chan *, void *, long, vlong)
|
skelwrite(Chan*, void*, long, vlong)
|
||||||
{
|
{
|
||||||
error(Eperm);
|
error(Ebadusefd);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
skelstat(Chan *c, uchar *db, int n)
|
skelstat(Chan *c, uchar *db, int n)
|
||||||
{
|
{
|
||||||
Skel *f;
|
|
||||||
Dir dir;
|
Dir dir;
|
||||||
|
|
||||||
f = c->aux;
|
if(step(c, &dir, 0) < 0)
|
||||||
qlock(&f->lk);
|
error(Enonexist);
|
||||||
step(c, &dir, 0);
|
|
||||||
qunlock(&f->lk);
|
|
||||||
|
|
||||||
n = convD2M(&dir, db, n);
|
n = convD2M(&dir, db, n);
|
||||||
if(n < BIT16SZ)
|
if(n < BIT16SZ)
|
||||||
|
|
Loading…
Reference in a new issue