shithub: gefs

Download patch

ref: 224a00e04a5a2fdbe2226944c4bdd94b669ee06a
parent: dffc95b10b789e3cc469a56b37b07e7bb39c1aa6
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Nov 6 20:14:04 EST 2022

blk: don't reinitialize log block with new address

when the log block was initialized, we cached it with
an address; reinitializing it means that we have a
pointer to it in the cache, but because the address
has changed, we can never look it up.

this means that if we try to pluck it, we will leave
it in place, and if we insert it again, we can end up
with a cycle in the hash table, which will cause bad
things and infinite loops to happen.

as a result, we need to allocate a new block.

--- a/blk.c
+++ b/blk.c
@@ -464,6 +464,10 @@
 	 * so we don't record this block as
 	 * available when we compress the log.
 	 */
+	if((b = cachepluck()) == nil){
+		free(log);
+		return -1;
+	}
 	if((ba = blkalloc_lk(a, 1)) == -1){
 		free(log);
 		return -1;
--- a/cache.c
+++ b/cache.c
@@ -90,6 +90,7 @@
 		return;
 	}
 	setflag(b, Bcached);
+	b->cached = getcallerpc(&b);
 	b->hnext = bkt->b;
 	bkt->b = b;
 	unlock(bkt);
@@ -115,6 +116,7 @@
 			b->bp.addr = -1;
 			b->bp.hash = -1;
 			clrflag(b, Bcached);
+			b->uncached = getcallerpc(&addr);
 			b->hnext = nil;
 			break;
 		}
@@ -166,10 +168,9 @@
 	assert(b->magic == Magic);
 	assert(b->ref == 0);
 	cachedel(b->bp.addr);
+	assert(!checkflag(b, Bcached));
 	lrudel(b);
 	b->flag = 0;
-	b->bp.addr = -1;
-	b->bp.hash = -1;
 	b->lasthold = 0;
 	b->lastdrop = 0;
 	b->freed = 0;