shithub: gefs

Download patch

ref: 39febdb6031e556559a43494b396abb898228b2f
parent: e7398383ed59cfcf02d8916fed0d0be3421822cd
author: Ori Bernstein <[email protected]>
date: Mon Dec 18 13:01:43 EST 2023

blk: make dipping into reserve blocks a manual operation

--- a/blk.c
+++ b/blk.c
@@ -7,7 +7,7 @@
 #include "fns.h"
 #include "atomic.h"
 
-static vlong	blkalloc_lk(Arena*, int);
+static vlong	blkalloc_lk(Arena*);
 static vlong	blkalloc(int, uint);
 static void	blkdealloc_lk(Arena*, vlong);
 static Blk*	initblk(Blk*, vlong, vlong, int);
@@ -293,7 +293,7 @@
 	 * and chaining.
 	 */
 	if(lb == nil || lb->logsz >= Logspc - Logslop){
-		if((o = blkalloc_lk(a, 1)) == -1)
+		if((o = blkalloc_lk(a)) == -1)
 			error(Efs);
 		nl = mklogblk(a, o);
 		p = lb->data + lb->logsz;
@@ -434,7 +434,7 @@
 		return -1;
 	}
 	for(i = 0; i < nblks; i++)
-		if((blks[i] = blkalloc_lk(a, 1)) == -1)
+		if((blks[i] = blkalloc_lk(a)) == -1)
 			error(Efs);
 
 	/* fill up the log with the ranges from the tree */
@@ -497,7 +497,7 @@
  * the alloc log.
  */
 static vlong
-blkalloc_lk(Arena *a, int force)
+blkalloc_lk(Arena *a)
 {
 	Avltree *t;
 	Arange *r;
@@ -505,7 +505,7 @@
 
 	t = a->free;
 	r = (Arange*)t->root;
-	if(!force && a->size - a->used <= a->reserve)
+	if(!usereserve && a->size - a->used <= a->reserve)
 		return -1;
 	if(r == nil)
 		broke(Estuffed);
@@ -559,20 +559,8 @@
 	tries = 0;
 Again:
 	a = pickarena(ty, hint, tries);
-	if(tries == fs->narena)
+	if(tries == 2*fs->narena)
 		error(Efull);
-	/*
-	 * TODO: there's an extreme edge case
-	 * here.
-	 *
-	 * If the file system has room to alloc
-	 * a data block but no log block, then
-	 * we end up with it in a stuck state.
-	 * The fix is to reserve alloc blocks,
-	 * so that we're guaranteed to be able
-	 * to log an alloc if the disk is working
-	 * correctly.
-	 */
 	tries++;
 	if(tries < fs->narena){
 		if(canqlock(a) == 0)
@@ -583,7 +571,7 @@
 		qunlock(a);
 		nexterror();
 	}
-	if((b = blkalloc_lk(a, 0)) == -1){
+	if((b = blkalloc_lk(a)) == -1){
 		qunlock(a);
 		poperror();
 		goto Again;
--- a/cons.c
+++ b/cons.c
@@ -235,6 +235,54 @@
 
 }
 
+void
+showfid(int fd, char**, int)
+{
+	int i;
+	Fid *f;
+	Conn *c;
+
+	for(c = fs->conns; c != nil; c = c->next){
+		fprint(fd, "fids:\n");
+		for(i = 0; i < Nfidtab; i++){
+			lock(&c->fidtablk[i]);
+			for(f = c->fidtab[i]; f != nil; f = f->next){
+				rlock(f->dent);
+				fprint(fd, "\tfid[%d] from %#zx: %d [refs=%ld, k=%K, qid=%Q]\n",
+					i, getmalloctag(f), f->fid, f->dent->ref, &f->dent->Key, f->dent->qid);
+				runlock(f->dent);
+			}
+			unlock(&c->fidtablk[i]);
+		}
+	}
+}
+
+void
+showtree(int fd, char **ap, int na)
+{
+	char *name;
+	Tree *t;
+	Blk *b;
+	int h;
+
+	name = "main";
+	memset(&t, 0, sizeof(t));
+	if(na == 1)
+		name = ap[0];
+	if(strcmp(name, "snap") == 0)
+		t = &fs->snap;
+	else if((t = opensnap(name, nil)) == nil){
+		fprint(fd, "open %s: %r\n", name);
+		return;
+	}
+	b = getroot(t, &h);
+	fprint(fd, "=== [%s] %B @%d\n", name, t->bp, t->ht);
+	showblk(fd, b, "contents", 1);
+	dropblk(b);
+	if(t != &fs->snap)
+		closesnap(t);
+}
+
 static void
 permflip(int fd, char **ap, int)
 {
@@ -248,36 +296,33 @@
 }
 
 static void
+unreserve(int fd, char **ap, int)
+{
+	if(strcmp(ap[0], "on") == 0)
+		usereserve = 0;
+	else if(strcmp(ap[0], "off") == 0)
+		usereserve = 1;
+	else
+		fprint(2, "unknown reserve %s\n", ap[0]);
+	fprint(fd, "reserve: %d → %d\n", !permissive, permissive);
+}
+static void
 help(int fd, char**, int)
 {
 	char *msg =
-		"help\n"
-		"	show this help\n"
-		"check\n"
-		"	run a consistency check on the file system\n"
-		"df\n"
-		"	show disk usage stats\n"
-		"halt\n"
-		"	stop all writers, sync, and go read-only\n"
-		"permissive [on|off]\n"
-		"	switch to/from permissive mode\n"
-		"snap (-d old | old new)\n"
-		"	delete, create or update a new snapshot based off old\n"
-		"sync\n"
-		"	flush all pending writes to disk\n"
-		"users\n"
-		"	reload user table from /adm/users in the main snap\n"
-		"show\n"
-		"	show debug information, the following dumps\n"
-		"	are supported:\n"
+		"help -- show this help\n"
+		"check -- check for consistency\n"
+		"df -- show disk usage\n"
+		"halt -- stop all writers, sync, and go read-only\n"
+		"permit [on|off] -- switch to/from permissive mode\n"
+		"reserve [on|off] -- enable block reserves\n"
+		"snap -[Smdl] [old [new]] -- manage snapshots\n"
+		"sync --flush all pending writes to disk\n"
+		"users -- reload user table from adm snapshot\n"
+		"show -- debug dumps\n"
 		"	tree [name]\n"
-		"		the contents of the tree associated with a\n"
-		"		snapshot. The special name 'snap' shows the\n"
-		"		snapshot tree\n"
 		"	fid\n"
-		"		the summary of open fids\n"
-		"	users\n"
-		"		the known user file\n";
+		"	users\n";
 	fprint(fd, "%s", msg);
 }
 
@@ -287,9 +332,10 @@
 	{.name="df",		.sub=nil, 	.minarg=0, .maxarg=0, .fn=showdf},
 	{.name="halt",		.sub=nil,	.minarg=0, .maxarg=0, .fn=haltfs},
 	{.name="help",		.sub=nil,	.minarg=0, .maxarg=0, .fn=help},
-	{.name="permissive",	.sub=nil,	.minarg=1, .maxarg=1, .fn=permflip},
+	{.name="permit",	.sub=nil,	.minarg=1, .maxarg=1, .fn=permflip},
 	{.name="snap",		.sub=nil,	.minarg=1, .maxarg=3, .fn=snapfs},
 	{.name="sync",		.sub=nil,	.minarg=0, .maxarg=0, .fn=syncfs},
+	{.name="reserve",	.sub=nil,	.minarg=0, .maxarg=1, .fn=unreserve},
 	{.name="users",		.sub=nil,	.minarg=0, .maxarg=1, .fn=refreshusers},
 
 	/* debugging */
--- a/dump.c
+++ b/dump.c
@@ -331,32 +331,6 @@
 }
 
 void
-showtree(int fd, char **ap, int na)
-{
-	char *name;
-	Tree *t;
-	Blk *b;
-	int h;
-
-	name = "main";
-	memset(&t, 0, sizeof(t));
-	if(na == 1)
-		name = ap[0];
-	if(strcmp(name, "snap") == 0)
-		t = &fs->snap;
-	else if((t = opensnap(name, nil)) == nil){
-		fprint(fd, "open %s: %r\n", name);
-		return;
-	}
-	b = getroot(t, &h);
-	fprint(fd, "=== [%s] %B @%d\n", name, t->bp, t->ht);
-	rshowblk(fd, b, 0, 1);
-	dropblk(b);
-	if(t != &fs->snap)
-		closesnap(t);
-}
-
-void
 showbp(int fd, Bptr bp, int recurse)
 {
 	Blk *b;
--- a/fns.h
+++ b/fns.h
@@ -10,6 +10,7 @@
 extern Gefs*	fs;
 extern int	debug;
 extern int	permissive;
+extern int	usereserve;
 extern char*	reamuser;
 extern void**	errctx;
 extern Blk*	blkbuf;
@@ -124,8 +125,6 @@
 void	showblk(int, Blk*, char*, int);
 void	showbp(int, Bptr, int);
 void	showtreeroot(int, Tree*);
-void	showtree(int, char**, int);
-void	showfid(int, char**, int);
 int	checkfs(int);
 
 #define dprint(...) \
--- a/fs.c
+++ b/fs.c
@@ -537,28 +537,6 @@
 	unlock(&fs->dtablk);
 }
 
-void
-showfid(int fd, char**, int)
-{
-	int i;
-	Fid *f;
-	Conn *c;
-
-	for(c = fs->conns; c != nil; c = c->next){
-		fprint(fd, "fids:\n");
-		for(i = 0; i < Nfidtab; i++){
-			lock(&c->fidtablk[i]);
-			for(f = c->fidtab[i]; f != nil; f = f->next){
-				rlock(f->dent);
-				fprint(fd, "\tfid[%d] from %#zx: %d [refs=%ld, k=%K, qid=%Q]\n",
-					i, getmalloctag(f), f->fid, f->dent->ref, &f->dent->Key, f->dent->qid);
-				runlock(f->dent);
-			}
-			unlock(&c->fidtablk[i]);
-		}
-	}
-}
-
 static Fid*
 getfid(Conn *c, u32int fid)
 {
--- a/main.c
+++ b/main.c
@@ -17,6 +17,7 @@
 int	noauth;
 int	nproc;
 int	permissive;
+int	usereserve;
 char	*reamuser;
 char	*dev;
 vlong	cachesz 	= 512*MiB;
--- a/ream.c
+++ b/ream.c
@@ -244,6 +244,7 @@
 	sz = d->length;
 	free(d);
 
+	print("reaming %s\n", dev);
 	if(sz < 128*MiB+Blksz)
 		sysfatal("ream: disk too small");
 	mnt = emalloc(sizeof(Mount), 1);