ref: 3e2d8934b70a0622a2bca53e281dbe811a3fed03
parent: a9fd1bd8bb277a68f9995132db70b6ef0bb09431
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Apr 25 19:58:49 EDT 2023
blk: defer frees/reclaims until after syncing
--- a/blk.c
+++ b/blk.c
@@ -17,7 +17,6 @@
static vlong blkalloc(int, uint);
static int blkdealloc_lk(vlong);
static Blk* initblk(Blk*, vlong, vlong, int);
-static int logop(Arena *, vlong, vlong, int);
int
checkflag(Blk *b, int f)
@@ -290,7 +289,7 @@
assert(off % Blksz == 0);
assert(op == LogAlloc || op == LogFree);
assert(lb == nil || lb->type == Tlog);
- dprint("logop %llx+%llx@%x: %s\n", off, len, lb->logsz, (op == LogAlloc) ? "Alloc" : "Free");
+ dprint("logop %llx+%llx@%x: %s\n", off, len, lb?lb->logsz:-1, (op == LogAlloc) ? "Alloc" : "Free");
/*
* move to the next block when we have
* 40 bytes in the log:
@@ -343,28 +342,16 @@
}
-static int
-logop(Arena *a, vlong off, vlong len, int op)
-{
- if(logappend(a, off, len, op, &a->tail) == -1)
- return -1;
- if(a->head.addr == -1)
- a->head = a->tail->bp;
- return 0;
-}
-
int
-loadlog(Arena *a)
+loadlog(Arena *a, Bptr bp)
{
vlong ent, off, len;
int op, i, n;
uvlong bh;
- Bptr bp;
char *d;
Blk *b;
- bp = a->head;
Nextblk:
if((b = getblk(bp, GBnochk)) == nil)
return -1;
@@ -457,14 +444,14 @@
}
graft = b->bp.addr;
- if(a->tail != nil){
- finalize(a->tail);
- if(syncblk(a->tail) == -1){
+ if(a->logtl != nil){
+ finalize(a->logtl);
+ if(syncblk(a->logtl) == -1){
dropblk(b);
return -1;
}
}
- a->tail = b;
+ a->logtl = b;
/*
* Prepare what we're writing back.
@@ -537,10 +524,10 @@
return -1;
lock(a);
- oldhd = a->head.addr;
- a->head.addr = hd->bp.addr;
- a->head.hash = hd->bp.hash;
- a->head.gen = -1;
+ oldhd = a->loghd.addr;
+ a->loghd.addr = hd->bp.addr;
+ a->loghd.hash = hd->bp.hash;
+ a->loghd.gen = -1;
rv = syncarena(a);
unlock(a);
if(rv == -1)
@@ -579,8 +566,8 @@
lock(a);
a->nlog = 0;
unlock(a);
- finalize(a->tail);
- if(syncblk(a->tail) == -1)
+ finalize(a->logtl);
+ if(syncblk(a->logtl) == -1)
return -1;
return 0;
}
@@ -633,8 +620,10 @@
r = -1;
a = getarena(b);
- if(logop(a, b, Blksz, LogFree) == -1)
- goto out;
+ if(logappend(a, b, Blksz, LogFree, &a->logtl) == -1)
+ return -1;
+ if(a->loghd.addr == -1)
+ a->loghd = a->logtl->bp;
if(freerange(a->free, b, Blksz) == -1)
goto out;
a->used -= Blksz;
@@ -643,6 +632,24 @@
return r;
}
+int
+blkrelease(vlong b)
+{
+ Arena *a;
+ int r;
+
+ a = getarena(b);
+ lock(a);
+ r = -1;
+ a = getarena(b);
+ if(logappend(a, b, Blksz, LogFree, &a->defertl) == -1)
+ return -1;
+ if(a->loghd.addr == -1)
+ a->loghd = a->logtl->bp;
+ unlock(a);
+ return r;
+}
+
static vlong
blkalloc(int ty, uint hint)
{
@@ -675,27 +682,16 @@
unlock(a);
goto Again;
}
- if(logop(a, b, Blksz, LogAlloc) == -1){
+ if(logappend(a, b, Blksz, LogAlloc, &a->logtl) == -1){
unlock(a);
return -1;
}
+ if(a->loghd.addr == -1)
+ a->loghd = a->logtl->bp;
unlock(a);
return b;
}
-int
-blkdealloc(vlong b)
-{
- Arena *a;
- int r;
-
- a = getarena(b);
- lock(a);
- r = blkdealloc_lk(b);
- unlock(a);
- return r;
-}
-
static Blk*
initblk(Blk *b, vlong bp, vlong gen, int ty)
{
@@ -963,7 +959,6 @@
{
ulong e, ge;
Bfree *p, *n;
- Arena *a;
int i;
ge = agetl(&fs->epoch);
@@ -981,15 +976,10 @@
while(p != nil){
n = p->next;
- a = getarena(p->bp.addr);
-
- lock(a);
cachedel(p->bp.addr);
- blkdealloc_lk(p->bp.addr);
+ blkrelease(p->bp.addr);
if(p->b != nil)
dropblk(p->b);
- unlock(a);
-
free(p);
p = n;
}
@@ -1132,8 +1122,17 @@
rsleep(&fs->syncrz);
for(i = 0; i < fs->narena; i++){
a = &fs->arenas[i];
- finalize(a->tail);
- if(syncblk(a->tail) == -1)
+
+ if(a->deferhd.addr != -1){
+ chainlog(a->logtl, a->deferhd.addr);
+ loadlog(a, a->deferhd);
+ a->logtl = a->defertl;
+ a->deferhd = (Bptr){-1, -1, -1};
+ a->defertl = nil;
+ }
+
+ finalize(a->logtl);
+ if(syncblk(a->logtl) == -1)
sysfatal("sync arena: %r");
if(syncarena(a) == -1)
sysfatal("sync arena: %r");
--- a/dat.h
+++ b/dat.h
@@ -509,16 +509,18 @@
Avltree *free;
Blk **queue;
int nqueue;
- Blk *b; /* arena block */
- Blk **q; /* write queue */
+ Blk *b; /* arena block */
+ Blk **q; /* write queue */
vlong nq;
vlong size;
vlong used;
vlong reserve;
/* allocation log */
- vlong nlog; /* number of blocks logged since last compression */
- Bptr head; /* start of allocation log */
- Blk *tail; /* end of the log, open for writing */
+ vlong nlog; /* logged since last copression */
+ Bptr loghd; /* allocation log */
+ Blk *logtl; /* end of the log, open for writing */
+ Bptr deferhd; /* allocation log */
+ Blk *defertl; /* end of the log, open for writing */
Syncq *sync;
};
--- a/fns.h
+++ b/fns.h
@@ -54,8 +54,9 @@
void freesync(void);
void freeblk(Tree*, Blk*);
void freebp(Tree*, Bptr);
+int dlappend(Dlist *dl, Bptr);
int killblk(Tree*, Bptr);
-int blkdealloc(vlong);
+int blkrelease(vlong);
ushort blkfill(Blk*);
uvlong blkhash(Blk*);
uvlong bufhash(void*, usize);
@@ -73,7 +74,7 @@
int loadarena(Arena*, Fshdr *fi, vlong);
void loadfs(char*);
void sync(void);
-int loadlog(Arena*);
+int loadlog(Arena*, Bptr);
int scandead(Dlist*, int, void(*)(Bptr, void*), void*);
int endfs(void);
int compresslog(Arena*);
--- a/load.c
+++ b/load.c
@@ -91,7 +91,7 @@
}
for(i = 0; i < fs->narena; i++){
a = &fs->arenas[i];
- if(loadlog(a) == -1)
+ if(loadlog(a, a->loghd) == -1)
sysfatal("load log: %r");
if(compresslog(a) == -1)
sysfatal("compress log: %r");
--- a/pack.c
+++ b/pack.c
@@ -532,8 +532,8 @@
PACK64(p, fi->arenasz); p += 8;
PACK64(p, fi->nextqid); p += 8;
PACK64(p, fi->nextgen); p += 8;
- PACK64(p, a->head.addr); p += 8; /* freelist addr */
- PACK64(p, a->head.hash); p += 8; /* freelist hash */
+ PACK64(p, a->loghd.addr); p += 8; /* freelist addr */
+ PACK64(p, a->loghd.hash); p += 8; /* freelist hash */
PACK64(p, a->size); p += 8; /* arena size */
PACK64(p, a->used); p += 8; /* arena used */
return p;
@@ -560,11 +560,16 @@
fi->arenasz = UNPACK64(p); p += 8;
fi->nextqid = UNPACK64(p); p += 8;
fi->nextgen = UNPACK64(p); p += 8;
- a->head.addr = UNPACK64(p); p += 8;
- a->head.hash = UNPACK64(p); p += 8;
- a->head.gen = -1; p += 0;
+ a->loghd.addr = UNPACK64(p); p += 8;
+ a->loghd.hash = UNPACK64(p); p += 8;
+ a->loghd.gen = -1; p += 0;
a->size = UNPACK64(p); p += 8;
a->used = UNPACK64(p); p += 8;
- a->tail = nil;
+ a->logtl = nil;
+
+ a->deferhd.addr = -1;
+ a->deferhd.hash = -1;
+ a->deferhd.gen = -1;
+ a->defertl = nil;
return p;
}
--- a/ream.c
+++ b/ream.c
@@ -165,11 +165,11 @@
Blk *b;
b = cachepluck();
- addr = start+Blksz; /* arena header */
+ addr = start+Blksz; /* arena loghder */
- a->head.addr = -1;
- a->head.hash = -1;
- a->head.gen = -1;
+ a->loghd.addr = -1;
+ a->loghd.hash = -1;
+ a->loghd.gen = -1;
memset(b->buf, 0, sizeof(b->buf));
b->type = Tlog;
@@ -197,12 +197,12 @@
b->type = Tarena;
b->bp.addr = start;
b->data = b->buf;
- a->head.addr = bo;
- a->head.hash = bh;
- a->head.gen = -1;
+ a->loghd.addr = bo;
+ a->loghd.hash = bh;
+ a->loghd.gen = -1;
a->size = asz;
a->used = Blksz;
- a->tail = nil;
+ a->logtl = nil;
packarena(b->data, Blksz, a, fi);
finalize(b);
if(syncblk(b) == -1)
@@ -260,7 +260,7 @@
a = &fs->arenas[i];
if((loadarena(a, fs, i*asz)) == -1)
sysfatal("ream: loadarena: %r");
- if(loadlog(a) == -1)
+ if(loadlog(a, a->loghd) == -1)
sysfatal("load log: %r");
if(compresslog(a) == -1)
sysfatal("compress log: %r");
@@ -321,8 +321,8 @@
for(i = 0; i < fs->narena; i++){
a = &fs->arenas[i];
- finalize(a->tail);
- if(syncblk(a->tail) == -1)
+ finalize(a->logtl);
+ if(syncblk(a->logtl) == -1)
sysfatal("sync arena: %r");
packarena(a->b->data, Blksz, a, fs);
finalize(a->b);
--- a/snap.c
+++ b/snap.c
@@ -154,7 +154,7 @@
return Efs;
if(docontents){
for(p = b->data; p != b->data+b->deadsz; p += 8){
- if(blkdealloc(UNPACK64(p)) == -1){
+ if(blkrelease(UNPACK64(p)) == -1){
dropblk(b);
return Efs;
}