ref: a0a4524bbb03bfa4902c6aa7102d912d403eef6b
parent: b33fa323a1d0194b79f6e1aabb88829767a43ba3
author: Ori Bernstein <[email protected]>
date: Mon Nov 29 10:55:17 EST 2021
tree: apply messages to the right files
--- a/blk.c
+++ b/blk.c
@@ -16,6 +16,8 @@
static int blkdealloc_lk(vlong);
static void cachedel(vlong);
+QLock blklock;
+
Blk*
readblk(vlong bp, int flg)
{
@@ -41,7 +43,7 @@
b->bp.addr = bp;
b->bp.hash = -1;
b->bp.gen = -1;
- b->ref = 0; /* caller must increment */
+ b->ref = 1;
b->cnext = nil;
b->cprev = nil;
b->hnext = nil;
@@ -559,12 +561,8 @@
* to the block, so we only
* want to reset the refs
* on an allocation.
- *
- * cacheblk incrmeents the
- * refcount, so we want to
- * start off at zero here.
*/
- b->ref = 0;
+ b->ref = 1;
}
b->type = t;
b->flag = Bdirty;
@@ -680,18 +678,31 @@
{
Blk *b;
- if((b = lookupblk(bp.addr)) == nil){
- if((b = readblk(bp.addr, flg)) == nil)
- return nil;
- if(blkhash(b) != bp.hash){
- werrstr("corrupt block %B: %llx != %llx", bp, blkhash(b), bp.hash);
- return nil;
- }
- b->bp.hash = bp.hash;
- b->bp.gen = bp.gen;
+ if((b = lookupblk(bp.addr)) != nil)
+ return cacheblk(b);
+
+ qlock(&blklock);
+ if((b = lookupblk(bp.addr)) != nil){
+ cacheblk(b);
+ qunlock(&blklock);
+ return b;
}
- assert(b->bp.addr == bp.addr);
- return cacheblk(b);
+ if((b = readblk(bp.addr, flg)) == nil){
+ qunlock(&blklock);
+ return nil;
+ }
+ if(blkhash(b) != bp.hash){
+ werrstr("corrupt block %B: %llx != %llx", bp, blkhash(b), bp.hash);
+ qunlock(&blklock);
+ abort();
+ return nil;
+ }
+ b->bp.hash = bp.hash;
+ b->bp.gen = bp.gen;
+ cacheblk(b);
+ qunlock(&blklock);
+
+ return b;
}
Blk*
@@ -743,6 +754,7 @@
wlock(b);
b->flag |= Bzombie;
+ b->freed = getcallerpc(&b);
wunlock(b);
dprint("freeing block %B @ %ld, from 0x%p\n", b->bp, b->ref, getcallerpc(&b));
--- a/cache.c
+++ b/cache.c
@@ -13,13 +13,10 @@
Blk *e, *c;
u32int h;
- /* FIXME: better hash. */
- refblk(b);
assert(b->bp.addr != 0);
if(b->flag & Bzombie){
- print("caching zombie: %B, flg=%x\n", b->bp, b->flag);
- sleep(30*1000);
-// abort();
+ print("caching zombie: %B, flg=%x, freed=0x%p\n", b->bp, b->flag, b->freed);
+ abort();
}
h = ihash(b->bp.addr);
bkt = &fs->cache[h % fs->cmax];
@@ -121,8 +118,10 @@
bkt = &fs->cache[h % fs->cmax];
lock(bkt);
for(b = bkt->b; b != nil; b = b->hnext)
- if(b->bp.addr == off)
+ if(b->bp.addr == off){
+ refblk(b);
break;
+ }
unlock(bkt);
return b;
}
--- a/dat.h
+++ b/dat.h
@@ -363,6 +363,7 @@
u32int fid;
vlong qpath;
+ long ref;
int mode;
int iounit;
@@ -435,6 +436,8 @@
vlong logsz; /* for allocation log */
vlong lognxt; /* for allocation log */
+
+ uintptr freed; /* debug */
Bptr bp;
long ref;
--- a/fs.c
+++ b/fs.c
@@ -149,9 +149,19 @@
if(f->fid == fid)
break;
unlock(&fs->fidtablk);
+ ainc(&f->ref);
return f;
}
+void
+putfid(Fid *f)
+{
+ if(adec(&f->ref) == 0){
+ clunkdent(f->dent);
+ free(f);
+ }
+}
+
Fid*
dupfid(int new, Fid *f)
{
@@ -164,6 +174,7 @@
*n = *f;
n->fid = new;
+ n->ref = 2; /* one for dup, one for clunk */
n->mode = -1;
n->next = nil;
@@ -198,16 +209,13 @@
pf = &fs->fidtab[h];
for(f = fs->fidtab[h]; f != nil; f = f->next){
if(f == fid){
+ assert(adec(&f->ref) != 0);
*pf = f->next;
- goto Found;
+ break;
}
pf = &f->next;
}
- abort();
-Found:
- clunkdent(fid->dent);
unlock(&fs->fidtablk);
- free(fid);
}
void
@@ -453,6 +461,7 @@
p = packstr(&err, p, e, m->wname[i]);
if(err){
rerror(m, "bad walk: %r");
+ putfid(o);
return;
}
k.k = kbuf;
@@ -462,6 +471,7 @@
}
if(kv2dir(&kv, &d) == -1){
rerror(m, Efs);
+ putfid(o);
return;
}
prev = d.qid.path;
@@ -470,14 +480,17 @@
r.nwqid = i;
if(i == 0 && m->nwname != 0){
rerror(m, estr);
+ putfid(o);
return;
}
f = o;
if(m->fid != m->newfid && i == m->nwname){
if((f = dupfid(m->newfid, o)) == nil){
- rerror(m, "%r");
+ rerror(m, Emem);
+ putfid(o);
return;
}
+ putfid(o);
}
if(i > 0){
dent = getdent(f->root.bp.addr, up, &d);
@@ -485,6 +498,7 @@
if(m->fid != m->newfid)
clunkfid(f);
rerror(m, Enomem);
+ putfid(f);
return;
}
if(i == m->nwname){
@@ -493,6 +507,7 @@
}
}
respond(m, &r);
+ putfid(f);
}
void
@@ -510,10 +525,12 @@
}
if((err = btlookup(&fs->root, f->dent, &kv, kvbuf, sizeof(kvbuf))) != nil){
rerror(m, err);
+ putfid(f);
return;
}
if((n = kv2statbuf(&kv, buf, sizeof(buf))) == -1){
rerror(m, "stat: %r");
+ putfid(f);
return;
}
r.type = Rstat;
@@ -520,6 +537,7 @@
r.stat = (uchar*)buf;
r.nstat = n;
respond(m, &r);
+ putfid(f);
}
void
@@ -550,6 +568,7 @@
clunkfid(f);
r.type = Rclunk;
respond(m, &r);
+ putfid(f);
}
void
@@ -596,11 +615,13 @@
mb.op = Oinsert;
mb.statop = 0;
if(dir2kv(f->qpath, &d, &mb, buf, sizeof(buf)) == -1){
- rerror(m, "%r");
+ rerror(m, Efs);
+ putfid(f);
return;
}
if(btupsert(&fs->root, &mb, 1) == -1){
rerror(m, "%r");
+ putfid(f);
return;
}
dent = getdent(f->root.bp.addr, f->qpath, &d);
@@ -608,6 +629,7 @@
if(m->fid != m->newfid)
clunkfid(f);
rerror(m, Enomem);
+ putfid(f);
return;
}
@@ -616,6 +638,7 @@
unlock(f);
clunkdent(dent);
rerror(m, Einuse);
+ putfid(f);
return;
}
f->mode = m->mode;
@@ -631,6 +654,7 @@
r.qid = d.qid;
r.iounit = f->iounit;
respond(m, &r);
+ putfid(f);
}
void
@@ -654,6 +678,7 @@
if(btupsert(&fs->root, &mb, 1) == -1){
runlock(f->dent);
rerror(m, "remove: %r");
+ putfid(f);
return;
}
runlock(f->dent);
@@ -661,6 +686,7 @@
r.type = Rremove;
respond(m, &r);
+ putfid(f);
}
int
@@ -685,14 +711,17 @@
}
if((e = fslookup(f, f->dent, &kv, buf, sizeof(buf), 0)) != nil){
rerror(m, e);
+ putfid(f);
return;
}
if(kv2dir(&kv, &d) == -1){
rerror(m, Efs);
+ putfid(f);
return;
}
if(fsaccess(&d, m->mode) == -1){
rerror(m, Eperm);
+ putfid(f);
return;
}
wlock(f->dent);
@@ -706,15 +735,16 @@
if(f->mode != -1){
rerror(m, Einuse);
unlock(f);
+ putfid(f);
return;
}
f->mode = m->mode;
- if((f->mode & 0x7) == OEXEC){
- lock(&fs->root.lk);
- f->root = fs->root;
+// if((f->mode & 0x7) == OEXEC){
+// lock(&fs->root.lk);
+// f->root = fs->root;
// refblk(fs->root.bp);
- unlock(&fs->root.lk);
- }
+// unlock(&fs->root.lk);
+// }
if(f->mode & OTRUNC){
wlock(f->dent);
// freeb(f->dent, 0, dent->length);
@@ -723,6 +753,7 @@
}
unlock(f);
respond(m, &r);
+ putfid(f);
}
char*
@@ -812,7 +843,6 @@
e = fslookup(f, &k, &kv, kvbuf, sizeof(kvbuf), 0);
if(e != nil && e != Eexist){
- fprint(2, "!!! error: %s", e);
werrstr(e);
return -1;
}
@@ -857,7 +887,7 @@
while(c != 0){
n = readb(f, p, o, c, e->length);
if(n == -1){
- fprint(2, "read: %r\n");
+ fprint(2, "read %K [%Q]@%lld+%lld: %r\n", &e->Key, e->qid, o, c);
runlock(e);
return Efs;
}
@@ -887,6 +917,7 @@
r.count = 0;
if((r.data = malloc(m->count)) == nil){
rerror(m, Emem);
+ putfid(f);
return;
}
if(f->dent->qid.type & QTDIR)
@@ -895,11 +926,12 @@
e = fsreadfile(m, f, &r);
if(e != nil){
rerror(m, e);
+ putfid(f);
return;
- }else{
- respond(m, &r);
- free(r.data);
}
+ respond(m, &r);
+ free(r.data);
+ putfid(f);
}
int
@@ -924,14 +956,11 @@
return -1;
if(fb < sz && (fo != 0 || n != Blksz)){
dprint("\tappending to block %B\n", b->bp);
- if(fslookup(f, m, &kv, buf, sizeof(buf), 0) != nil){
+ if(fslookup(f, m, &kv, buf, sizeof(buf), 0) != nil)
return -1;
- }
bp = unpackbp(kv.v);
-
- if((t = getblk(bp, GBraw)) == nil){
+ if((t = getblk(bp, GBraw)) == nil)
return -1;
- }
memcpy(b->buf, t->buf, Blksz);
freeblk(t);
putblk(t);
@@ -965,6 +994,7 @@
if((f->mode&0x7) != OWRITE){
dprint("f->mode: %x\n", f->mode);
rerror(m, Einuse);
+ putfid(f);
return;
}
@@ -984,6 +1014,8 @@
// FIXME: free pages
wunlock(f->dent);
rerror(m, "%r");
+ putfid(f);
+ abort();
return;
}
p += n;
@@ -1005,7 +1037,9 @@
}
if(btupsert(&fs->root, kv, i+1) == -1){
fprint(2, "upsert: %r\n");
+ putfid(f);
abort();
+ return;
}
wunlock(f->dent);
@@ -1012,6 +1046,7 @@
r.type = Rwrite;
r.count = m->count;
respond(m, &r);
+ putfid(f);
}
void
--- a/ream.c
+++ b/ream.c
@@ -101,8 +101,8 @@
sysfatal("ream: disk too small");
if((s = mallocz(sizeof(Blk), 1)) == nil)
sysfatal("ream: %r");
+ refblk(s);
-
sz = d->length;
sz = sz - (sz % Blksz) - Blksz;
fs->narena = sz / (128*GiB);
@@ -145,6 +145,7 @@
*/
if((r = newblk(Tleaf)) == nil)
sysfatal("ream: allocate root: %r");
+ refblk(r);
initroot(r);
finalize(r);
syncblk(r);
--- a/tree.c
+++ b/tree.c
@@ -186,20 +186,31 @@
bufsearch(Blk *b, Key *k, Msg *m, int *same)
{
int lo, hi, mid, r;
+ Msg cmp;
r = -1;
lo = 0;
- hi = b->nbuf - 1;
- while(lo <= hi){
+ hi = b->nbuf;
+ while(lo < hi){
mid = (hi + lo) / 2;
- getmsg(b, mid, m);
- r = keycmp(k, m);
+ getmsg(b, mid, &cmp);
+ r = keycmp(k, &cmp);
if(r < 0)
- hi = mid - 1;
+ hi = mid;
else
lo = mid + 1;
}
+ /*
+ * we can have duplicate messages, and we
+ * want to point to the first of them:
+ * scan backwards.
+ */
lo--;
+ for(; lo > 0; lo--){
+ getmsg(b, lo-1, &cmp);
+ if(keycmp(k, &cmp) != 0)
+ break;
+ }
if(lo >= 0){
getmsg(b, lo, m);
r = keycmp(k, m);
@@ -351,11 +362,13 @@
{
switch(m->op){
case Odelete:
+ assert(keycmp(r, m) == 0);
return 0;
case Oinsert:
cpkvp(r, m, buf, nbuf);
return 1;
case Owstat:
+ assert(keycmp(r, m) == 0);
statupdate(r, m);
return 1;
}
@@ -429,13 +442,14 @@
print("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
abort();
}
+ cpkvp(&v, &m, buf, sizeof(buf));
spc -= valsz(&m);
goto Copy;
case 0:
i++;
while(j < up->hi){
- Copy:
ok = apply(&v, &m, buf, sizeof(buf));
+ Copy:
j++;
p->pullsz += msgsz(&m);
if(j >= up->hi || pullmsg(up, j, &v, &m, &full, spc) != 0)
@@ -620,13 +634,14 @@
print("%d(/%d), %d: %M not insert\n", i, b->nval, j, &m);
abort();
}
+ cpkvp(&v, &m, buf, sizeof(buf));
spc -= valsz(&m);
goto Copy;
case 0:
i++;
while(j < up->hi){
- Copy:
ok = apply(&v, &m, buf, sizeof(buf));
+ Copy:
p->pullsz += msgsz(&m);
j++;
if(j == up->hi || pullmsg(up, j, &v, &m, &full, spc) != 0)
@@ -1210,21 +1225,27 @@
if((p = calloc(h, sizeof(Blk*))) == nil)
return Emem;
err = Eexist;
+ ok = 0;
p[0] = refblk(b);
for(i = 1; i < h; i++){
if(blksearch(p[i-1], k, r, nil) == -1)
- goto Out;
+ break;
if((p[i] = getblk(r->bp, 0)) == nil)
return Efs;
}
- blksearch(p[h-1], k, r, &ok);
+ if(p[h-1] != nil)
+ blksearch(p[h-1], k, r, &ok);
if(ok)
cpkvp(r, r, buf, nbuf);
- for(i = h - 2; i >= 0; i--){
+ for(i = h-2; i >= 0; i--){
+ if(p[i] == nil)
+ continue;
j = bufsearch(p[i], k, &m, &same);
- if(!same)
+ if(j < 0 || !same)
continue;
- for(; j < p[i]->nbuf; j++){
+ assert(ok || m.op == Oinsert);
+ ok = apply(r, &m, buf, nbuf);
+ for(j++; j < p[i]->nbuf; j++){
getmsg(p[i], j, &m);
if(keycmp(k, &m) != 0)
break;
@@ -1233,7 +1254,6 @@
}
if(ok)
err = nil;
-Out:
for(i = 0; i < h; i++)
if(p[i] != nil)
putblk(p[i]);