ref: 386c056a3d6f6a10c01b5327907d3a640aa44964
parent: 6aa266e6af166f528bce7316c59d80761284e663
author: Ori Bernstein <[email protected]>
date: Tue Oct 26 10:47:30 EDT 2021
check: better dump formatting, misc fixes.
--- a/blk.c
+++ b/blk.c
@@ -16,7 +16,6 @@
static vlong blkalloc_lk(Arena*);
static int blkdealloc_lk(vlong);
static void cachedel(vlong);
-static Blk *lookupblk(vlong);
Blk*
readblk(vlong bp, int flg)
@@ -25,7 +24,7 @@
vlong off, rem, n;
assert(bp != -1);
- if((b = malloc(sizeof(Blk))) == nil)
+ if((b = mallocz(sizeof(Blk), 1)) == nil)
return nil;
off = bp;
rem = Blksz;
@@ -586,28 +585,11 @@
b->cprev = nil;
b->hnext = nil;
+ print("new block %B from %p, flag=%x\n", b->bp, getcallerpc(&t), b->flag);
return cacheblk(b);
}
-static Blk*
-lookupblk(vlong off)
-{
- Bucket *bkt;
- u32int h;
- Blk *b;
- h = ihash(off);
-
- bkt = &fs->cache[h % fs->cmax];
- lock(bkt);
- for(b = bkt->b; b != nil; b = b->hnext)
- if(b->bp.addr == off)
- break;
- unlock(bkt);
- return b;
-}
-
-
int
syncblk(Blk *b)
{
@@ -761,18 +743,11 @@
{
Arena *a;
- /* we can have patterns like:
- * b = getblk();
- * use(b);
- * freeblk(b);
- * unref(b);
- */
- if(b->ref != 1 && ((b->flag & Bcached) && b->ref != 2)){
- fprint(2, "warning: dangling refs: %B @ %ld\n", b->bp, b->ref);
- wlock(b);
- b->flag |= Bzombie;
- wunlock(b);
- }
+ wlock(b);
+ b->flag |= Bzombie;
+ wunlock(b);
+ fprint(2, "freeing block %B @ %ld, from 0x%p\n", b->bp, b->ref, getcallerpc(&b));
+
assert((b->flag & Bqueued) == 0);
a = getarena(b->bp.addr);
lock(a);
--- a/cache.c
+++ b/cache.c
@@ -16,7 +16,10 @@
/* FIXME: better hash. */
refblk(b);
assert(b->bp.addr != 0);
- assert(!(b->flag & Bzombie));
+ if(b->flag & Bzombie){
+ print("caching zombie: %B, flg=%x\n", b->bp, b->flag);
+ abort();
+ }
h = ihash(b->bp.addr);
bkt = &fs->cache[h % fs->cmax];
lock(bkt);
@@ -70,7 +73,7 @@
}
static void
-cachedel(vlong del)
+cachedel_(vlong del)
{
Bucket *bkt;
Blk *b, **p;
@@ -104,3 +107,22 @@
fs->chead = b;
unlock(&fs->lrulk);
}
+
+Blk*
+lookupblk(vlong off)
+{
+ Bucket *bkt;
+ u32int h;
+ Blk *b;
+
+ h = ihash(off);
+
+ bkt = &fs->cache[h % fs->cmax];
+ lock(bkt);
+ for(b = bkt->b; b != nil; b = b->hnext)
+ if(b->bp.addr == off)
+ break;
+ unlock(bkt);
+ return b;
+}
+
--- a/check.c
+++ b/check.c
@@ -212,7 +212,8 @@
if(bkt->b != nil)
fprint(fd, "bkt%d\n", i);
for(b = bkt->b; b != nil; b = b->hnext)
- fprint(fd, "\t%p[ref=%ld, t=%d] => %B\n", b, b->ref, b->type, b->bp);
+ if(b->ref != 1)
+ fprint(fd, "\t%p[ref=%ld, t=%d] => %B\n", b, b->ref, b->type, b->bp);
unlock(bkt);
}
}
--- /dev/null
+++ b/dump.c
@@ -1,0 +1,168 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <avl.h>
+#include <fcall.h>
+#include <ctype.h>
+
+#include "dat.h"
+#include "fns.h"
+
+static int
+showkey(Fmt *fmt, Key *k)
+{
+ int n;
+
+ /*
+ * dent: pqid[8] qid[8] -- a directory entry key.
+ * ptr: off[8] hash[8] -- a key for an Dir block.
+ * dir: fixed statbuf header, user ids
+ */
+ switch(k->k[0]){
+ case Kdat: /* qid[8] off[8] => ptr[16]: pointer to data page */
+ n = fmtprint(fmt, "dat qid:%llx off:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
+ break;
+ case Kent: /* pqid[8] name[n] => dir[n]: serialized Dir */
+ n = fmtprint(fmt, "ent dir:%llx, name:\"%.*s\")", GBIT64(k->k+1), k->nk-11, k->k+11);
+ break;
+ case Ksnap: /* name[n] => dent[16] ptr[16]: snapshot root */
+ n = fmtprint(fmt, "snap dent:%llx ptr:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
+ break;
+ case Ksuper: /* qid[8] => pqid[8]: parent dir */
+ n = fmtprint(fmt, "up parent:%llx ptr:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
+ break;
+ default:
+ n = fmtprint(fmt, "%.*H", k->nk, k->k);
+ break;
+ }
+ return n;
+}
+
+static int
+showval(Fmt *fmt, Kvp *v, int op)
+{
+ char *p;
+ Dir d;
+ int n;
+
+ n = 0;
+ switch(v->k[0]){
+ case Kdat: /* qid[8] off[8] => ptr[16]: pointer to data page */
+ n = fmtprint(fmt, "blk:%llx, hash:%llx", GBIT64(v->v), GBIT64(v->v+8));
+ break;
+ case Kent: /* pqid[8] name[n] => dir[n]: serialized Dir */
+ switch(op&0xf){
+ case Onop:
+ case Oinsert:
+ if(kv2dir(v, &d) == -1)
+ n = fmtprint(fmt, "bad dir");
+ else
+ n = fmtprint(fmt, "[qid=(%lld,%lud,%d), %lo, t=%lud,%lud, l=%lld]",
+ d.qid.path, d.qid.vers, d.qid.type,
+ d.mode, d.atime, d.mtime, d.length);
+ break;
+ case Odelete:
+ n = fmtprint(fmt, "delete");
+ case Owstat:
+ p = v->v;
+ if(op & Owmtime){
+ n += fmtprint(fmt, "mtime:%llx ", GBIT64(p));
+ p += 8;
+ }
+ if(op & Owsize){
+ n += fmtprint(fmt, "size:%llx ", GBIT64(p));
+ p += 8;
+ }
+ if(op & Owmode){
+ n += fmtprint(fmt, "mode:%o ", GBIT32(p));
+ p += 4;
+ }
+ if(p != v->v + v->nv)
+ abort();
+ }
+ break;
+ case Ksnap: /* name[n] => dent[16] ptr[16]: snapshot root */
+ n = fmtprint(fmt, "blk:%llx, hash:%llx", GBIT64(v->v), GBIT64(v->v+8));
+ break;
+ case Ksuper: /* qid[8] => pqid[8]: parent dir */
+ n = fmtprint(fmt, "parent: %llx", GBIT64(v->v));
+ break;
+ default:
+ n = fmtprint(fmt, "%.*H", v->nk, v->k);
+ break;
+ }
+ return n;
+
+}
+
+int
+Bconv(Fmt *fmt)
+{
+ Bptr bp;
+
+ bp = va_arg(fmt->args, Bptr);
+ return fmtprint(fmt, "(%llx,%llx,%llx)", bp.addr, bp.hash, bp.gen);
+}
+
+int
+Mconv(Fmt *fmt)
+{
+ char *opname[] = {
+ [Oinsert] "Oinsert",
+ [Odelete] "Odelete",
+ [Owstat] "Owstat",
+ };
+ Msg *m;
+ int n;
+
+ m = va_arg(fmt->args, Msg*);
+ n = fmtprint(fmt, "Msg(%s, ", opname[m->op&0xf]);
+ n += showkey(fmt, m);
+ n += fmtprint(fmt, ") => (");
+ n += showval(fmt, m, m->op);
+ n += fmtprint(fmt, ")");
+ return n;
+}
+
+int
+Pconv(Fmt *fmt)
+{
+ Kvp *kv;
+ int n;
+
+ kv = va_arg(fmt->args, Kvp*);
+ n = fmtprint(fmt, "Kvp(");
+ n += showkey(fmt, kv);
+ n += fmtprint(fmt, ") => (");
+ if(kv->type == Vinl)
+ n += showval(fmt, kv, Onop);
+ else
+ n += fmtprint(fmt, "(%B,%ud))", kv->bp, kv->fill);
+ n += fmtprint(fmt, ")");
+ return n;
+}
+
+int
+Kconv(Fmt *fmt)
+{
+ Key *k;
+ int n;
+
+ k = va_arg(fmt->args, Key*);
+ n = fmtprint(fmt, "Key(");
+ n += showkey(fmt, k);
+ n += fmtprint(fmt, ")");
+ return n;
+}
+
+int
+Rconv(Fmt *fmt)
+{
+ Arange *r;
+
+ r = va_arg(fmt->args, Arange*);
+ if(r == nil)
+ return fmtprint(fmt, "<Arange:nil>");
+ else
+ return fmtprint(fmt, "Arange(%lld+%lld)", r->off, r->len);
+}
--- a/fns.h
+++ b/fns.h
@@ -14,6 +14,7 @@
Blk* getblk(Bptr, int);
Blk* refblk(Blk*);
Blk* cacheblk(Blk*);
+Blk* lookupblk(vlong);
Blk* readblk(vlong, int);
Arena* getarena(vlong);
void putblk(Blk*);
@@ -86,6 +87,13 @@
char *packbp(char*, Bptr*);
Bptr unpackbp(char*);
+
+/* fmt */
+int Bconv(Fmt*);
+int Mconv(Fmt*);
+int Pconv(Fmt*);
+int Rconv(Fmt*);
+int Kconv(Fmt*);
/* scratch */
void setmsg(Blk *, int, Msg *);
--- a/fs.c
+++ b/fs.c
@@ -71,7 +71,7 @@
lock(&fs->dtablk);
for(e = fs->dtab[h]; e != nil; e = e->next){
if(e->qid.path == d->qid.path && e->rootb == root){
- dprint("found %p\n", e);
+ dprint("found %p [%K]\n", e, &e->Key);
ainc(&e->ref);
unlock(&fs->dtablk);
return e;
@@ -95,6 +95,7 @@
e->nk = ek - e->buf;
e->next = fs->dtab[h];
fs->dtab[h] = e;
+ dprint("created %p [%K]\n", e, &e->Key);
unlock(&fs->dtablk);
return e;
@@ -108,7 +109,6 @@
if(adec(&de->ref) == 0){
h = (ihash(de->qid.path) ^ ihash(de->rootb)) % Ndtab;
-dprint("freeing dent, hash=%d, p=0x%p\n", h, de);
lock(&fs->dtablk);
pe = &fs->dtab[h];
for(e = fs->dtab[h]; e != nil; e = e->next){
@@ -430,7 +430,7 @@
fswalk(Fmsg *m)
{
char *p, *e, *estr, kbuf[Maxent];
- int i, err;
+ int i, nwalk, err;
vlong up, prev;
Fid *o, *f;
Dent *dent;
@@ -450,6 +450,7 @@
}
err = 0;
estr = nil;
+ nwalk = 0;
up = o->qpath;
prev = o->qpath;
r.type = Rwalk;
@@ -469,13 +470,15 @@
k.nk = p - kbuf;
//showfs("walking");
//dprint("looking up %K\n", &k);
- if((estr = fslookup(o, &k, &kv, &b, 0)) != nil)
+ if((estr = fslookup(o, &k, &kv, &b, 0)) != nil){
break;
+ }
if(kv2dir(&kv, &d) == -1){
rerror(m, Efs);
putblk(b);
return;
}
+ nwalk = i;
prev = d.qid.path;
putblk(b);
r.wqid[r.nwqid] = d.qid;
@@ -486,7 +489,7 @@
return;
}
f = o;
- if(m->fid != m->newfid){
+ if(m->fid != m->newfid && i == m->nwname){
if((f = dupfid(m->newfid, o)) == nil){
rerror(m, "%r");
return;
@@ -493,7 +496,8 @@
}
}
if(i > 0){
- d.name = m->wname[i-1];
+ d.name = m->wname[nwalk];
+ d.qid = m->wqid[nwalk];
dent = getdent(f->root.bp.addr, up, &d);
if(dent == nil){
if(m->fid != m->newfid)
@@ -501,8 +505,10 @@
rerror(m, Enomem);
return;
}
- f->qpath = r.wqid[r.nwqid-1].path;
- f->dent = dent;
+ if(i == m->nwname){
+ f->qpath = r.wqid[i-1].path;
+ f->dent = dent;
+ }
}
respond(m, &r);
}
@@ -510,7 +516,7 @@
void
fsstat(Fmsg *m)
{
- char buf[STATMAX];
+ char *err, buf[STATMAX];
Fcall r;
Fid *f;
Kvp kv;
@@ -521,8 +527,9 @@
rerror(m, "no such fid");
return;
}
- if(btlookup(&fs->root, f->dent, &kv, &b) != nil){
- rerror(m, Eexist);
+ print("stat %K\n", &f->dent->Key);
+ if((err = btlookup(&fs->root, f->dent, &kv, &b)) != nil){
+ rerror(m, err);
return;
}
if((n = kv2statbuf(&kv, buf, sizeof(buf))) == -1){
@@ -1006,7 +1013,9 @@
if(n == -1){
// badwrite(f, i);
// FIXME: free pages
+ wunlock(f->dent);
rerror(m, "%r");
+ return;
}
p += n;
o += n;
@@ -1024,7 +1033,10 @@
PBIT64(kv[i].v, m->offset+m->count);
f->dent->length = m->offset+m->count;
}
- btupsert(&fs->root, kv, i+1);
+ if(btupsert(&fs->root, kv, i+1) == -1){
+ fprint(2, "upsert: %r\n");
+ abort();
+ }
wunlock(f->dent);
r.type = Rwrite;
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@
#include <bio.h>
#include <avl.h>
#include <fcall.h>
-#include <ctype.h>
#include "dat.h"
#include "fns.h"
@@ -14,13 +13,17 @@
int debug;
char *srvname = "gefs";
-static int
-Bconv(Fmt *fmt)
+void
+initfs(vlong cachesz)
{
- Bptr bp;
+ if((fs = mallocz(sizeof(Gefs), 1)) == nil)
+ sysfatal("malloc: %r");
- bp = va_arg(fmt->args, Bptr);
- return fmtprint(fmt, "(%llx,%llx,%llx)", bp.addr, bp.hash, bp.gen);
+ fs->cmax = cachesz/Blksz;
+ if(fs->cmax >= (2*GiB)/sizeof(Bucket))
+ sysfatal("cache too big");
+ if((fs->cache = mallocz(fs->cmax*sizeof(Bucket), 1)) == nil)
+ sysfatal("malloc: %r");
}
void
@@ -39,94 +42,6 @@
}
}
-static int
-Mconv(Fmt *fmt)
-{
- char *opname[] = {
- [Oinsert] "Oinsert",
- [Odelete] "Odelete",
- [Owstat] "Owstat",
- };
- Msg *m;
-
- m = va_arg(fmt->args, Msg*);
- return fmtprint(fmt, "Msg(%s, [%d]%.*X,[%d]%.*X)",
- opname[m->op&0xf],
- m->nk, m->nk, m->k,
- m->nv, m->nv, m->v);
-}
-
-static int
-Pconv(Fmt *fmt)
-{
- Kvp *kv;
-
- kv = va_arg(fmt->args, Kvp*);
- if(kv->type == Vinl)
- return fmtprint(fmt, "Kvp([%d]%.*X,[%d]%.*X)",
- kv->nk, kv->nk, kv->k,
- kv->nv, kv->nv, kv->v);
- else
- return fmtprint(fmt, "Kvp([%d]%.*X,(%B,%ud))",
- kv->nk, kv->nk, kv->k, kv->bp, kv->fill);
-}
-
-static int
-Rconv(Fmt *fmt)
-{
- Arange *r;
-
- r = va_arg(fmt->args, Arange*);
- if(r == nil)
- return fmtprint(fmt, "<Arange:nil>");
- else
- return fmtprint(fmt, "Arange(%lld+%lld)", r->off, r->len);
-}
-
-static int
-Kconv(Fmt *fmt)
-{
- Key *k;
-
- k = va_arg(fmt->args, Key*);
- return fmtprint(fmt, "Key([%d]%.*X)", k->nk, k->nk, k->k);
-}
-
-static int
-Xconv(Fmt *fmt)
-{
- char *s, *e;
- int n, i;
-
- n = 0;
- i = fmt->prec;
- s = va_arg(fmt->args, char*);
- e = s + fmt->prec;
- for(; s != e; s++){
- if(i % 4 == 0 && i != 0)
- n += fmtprint(fmt, ":");
- i--;
- if(isalnum(*s))
- n += fmtrune(fmt, *s);
- else
- n += fmtprint(fmt, "%02x", *s&0xff);
- }
- return n;
-}
-
-void
-initfs(vlong cachesz)
-{
- if((fs = mallocz(sizeof(Gefs), 1)) == nil)
- sysfatal("malloc: %r");
-
- fs->cmax = cachesz/Blksz;
- if(fs->cmax >= (2*GiB)/sizeof(Bucket))
- sysfatal("cache too big");
- if((fs->cache = mallocz(fs->cmax*sizeof(Bucket), 1)) == nil)
- sysfatal("malloc: %r");
-}
-
int
postfd(char *name, char *suff)
{
@@ -189,12 +104,12 @@
initfs(cachesz);
initshow();
quotefmtinstall();
+ fmtinstall('H', encodefmt);
fmtinstall('B', Bconv);
fmtinstall('M', Mconv);
fmtinstall('P', Pconv);
fmtinstall('K', Kconv);
fmtinstall('R', Rconv);
- fmtinstall('X', Xconv);
fmtinstall('F', fcallfmt);
if(ream){
reamfs(argv[0]);
--- a/mkfile
+++ b/mkfile
@@ -6,6 +6,7 @@
cache.$O\
check.$O\
cons.$O\
+ dump.$O\
fs.$O\
hash.$O\
load.$O\
--- a/tree.c
+++ b/tree.c
@@ -579,8 +579,10 @@
case Owstat:
p = m->v;
idx = blksearch(b, m, &kv, &same);
- if(idx == -1 || !same)
+ if(idx == -1 || !same){
+ fprint(2, "missing keyval %P [idx=%d, same=%d]\n", &kv, idx, same);
abort();
+ }
/* bump version */
v = GBIT32(kv.v+8);
PBIT32(kv.v+8, v+1);