ref: 159f96c534563f26edeeb227cd00f1bdd3bd2596
parent: 8561a843070582d48ef7f99e1138941c3509975f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Jun 19 18:58:16 EDT 2019
cwfs: properly handle 64 bit qid path for historical reasons, kenfs stores directory entries in pre 9p2000 format with directories having the QPDIR bit 31 set in the qid path. however, the 64 bit fileserver allows 64 bit qid paths. given that we do not support pre 9p2000 clients and do not rely on the QPDIR, but want to keep the block check tags consistent, we will *INVERT* the QPDIR bit in directory entry qid paths for directories. this preserves the on-disk semantics (for < 31 bit qmax) but does not complicate qid generation and recovery. also makes it easy to convert between directory entry qid and 9p format.
--- a/sys/src/cmd/cwfs/9p2.c
+++ b/sys/src/cmd/cwfs/9p2.c
@@ -27,11 +27,9 @@
void
mkqid9p1(Qid9p1* qid9p1, Qid* qid)
{
- if(qid->path & 0xFFFFFFFF00000000LL)
- panic("mkqid9p1: path %lluX", (Wideoff)qid->path);
- qid9p1->path = qid->path & 0xFFFFFFFF;
+ qid9p1->path = qid->path;
if(qid->type & QTDIR)
- qid9p1->path |= QPDIR;
+ qid9p1->path ^= QPDIR;
qid9p1->version = qid->vers;
}
@@ -74,7 +72,9 @@
void
mkqid9p2(Qid* qid, Qid9p1* qid9p1, int mode9p1)
{
- qid->path = (ulong)(qid9p1->path & ~QPDIR);
+ qid->path = qid9p1->path;
+ if(mode9p1 & DDIR)
+ qid->path ^= QPDIR;
qid->vers = qid9p1->version;
qid->type = mktype9p2(mode9p1);
}
@@ -399,7 +399,7 @@
Iobuf *p, *p1;
Dentry *d, *d1;
int error, slot, mask;
- Off addr, qpath;
+ Off addr;
p = p1 = nil;
@@ -482,10 +482,9 @@
goto out;
}
}
- qpath = d->qid.path;
p1 = dnodebuf1(p, d, addr, 0, file->uid);
p = nil;
- if(p1 == nil || checktag(p1, Tdir, qpath)){
+ if(p1 == nil || checktag(p1, Tdir, d->qid.path ^ QPDIR)){
error = Eentry;
goto out;
}
@@ -854,7 +853,7 @@
error = Efull;
goto out;
}
- if(checktag(p1, Tdir, d->qid.path)){
+ if(checktag(p1, Tdir, d->qid.path ^ QPDIR)){
putbuf(p1);
goto phase;
}
@@ -904,7 +903,7 @@
if((p1 = getbuf(file->fs->dev, addr1, Brd|Bimm|Bmod)) == nil)
goto phase;
d1 = getdir(p1, slot1);
- if(d1 == nil || checktag(p1, Tdir, d->qid.path)) {
+ if(d1 == nil || checktag(p1, Tdir, d->qid.path ^ QPDIR)) {
putbuf(p1);
goto phase;
}
@@ -929,7 +928,7 @@
d1->mode = DALLOC | (f->perm & 0777);
if(f->perm & DMDIR) {
d1->mode |= DDIR;
- d1->qid.path |= QPDIR;
+ d1->qid.path ^= QPDIR;
}
if(f->perm & DMAPPEND)
d1->mode |= DAPND;
@@ -1359,7 +1358,7 @@
p1 = dnodebuf(p, d, addr, 0, f->uid);
if(!p1)
break;
- if(checktag(p1, Tdir, d->qid.path)) {
+ if(checktag(p1, Tdir, d->qid.path ^ QPDIR)) {
err = Ephase;
goto out;
}
@@ -1688,7 +1687,7 @@
for(addr = 0; ; addr++){
if((p = dnodebuf(p1, d1, addr, 0, file->uid)) == nil)
break;
- if(checktag(p, Tdir, d1->qid.path)){
+ if(checktag(p, Tdir, d1->qid.path ^ QPDIR)){
putbuf(p);
continue;
}
--- a/sys/src/cmd/cwfs/chk.c
+++ b/sys/src/cmd/cwfs/chk.c
@@ -430,7 +430,9 @@
}
/* check qid */
- edent.qpath = d->qid.path & ~QPDIR;
+ edent.qpath = d->qid.path;
+ if(d->mode & DDIR)
+ edent.qpath ^= QPDIR;
qmark(edent.qpath);
if(edent.qpath > maxq)
maxq = edent.qpath;
--- a/sys/src/cmd/cwfs/con.c
+++ b/sys/src/cmd/cwfs/con.c
@@ -513,8 +513,10 @@
mod = 0;
qpath = d->qid.path;
typ = Tfile;
- if(d->mode & DDIR)
+ if(d->mode & DDIR){
+ qpath ^= QPDIR;
typ = Tdir;
+ }
for(i=0; i<NDBLOCK; i++) {
print("dblock[%d] = %lld\n", i, (Wideoff)d->dblock[i]);
ckblock(p->dev, d->dblock[i], typ, qpath);
--- a/sys/src/cmd/cwfs/cw.c
+++ b/sys/src/cmd/cwfs/cw.c
@@ -1311,11 +1311,11 @@
}
Off
-cwrecur(Cw *cw, Off addr, int tag, int tag1, long qp)
+cwrecur(Cw *cw, Off addr, int tag, int tag1, Off qp)
{
Iobuf *p;
Dentry *d;
- long qp1;
+ Off qp1;
int i, j, shouldstop;
Off na;
char *np;
@@ -1373,14 +1373,16 @@
d = getdir(p, i);
if((d->mode & (DALLOC|DTMP)) != DALLOC)
continue;
- qp1 = d->qid.path & ~QPDIR;
if(np)
strncpy(np, d->name, NAMELEN);
else if(i > 0)
fprint(2, "cwrecur: root with >1 directory\n");
+ qp1 = d->qid.path;
tag1 = Tfile;
- if(d->mode & DDIR)
+ if(d->mode & DDIR){
+ qp1 ^= QPDIR;
tag1 = Tdir;
+ }
for(j=0; j<NDBLOCK; j++) {
na = d->dblock[j];
if(na) {
--- a/sys/src/cmd/cwfs/dentry.c
+++ b/sys/src/cmd/cwfs/dentry.c
@@ -65,6 +65,8 @@
}
dev = p->dev;
qpath = d->qid.path;
+ if(d->mode & DDIR)
+ qpath ^= QPDIR;
/* is `a' a direct block? */
if(a < NDBLOCK) {
--- a/sys/src/cmd/cwfs/iobuf.c
+++ b/sys/src/cmd/cwfs/iobuf.c
@@ -201,19 +201,18 @@
checktag(Iobuf *p, int tag, Off qpath)
{
Tag *t;
- ulong pc;
+ uintptr pc;
- qpath &= ~QPDIR;
t = (Tag*)(p->iobuf+BUFSIZE);
- if((tag != t->tag) || ((qpath != QPNONE) && (qpath != t->path))){
+ if(tag != t->tag || qpath != QPNONE && qpath != t->path){
pc = getcallerpc(&p);
if(qpath == QPNONE){
- fprint(2, "checktag pc=%lux %Z(%llux) tag/path=%G/%llud; expected %G\n",
+ fprint(2, "checktag pc=%p %Z(%llux) tag/path=%G/%llud; expected %G\n",
pc, p->dev, (Wideoff)p->addr, t->tag, (Wideoff)t->path, tag);
} else {
- fprint(2, "checktag pc=%lux %Z(%llux) tag/path=%G/%llud; expected %G/%llud\n",
- pc, p->dev, (Wideoff)p->addr, t->tag, (Wideoff)t->path, tag, qpath);
+ fprint(2, "checktag pc=%p %Z(%llux) tag/path=%G/%llud; expected %G/%llud\n",
+ pc, p->dev, (Wideoff)p->addr, t->tag, (Wideoff)t->path, tag, (Wideoff)qpath);
}
return 1;
}
@@ -221,7 +220,7 @@
}
void
-settag(Iobuf *p, int tag, long qpath)
+settag(Iobuf *p, int tag, Off qpath)
{
Tag *t;
@@ -228,7 +227,7 @@
t = (Tag*)(p->iobuf+BUFSIZE);
t->tag = tag;
if(qpath != QPNONE)
- t->path = qpath & ~QPDIR;
+ t->path = qpath;
p->flags |= Bmod;
}
--- a/sys/src/cmd/cwfs/portfns.h
+++ b/sys/src/cmd/cwfs/portfns.h
@@ -160,7 +160,7 @@
void fs_send(Queue*, void*);
void serve(void *);
int serve9p2(Msgbuf*);
-void settag(Iobuf*, int, long);
+void settag(Iobuf*, int, Off);
int strtouid(char*);
Off superaddr(Device*);
void superream(Device*, Off);
--- a/sys/src/cmd/cwfs/sub.c
+++ b/sys/src/cmd/cwfs/sub.c
@@ -380,8 +380,9 @@
if(!p || checktag(p, Tsuper, QPSUPER))
panic("newqid: super block");
sb = (Superb*)p->iobuf;
- sb->qidgen++;
- path = sb->qidgen;
+ do {
+ path = ++sb->qidgen;
+ } while(path == QPDIR);
putbuf(p);
return path;
}