shithub: gefs

Download patch

ref: 3ee102676b5d02a2310ba38b8565e96ee4df6aa9
parent: 0a951c125346c524c02bbe03b9541ced9464046f
author: Ori Bernstein <[email protected]>
date: Sat Nov 4 23:16:43 EST 2023

snap: don't create snapshots pre-garbled

we still deallocate blocks we shouldn't, but at least
we no longer start snapshots off pointing at junk

--- a/dat.h
+++ b/dat.h
@@ -272,6 +272,7 @@
 	Oclearb,	/* free block ptr if exists */
 	Oclobber,	/* remove file if it exists */
 	Owstat,		/* update kvp dirent */
+	Oretag,		/* reference a snap id */
 	Nmsgtype,	/* maximum message type */
 };
 
--- a/fns.h
+++ b/fns.h
@@ -67,7 +67,7 @@
 void	clunkmount(Mount*);
 
 char*	updatesnap(Tree**, Tree*, char*);
-char*	labelsnap(Tree*, char*, int);
+char*	tagsnap(Tree*, char*, int);
 char*	delsnap(Tree*, vlong, char*);
 char*	freedl(Dlist*, int);
 Tree*	opensnap(char*, int*);
@@ -144,6 +144,7 @@
 void	dlist2kv(Dlist*, Kvp*, char*, int);
 void	lbl2kv(char*, vlong, uint, Kvp*, char*, int);
 void	link2kv(vlong, vlong, Kvp*, char*, int);
+void	retag2kv(vlong, int, int, Kvp*, char*, int);
 void	tree2kv(Tree*, Kvp*, char*, int);
 
 int	kv2dir(Kvp*, Xdir*);
@@ -156,7 +157,7 @@
 char*	packbp(char*, int, Bptr*);
 char*	packdkey(char*, int, vlong, char*);
 char*	packdval(char*, int, Xdir*);
-char*	packlabel(char*, int, char*);
+char*	packlbl(char*, int, char*);
 char*	packsnap(char*, int, vlong);
 char*	packsuper(char*, int, vlong);
 char*	packtree(char*, int, Tree*);
--- a/fs.c
+++ b/fs.c
@@ -73,7 +73,7 @@
 			unlock(&fs->mountlk);
 			return;
 		}
-		if((e = labelsnap(t, a->new, a->mutable)) != nil){
+		if((e = tagsnap(t, a->new, a->mutable)) != nil){
 			fprint(a->fd, "snap: error creating '%s': %s\n", a->new, e);
 			unlock(&fs->mountlk);
 			return;
--- a/pack.c
+++ b/pack.c
@@ -398,6 +398,21 @@
 }
 
 void
+retag2kv(vlong gen, int dlbl, int dsucc, Kvp *kv, char *buf, int nbuf)
+{
+	char *p;
+
+	kv->k = buf;
+	if((p = packsnap(buf, nbuf, gen)) == nil)
+		abort();
+	kv->nk = p - buf;
+	kv->v = p;
+	p[0] = dlbl;
+	p[1] = dsucc;
+	kv->nv = 2;
+}
+
+void
 link2kv(vlong gen, vlong succ, Kvp *kv, char *buf, int nbuf)
 {
 	char *p;
@@ -450,7 +465,7 @@
 }
 
 char*
-packlabel(char *p, int sz, char *name)
+packlbl(char *p, int sz, char *name)
 {
 	int n;
 
--- a/ream.c
+++ b/ream.c
@@ -140,7 +140,7 @@
 	t.nlbl = 1;
 	t.ht = 1;
 	t.gen = fs->nextgen++;
-	t.prev = -1ULL;
+	t.prev = 0;
 	t.bp = a->bp;
 	p = packtree(p, e - p, &t);
 	kv.nv = p - kv.v;
@@ -155,11 +155,11 @@
 	kv.nk = p - kv.k;
 	kv.v = p;
 	memset(&t, 0, sizeof(Tree));
-	t.nsucc = 1;
+	t.nsucc = 0;
 	t.nlbl = 1;
 	t.ht = 1;
 	t.gen = fs->nextgen++;
-	t.prev = -1ULL;
+	t.prev = 0;
 	t.bp = r->bp;
 	p = packtree(p, e - p, &t);
 	kv.nv = p - kv.v;
--- a/snap.c
+++ b/snap.c
@@ -321,7 +321,7 @@
 
 		m[nm].op = Odelete;
 		m[nm].k = buf[nm];
-		if((e = packlabel(buf[nm], sizeof(buf[nm]), name)) == nil)
+		if((e = packlbl(buf[nm], sizeof(buf[nm]), name)) == nil)
 			return Ename;
 		m[nm].nk = e - m[nm].k;
 		m[nm].v = nil;
@@ -359,7 +359,7 @@
  * will show up in the dump.
  */
 char*
-labelsnap(Tree *t, char *name, int mutable)
+tagsnap(Tree *t, char *name, int mutable)
 {
 	char buf[3][Kvmax];
 	Msg m[3];
@@ -381,31 +381,23 @@
 		n->nsucc = 0;
 		n->ht = t->ht;
 		n->bp = t->bp;
-		n->prev = t->gen;
+		n->prev = t->prev;
 		n->base = t->gen;
 		n->gen = aincv(&fs->nextgen, 1);
 		n->memgen = aincv(&fs->nextgen, 1);
 
-		t->flag |= Tforked;
-		t->nsucc++;
-
-		m[i].op = Oinsert;
-		tree2kv(t, &m[i], buf[i], sizeof(buf[i]));
+		m[i].op = Oretag;
+		retag2kv(t->gen, 0, 1, &m[i], buf[i], sizeof(buf[i]));
 		i++;
-
 		m[i].op = Oinsert;
-		tree2kv(n, &m[i], buf[i], sizeof(buf[i]));
-		i++;
-
-		m[i].op = Oinsert;
 		lbl2kv(name, n->gen, 1, &m[i], buf[i], sizeof(buf[i]));
 		i++;
 	}else{
 		t->nlbl++;
-		m[i].op = Oinsert;
-		tree2kv(t, &m[i], buf[i], sizeof(buf[i]));
-		i++;
 
+		m[i].op = Oretag;
+		retag2kv(t->gen, 1, 0, &m[i], buf[i], sizeof(buf[i]));
+		i++;
 		m[i].op = Oinsert;
 		lbl2kv(name, t->gen, 0, &m[i], buf[i], sizeof(buf[i]));
 		i++;
@@ -426,15 +418,15 @@
 	char buf[4][Kvmax], *e;
 	Msg m[4];
 	Tree *t;
+	int i;
 
 	if(!o->dirty)
 		return nil;
 
 	/* update the old kvp */
-	o->nsucc++;
+	o->gen, o->nsucc, o->nlbl, o->bp);
 	o->nlbl--;
-	m[0].op = Oinsert;
-	tree2kv(o, &m[0], buf[0], sizeof(buf[0]));
+	o->nsucc++;
 
 	/* create the new one */
 
@@ -448,17 +440,31 @@
 	t->ht = o->ht;
 	t->bp = o->bp;
 	t->base = o->base;
-	t->prev = o->gen;
+	if(o->nlbl == 0 && o->nsucc == 1)
+		t->prev = o->prev;
+	else
+		t->prev = o->gen;
 	t->gen = o->memgen;
 	t->memgen = aincv(&fs->nextgen, 1);
 
-	m[1].op = Oinsert;
-	tree2kv(t, &m[1], buf[1], sizeof(buf[1]));
-	m[2].op = Oinsert;
-	link2kv(t->prev, t->gen, &m[2], buf[2], sizeof(buf[2]));
-	m[3].op = Oinsert;
-	lbl2kv(lbl, t->gen, Lmut, &m[3], buf[3], sizeof(buf[3]));
-	if((e = btupsert(&fs->snap, m, 4)) != nil){
+	i = 0;
+	m[i].op = Oretag;
+	retag2kv(o->gen, -1, 1, &m[i], buf[i], sizeof(buf[i]));
+	i++;
+
+	m[i].op = Oinsert;
+	tree2kv(t, &m[i], buf[i], sizeof(buf[i]));
+	i++;
+
+	m[i].op = Oinsert;
+	link2kv(t->prev, t->gen, &m[i], buf[i], sizeof(buf[i]));
+	i++;
+
+	m[i].op = Oinsert;
+	lbl2kv(lbl, t->gen, Lmut, &m[i], buf[i], sizeof(buf[i]));
+	i++;
+
+	if((e = btupsert(&fs->snap, m, i)) != nil){
 		free(t);
 		return e;
 	}
@@ -467,10 +473,8 @@
 	o->dirty = 0;
 
 	/* this was the last ref to the snap */
-	if(o->nlbl == 0 && o->nsucc == 1){
-		t->prev = o->prev;
+	if(o->nlbl == 0 && o->nsucc == 1)
 		delsnap(o, -1, nil);
-	}
 	closesnap(o);
 	asetp(r, t);
 	return nil;
@@ -490,7 +494,7 @@
 	Key k;
 
 	/* Klabel{"name"} => Ksnap{id} */
-	if((p = packlabel(buf, sizeof(buf), label)) == nil)
+	if((p = packlbl(buf, sizeof(buf), label)) == nil)
 		return nil;
 	k.k = buf;
 	k.nk = p - buf;
--- a/tree.c
+++ b/tree.c
@@ -400,6 +400,8 @@
 static int
 apply(Kvp *kv, Msg *m, char *buf, int nbuf)
 {
+	Tree t;
+
 	switch(m->op){
 	case Oclearb:
 	case Odelete:
@@ -412,6 +414,13 @@
 	case Owstat:
 		assert(keycmp(kv, m) == 0);
 		statupdate(kv, m);
+		return 1;
+	case Oretag:
+		assert(m->nv == 2);
+		unpacktree(&t, kv->v, kv->nv);
+		t.nlbl += m->v[0];
+		t.nsucc += m->v[1];
+		packtree(kv->v, kv->nv, &t);
 		return 1;
 	default:
 		abort();