M bitsy/devsac.c => bitsy/devsac.c +72 -64
@@ 99,13 99,13 @@ static Sac root;
static Cache cache[CacheSize];
static ulong cacheage;
-static void sacdir(Chan *, SacDir*, char*);
+static int sacdir(Chan *, SacDir*, uchar*, int);
static ulong getl(void *p);
static Sac *saccpy(Sac *s);
-static Sac *saclookup(Sac *s, char *name);
-static int sacdirread(Chan *, char *p, long off, long cnt);
-static void loadblock(void *buf, uchar *offset, int blocksize);
-static void sacfree(Sac*);
+static Sac *saclookup(Sac *s, char *name);
+static int sacdirread(Chan *, uchar *p, long off, long cnt);
+static void loadblock(void *buf, uchar *offset, int blocksize);
+static void sacfree(Sac*);
static void
pathtoqid(ulong path, Qid *q)
@@ 119,6 119,17 @@ pathtoqid(ulong path, Qid *q)
}
static void
+omodetomode(ulong om, ulong *m)
+{
+ ulong nm;
+
+ nm = om & ~(CHDIR|CHAPPEND|CHEXCL|CHMOUNT);
+ if(om & CHDIR)
+ nm |= DMDIR;
+ *m = nm;
+}
+
+static void
sacinit(void)
{
SacHeader *hdr;
@@ 152,7 163,6 @@ sacattach(char* spec)
{
Chan *c;
int dev;
- int opath;
dev = atoi(spec);
if(dev != 0)
@@ 163,29 173,19 @@ sacattach(char* spec)
error("devsac: bad magic");
c = devattach('C', spec);
- path = getl(root.qid);
- pathtoqid(path, &c->qid;
+ pathtoqid(getl(root.qid), &c->qid);
c->dev = dev;
c->aux = saccpy(&root);
return c;
}
-static Chan*
-sacclone(Chan *c, Chan *nc)
-{
- nc = devclone(c, nc);
- nc->aux = saccpy(c->aux);
- return nc;
-}
-
static Walkqid*
sacwalk(Chan *c, Chan *nc, char **name, int nname)
{
Sac *sac;
- int i, j, alloc;
+ int j, alloc;
Walkqid *wq;
char *n;
- Dir dir;
if(nname > 0)
isdir(c);
@@ 200,26 200,35 @@ sacwalk(Chan *c, Chan *nc, char **name, int nname)
}
if(nc == nil){
nc = devclone(c);
- nc->type = 0; /* device doesn't know about this channel yet */
alloc = 1;
}
wq->clone = nc;
for(j=0; j<nname; j++){
isdir(nc);
-
- if(name[0]=='.' && name[1]==0)
- return 1;
+ n = name[j];
+ if(strcmp(n, ".") == 0){
+ wq->qid[wq->nqid++] = nc->qid;
+ continue;
+ }
sac = nc->aux;
- sac = saclookup(sac, name);
+ sac = saclookup(sac, n);
if(sac == nil) {
+ if(j == 0)
+ error(Enonexist);
strncpy(up->error, Enonexist, NAMELEN);
- return 0;
+ break;
}
nc->aux = sac;
pathtoqid(getl(sac->qid), &nc->qid);
}
- return 1;
+ poperror();
+ if(wq->nqid < nname){
+ if(alloc)
+ cclose(wq->clone);
+ wq->clone = nil;
+ }
+ return wq;
}
static Chan*
@@ 260,12 269,8 @@ sacread(Chan *c, void *a, long n, vlong voff)
buf = a;
cnt = n;
- if(c->qid.path & CHDIR){
- cnt = (cnt/DIRLEN)*DIRLEN;
- if(off%DIRLEN)
- error("i/o error");
- return sacdirread(c, buf, off, cnt);
- }
+ if(c->qid.type & QTDIR)
+ return sacdirread(c, a, off, cnt);
sac = c->aux;
length = getl(sac->length);
if(off >= length)
@@ 311,11 316,13 @@ sacclose(Chan* c)
sacfree(sac);
}
-
-static void
-sacstat(Chan *c, char *db)
+static int
+sacstat(Chan *c, uchar *db, int n)
{
- sacdir(c, c->aux, db);
+ n = sacdir(c, c->aux, db, n);
+ if(n == 0)
+ error(Ebadarg);
+ return n;
}
static Sac*
@@ 361,24 368,23 @@ sacfree(Sac *s)
free(s);
}
-static void
-sacdir(Chan *c, SacDir *s, char *buf)
+static int
+sacdir(Chan *c, SacDir *s, uchar *db, int n)
{
Dir dir;
- memmove(dir.name, s->name, NAMELEN);
- dir.qid = (Qid){getl(s->qid), 0};
- dir.mode = getl(s->mode);
+ dir.name = s->name;
+ dir.uid = s->uid;
+ dir.gid = s->gid;
+ dir.muid = s->uid;
+ pathtoqid(getl(s->qid), &dir.qid);
+ omodetomode(getl(s->mode), &dir.mode);
dir.length = getl(s->length);
- if(dir.mode &CHDIR)
- dir.length *= DIRLEN;
- memmove(dir.uid, s->uid, NAMELEN);
- memmove(dir.gid, s->gid, NAMELEN);
dir.atime = getl(s->atime);
dir.mtime = getl(s->mtime);
dir.type = devtab[c->type]->dc;
dir.dev = c->dev;
- convD2M(&dir, buf);
+ return convD2M(&dir, db, n);
}
static void
@@ 457,41 463,44 @@ sacparent(Sac *s)
return s;
}
+/* n**2 alg to read a directory */
static int
-sacdirread(Chan *c, char *p, long off, long cnt)
+sacdirread(Chan *c, uchar *p, long off, long cnt)
{
uchar *blocks;
SacDir *buf;
- int iblock, per, i, j, n, ndir;
+ int per, i, j, n, ndir;
+ long sofar;
Sac *s;
s = c->aux;
blocks = data + getl(s->blocks);
per = blocksize/sizeof(SacDir);
ndir = getl(s->length);
- off /= DIRLEN;
- cnt /= DIRLEN;
- if(off >= ndir)
- return 0;
- if(cnt > ndir-off)
- cnt = ndir-off;
- iblock = -1;
- buf = malloc(per*sizeof(SacDir));
- for(i=off; i<off+cnt; i++) {
- j = i/per;
- if(j != iblock) {
+
+ buf = malloc(blocksize);
+ sofar = 0;
+ for(j = 0; j < ndir; j++) {
+ i = j%per;
+ if(i == 0) {
n = per;
if(n > ndir-j*per)
n = ndir-j*per;
loadblock(buf, blocks + j*OffsetSize, n*sizeof(SacDir));
- iblock = j;
}
- j *= per;
- sacdir(c, buf+i-j, p);
- p += DIRLEN;
+ n = sacdir(c, buf+i, p, cnt - sofar);
+ if(n == 0)
+ break;
+ if(off > 0)
+ off -= n;
+ else {
+ p += n;
+ sofar += n;
+ }
}
free(buf);
- return cnt*DIRLEN;
+
+ return sofar;
}
static Sac*
@@ 551,7 560,6 @@ Dev sacdevtab = {
devreset,
sacinit,
sacattach,
- sacclone,
sacwalk,
sacstat,
sacopen,
M bitsy/fns.h => bitsy/fns.h +2 -1
@@ 39,6 39,7 @@ ulong inl(ulong);
void intrenable(int, int, void (*)(Ureg*, void*), void*, char*);
int iprint(char*, ...);
void irpower(int);
+#define kmapinval()
void lcdpower(int);
void links(void);
void* mapmem(ulong, int, int);
@@ 75,7 76,7 @@ void putpid(ulong);
void qpanic(char *, ...);
void rs232power(int);
void uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int));
-void sa1100_uartsetup(int);
+void sa1110_uartsetup(int);
void screeninit(void);
int screenprint(char*, ...); /* debugging */
void serialµcputs(uchar *str, int n);
M bitsy/main.c => bitsy/main.c +1 -1
@@ 35,7 35,7 @@ main(void)
mmuinit();
machinit();
trapinit();
- sa1100_uartsetup(1);
+ sa1110_uartsetup(1);
rs232power(1);
dmainit();
screeninit();
M port/chan.c => port/chan.c +58 -20
@@ 6,12 6,12 @@
#include "../port/error.h"
int chandebug=0; /* toggled by sysr1 */
+QLock chanprint; /* probably asking for trouble (deadlocks) -rsc */
/* transition BUG */
int client9p = 2;
int kernel9p = 2;
-
int domount(Chan**, Mhead**);
Ref mheadcounter;
@@ 45,13 45,26 @@ dumpmount(void) /* DEBUGGING */
f->from->qid.vers, devtab[f->from->type]->dc,
f->from->dev);
for(t = f->mount; t; t = t->next)
- print("\t%p: %s (umh %p)\n", t, t->to->name->s, t->to->umh);
+ print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);
}
}
poperror();
runlock(&pg->ns);
}
+
+char*
+c2name(Chan *c) /* DEBUGGING */
+{
+ if(c == nil)
+ return "<nil chan>";
+ if(c->name == nil)
+ return "<nil name>";
+ if(c->name->s == nil)
+ return "<nil name.s>";
+ return c->name->s;
+}
+
enum
{
CNAMESLOP = 20
@@ 225,7 238,6 @@ newchan(void)
c->link = chanalloc.list;
chanalloc.list = c;
unlock(&chanalloc);
-if(chandebug) print("newchan %d\n", c->fid);
}
/* if you get an error before associating with a dev,
@@ 676,6 688,11 @@ undomount(Chan *c, Cname *name)
he = &pg->mnthash[MNTHASH];
for(h = pg->mnthash; h < he; h++) {
for(f = *h; f; f = f->hash) {
+ if(strcmp(f->from->name->s, name->s) != 0)
+ continue;
+if(chandebug)
+print("[%lud]\tundomount found head %s; need chan (path %.8llux dev %C %lud)\n",
+ up->pid, name->s, c->qid.path, devtab[c->type]->dc, c->dev);
for(t = f->mount; t; t = t->next) {
if(eqchan(c, t->to, 1)) {
/*
@@ 690,6 707,8 @@ undomount(Chan *c, Cname *name)
incref(nc);
cclose(c);
c = nc;
+if(chandebug)
+print("[%lud]\tundomount found %s\n", up->pid, c2name(c));
break;
}
}
@@ 722,10 741,12 @@ walk(Chan **cp, char **names, int nnames, int nomount)
mh = nil;
if(chandebug){
-print("walk");
+qlock(&chanprint);
+print("[%lud] walk %s to ", up->pid, c2name(c));
for(i=0; i<nnames; i++)
- print(" %s", names[i]);
+ print("%s%s", i?"/":"", names[i]);
print("\n");
+qunlock(&chanprint);
}
/*
@@ 755,9 776,13 @@ print("\n");
}
if(chandebug){
-print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.path, devtab[c->type]->dc, c->dev);
+qlock(&chanprint);
+print("[%lud]\twalk from %s (path %.8llux dev %C %lud) to ",
+ up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev);
for(i=0; i<ntry; i++)
- print(" %s", names[i]);
+ print("%s%s", i?"/":"", names[i]);
+print("\n");
+qunlock(&chanprint);
}
if(!dotdot && !nomount)
domount(&c, &mh);
@@ 766,12 791,11 @@ for(i=0; i<ntry; i++)
dev = c->dev;
if((wq = devtab[type]->walk(c, nil, names, ntry)) == nil){
-if(chandebug) print("walk failed.");
+if(chandebug) print("[%lud]\twalk failed.\n", up->pid);
/* try a union mount, if any */
if(mh == nil || nomount){
Giveup:
-if(chandebug) print("give up\n");
-//delay(2000);
+if(chandebug) print("[%lud]\tgive up\n", up->pid);
cclose(c);
cnameclose(cname);
return -1;
@@ 784,7 808,9 @@ if(chandebug) print("give up\n");
}
for(f = mh->mount; f; f = f->next)
{
-if(chandebug) print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.path, devtab[c->type]->dc, c->dev);
+if(chandebug)
+ print("[%lud]\twalk from %s (path %.8llux dev %C %lud)\n",
+ up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev);
if((wq = devtab[f->to->type]->walk(f->to, nil, names, ntry)) != nil)
break;
}
@@ 802,34 828,49 @@ if(chandebug) print("\ttry chan: qid %.8llux devchar %C dev %lud ->\n", c->qid.p
if(dotdot) {
assert(wq->nqid == 1);
assert(wq->clone != nil);
-if(chandebug) print("undo wq->clone->name %s cname %s...", wq->clone->name->s, cname->s);
+
+ cname = addelem(cname, "..");
+if(chandebug)
+print("[%lud]\tundo wq->clone %s cname %s\n", up->pid, c2name(wq->clone), cname?cname->s:"<nil name>");
nc = undomount(wq->clone, cname);
-if(chandebug) print("undidmount nc %s...", nc->name->s);
+if(chandebug)
+print("[%lud]\tundo returned %s\n", up->pid, c2name(nc));
n = 1;
} else {
nc = nil;
-if(chandebug) print("find.");
if(!nomount)
for(i=0; i<wq->nqid && i<nnames-1; i++)
if(findmount(&nc, &nmh, type, dev, wq->qid[i]))
break;
if(nc == nil){ /* no mount points along path */
+if(chandebug)
+print("[%lud]\tno mount points along path\n", up->pid);
if(wq->clone == nil){
cclose(c);
cnameclose(cname);
free(wq);
-if(chandebug) print("fail\n");
return -1;
}
n = wq->nqid;
nc = wq->clone;
}else{ /* stopped early, at a mount point */
+if(chandebug){int j;
+qlock(&chanprint);
+print("[%lud]\tfound mount point: ", up->pid);
+for(j=0; j<=i; j++)
+ print("%s%s", j?"/":"", names[j]);
+print(" becomes ");
+print("%s\n", c2name(nc));
+qunlock(&chanprint);
+}
if(wq->clone != nil){
cclose(wq->clone);
wq->clone = nil;
}
n = i+1;
}
+ for(i=0; i<n; i++)
+ cname = addelem(cname, names[i]);
}
cclose(c);
@@ 837,12 878,8 @@ if(chandebug) print("fail\n");
putmhead(mh);
mh = nmh;
- for(i=0; i<n; i++)
- cname = addelem(cname, names[i]);
-
names += n;
nnames -= n;
-//print("nc %s nnames %d devchar %C qid %.8llux\n", cname->s, nnames, devtab[c->type]->dc, c->qid.path);
free(wq);
}
@@ 860,7 897,8 @@ if(c->umh != nil){
cclose(*cp);
*cp = c;
-if(chandebug) print("success\n");
+if(chandebug)
+print("[%lud]\twalk succeeds; name %s chan (path %.8llux dev %C %lud)\n", up->pid, c2name(c), c->qid.path, devtab[c->type]->dc, c->dev);
return 0;
}
M port/devloopback.c => port/devloopback.c +14 -17
@@ 185,21 185,6 @@ loopbackattach(char *spec)
return c;
}
-static Chan*
-loopbackclone(Chan *c, Chan *nc)
-{
- Loop *lb;
-
- lb = c->aux;
- nc = devclone(c, nc);
- qlock(lb);
- lb->ref++;
- if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata)
- lb->link[ID(c->qid.path)].ref++;
- qunlock(lb);
- return nc;
-}
-
static int
loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
{
@@ 247,7 232,7 @@ loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
if(i >= nelem(loopportdir))
return -1;
tab = &loopportdir[i];
- mkqid(&qid, QID(ID(c->qid.path), tab->qid.path), 0, QTDIR);
+ mkqid(&qid, QID(ID(c->qid.path), tab->qid.path), 0, QTFILE);
devdir(c, qid, tab->name, tab->length, eve, tab->perm, dp);
return 1;
default:
@@ 273,7 258,19 @@ loopbackgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
static Walkqid*
loopbackwalk(Chan *c, Chan *nc, char **name, int nname)
{
- return devwalk(c, nc, name, nname, nil, 0, loopbackgen);
+ Walkqid *wq;
+ Loop *lb;
+
+ wq = devwalk(c, nc, name, nname, nil, 0, loopbackgen);
+ if(wq != nil && wq->clone != nil && wq->clone != c){
+ lb = c->aux;
+ qlock(lb);
+ lb->ref++;
+ if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata)
+ lb->link[ID(c->qid.path)].ref++;
+ qunlock(lb);
+ }
+ return wq;
}
static int
M port/devmnt.c => port/devmnt.c +16 -23
@@ 80,7 80,7 @@ static Chan*
mntattach(char *muxattach)
{
Mnt *m;
- Chan *c, *mc;
+ Chan *c;
struct bogus{
Chan *chan;
char *spec;
@@ 155,23 155,6 @@ mntattach(char *muxattach)
mattach(m, c, bogus.spec);
poperror();
- /*
- * Detect a recursive mount for a mount point served by exportfs.
- * If QTDIR is clear in the returned qid, the foreign server is
- * requesting the mount point be folded into the connection
- * to the exportfs. In this case the remote mount driver does
- * the multiplexing.
- */
- mc = m->c;
- if(mc->type == devno('M', 0) && (c->qid.type&QTDIR) == 0) {
- mclose(m, c);
- c->qid.type |= QTDIR;
- c->mntptr = mc->mntptr;
- c->mchan = c->mntptr->c;
- c->mqid = c->qid;
- incref(c->mntptr);
- }
-
if(bogus.flags & MCACHE)
c->flag |= CCACHE;
@@ 227,8 210,8 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname)
Mnt *m;
Mntrpc *r;
Walkqid *wq;
-extern int chandebug;
-if(chandebug){
+
+if(0){
print("mntwalk ");
for(i=0; i<nname; i++)
print("%s/", name[i]);
@@ 678,12 661,22 @@ mountio(Mnt *m, Mntrpc *r)
}
int
-mntreadn(Chan *c, uchar *buf, int n)
+mntreadn(Chan *c, uchar *buf, int n, int uninterruptable)
{
int m, dm;
for(m=0; m<n; m+=dm){
+ if(uninterruptable)
+ if(waserror()){
+ /* user DEL may stop assembly; wait for full 9P msg. */
+ if(strstr(up->error, "interrupt") == nil)
+ nexterror();
+ dm = 0;
+ continue;
+ }
dm = devtab[c->type]->read(c, buf, n-m, 0);
+ if(uninterruptable)
+ poperror();
if(dm <= 0)
return 0;
buf += dm;
@@ 703,7 696,7 @@ mntrpcread(Mnt *m, Mntrpc *r)
r->reply.type = 0;
r->reply.tag = 0;
/* read size, then read exactly the right number of bytes */
- n = mntreadn(m->c, r->rpc, BIT32SZ);
+ n = mntreadn(m->c, r->rpc, BIT32SZ, 0);
if(n != BIT32SZ){
if(n > 0)
print("devmnt expected BIT32SZ got %d\n", n);
@@ 714,7 707,7 @@ mntrpcread(Mnt *m, Mntrpc *r)
print("devmnt: len %d max messagesize %ld\n", len, m->c->iounit);
return -1;
}
- n += mntreadn(m->c, r->rpc+BIT32SZ, len-BIT32SZ);
+ n += mntreadn(m->c, r->rpc+BIT32SZ, len-BIT32SZ, 1);
if(n != len){
print("devmnt: length %d expected %d\n", n, len);
return -1;