shithub: gefs

Download patch

ref: 6841bfba89c29074d3a9161ee7f01157d22189a8
parent: 40726771923925e566f65389a8d09fd5932a47d0
author: Ori Bernstein <[email protected]>
date: Sat Oct 22 15:43:10 EDT 2022

blk: reserve 0.1% of disk for allocation logs

a full disk will not be able to compress logs
or delete data.

--- a/blk.c
+++ b/blk.c
@@ -13,7 +13,7 @@
 	vlong len;
 };
 
-static vlong	blkalloc_lk(Arena*);
+static vlong	blkalloc_lk(Arena*, int);
 static vlong	blkalloc(int);
 static int	blkdealloc_lk(vlong);
 static Blk*	initblk(Blk*, vlong, int);
@@ -261,7 +261,7 @@
 	 */
 	if(lb == nil || lb->logsz >= Logspc - 40){
 		pb = lb;
-		if((o = blkalloc_lk(a)) == -1)
+		if((o = blkalloc_lk(a, 1)) == -1)
 			return -1;
 		if((lb = cachepluck()) == nil)
 			return -1;
@@ -421,7 +421,7 @@
 	 * because otherwise we have a deadlock
 	 * allocating the block.
 	 */
-	if((ba = blkalloc_lk(a)) == -1)
+	if((ba = blkalloc_lk(a, 1)) == -1)
 		return -1;
 	if((b = cachepluck()) == nil)
 		return -1;
@@ -462,7 +462,7 @@
 	 * so we don't record this block as
 	 * available when we compress the log.
 	 */
-	if((ba = blkalloc_lk(a)) == -1){
+	if((ba = blkalloc_lk(a, 1)) == -1){
 		free(log);
 		return -1;
 	}
@@ -543,7 +543,7 @@
  * the alloc log.
  */
 static vlong
-blkalloc_lk(Arena *a)
+blkalloc_lk(Arena *a, int force)
 {
 	Avltree *t;
 	Arange *r;
@@ -551,8 +551,12 @@
 
 	t = a->free;
 	r = (Arange*)t->root;
-	if(r == nil)
+	if(!force && a->size - a->used <= a->reserve)
 		return -1;
+	if(r == nil){
+		fprint(2, "out of space");
+		abort();
+	}
 
 	/*
 	 * A bit of sleight of hand here:
@@ -618,7 +622,7 @@
 	 */
 	tries++;
 	lock(a);
-	if((b = blkalloc_lk(a)) == -1){
+	if((b = blkalloc_lk(a, 0)) == -1){
 		unlock(a);
 		goto Again;
 	}
--- a/dat.h
+++ b/dat.h
@@ -493,6 +493,7 @@
 	vlong	nq;
 	vlong	size;
 	vlong	used;
+	vlong	reserve;
 	/* freelist */
 	Bptr	head;
 	Blk	*tail;	/* tail held open for writing */
--- a/load.c
+++ b/load.c
@@ -63,6 +63,9 @@
 		a = &fs->arenas[i];
 		if((loadarena(a, &fi, i*fs->arenasz)) == -1)
 			sysfatal("loadfs: %r");
+		a->reserve = a->size / 1024;
+		if(a->reserve < 32*MiB)
+			a->reserve = 32*MiB;
 		mergeinfo(fs, &fi);
 		if(!fs->gotinfo){
 			if((fs->arenas = realloc(fs->arenas, fs->narena*sizeof(Arena))) == nil)
@@ -90,7 +93,7 @@
 	fprint(2, "load %s:\n", dev);
 	fprint(2, "\tsnaptree:\t%B\n", fs->snap.bp);
 	fprint(2, "\tnarenas:\t%d\n", fs->narena);
-	fprint(2, "\tarenasz:\t%lld\n", fs->arenasz);
+	fprint(2, "\tarenasz:\t%lld MiB\n", fs->arenasz/MiB);
 	fprint(2, "\tnextqid:\t%lld\n", fs->nextqid);
 	fprint(2, "\tnextgen:\t%lld\n", fs->nextgen);
 	fprint(2, "\tblocksize:\t%lld\n", Blksz);