shithub: gefs

Download patch

ref: 34be16ef74b0c991850ee82931e9bd21f01a0a4f
parent: c25ea72c90893cf97d313178f5e2a38077cd9cd4
author: Ori Bernstein <[email protected]>
date: Sun Dec 12 22:01:42 EST 2021

sync: separate snapshots from dataset names

--- a/blk.c
+++ b/blk.c
@@ -728,7 +728,10 @@
 	b->freed = getcallerpc(&b);
 	unlock(b);
 	dprint("freeing block %B @ %ld, from 0x%p\n", b->bp, b->ref, getcallerpc(&b));
-	freebp(b->bp);
+	if(b->bp.gen == fs->nextgen)
+		freebp(b->bp);
+//	else
+//		deadlist(b->bp);
 }
 
 void
--- a/check.c
+++ b/check.c
@@ -260,29 +260,16 @@
 void
 showfs(int fd, char **ap, int na)
 {
-	char *p, *e, *name, kbuf[Kvmax], kvbuf[Kvmax];;
+	char *e, *name;
 	Tree t;
-	Key k;
-	Kvp kv;
 
-	name = (na == 0) ? "main" : ap[0];
-	k.k = kbuf;
-	k.k[0] = Ksnap;
-	k.nk = 1+snprint(k.k+1, sizeof(kbuf)-1, "%s", name);
-	if((e = btlookup(&fs->snap, &k, &kv, kvbuf, sizeof(kvbuf))) != nil){
-		fprint(fd, "lookup %K: %s\n", &k, e);
+	name = "main";
+	if(na == 1)
+		name = ap[0];
+	if((e = opensnap(&t, name)) != nil){
+		fprint(fd, "open %s: %s\n", name, e);
 		return;
 	}
-	if(kv.nv != Rootsz+Ptrsz){
-		fprint(fd, "bad snap %P\n", &kv);
-		return;
-	}
-
-	p = kv.v;
-	t.ht = GBIT32(p); p += 4;
-	t.bp.addr = GBIT64(p); p += 8;
-	t.bp.hash = GBIT64(p); p += 8;
-	t.bp.gen = GBIT64(p);
 	showtree(fd, &t, name);
 }
 
--- a/dat.h
+++ b/dat.h
@@ -48,6 +48,8 @@
 	Ptrsz	= 24,			/* off, hash, gen */
 	Fillsz	= 2,			/* block fill count */
 	Offksz	= 17,			/* type, qid, off */
+	Snapsz	= 9,			/* tag, snapid */
+	Treesz	= 4+Ptrsz+Ptrsz,	/* height, root, deadlist */
 	Kvmax	= Keymax + Inlmax,	/* Key and value */
 	Kpmax	= Keymax + Ptrsz,	/* Key and pointer */
 	
@@ -70,8 +72,8 @@
 	 */
 	Kdat,	/* qid[8] off[8] => ptr[16]:	pointer to data page */
 	Kent,	/* pqid[8] name[n] => dir[n]:	serialized Dir */
-	Ksnap,	/* sid[8] => ref[8], tree[24]:	snapshot root */
 	Kdset,	/* name[] => snapid[]:		dataset (snapshot ref) */
+	Ksnap,	/* sid[8] => ref[8], tree[52]:	snapshot root */
 	Ksuper,	/* qid[8] => pqid[8]:		parent dir */
 };
 
@@ -252,6 +254,7 @@
 struct Tree {
 	Lock	lk;
 	Bptr	bp;
+	Bptr	dp;
 	int	ht;
 };
 
@@ -290,8 +293,8 @@
 	Tree	snap;
 
 	Lock	qidlk;
-	vlong	nextqid;
-	vlong	nextgen; /* unlocked: only touched by mutator thread */
+	uvlong	nextqid;
+	uvlong	nextgen; /* unlocked: only touched by mutator thread */
 
 	Arena	*arenas;
 	int	narena;
@@ -371,11 +374,8 @@
 
 struct Mount {
 	long	ref;
-	Msg	m;
-	char	kbuf[Keymax];
-	char	vbuf[Rootsz+Ptrsz];
+	char	*name;
 	Tree	root;
-	Bptr	dead;
 };
 
 struct Fid {
--- a/dump.c
+++ b/dump.c
@@ -25,8 +25,11 @@
 	case Kent:	/* pqid[8] name[n] => dir[n]:	serialized Dir */
 		n = fmtprint(fmt, "ent dir:%llx, name:\"%.*s\")", GBIT64(k->k+1), k->nk-11, k->k+11);
 		break;
+	case Kdset:	/* name[n] => tree[24]:	snapshot ref */
+		n = fmtprint(fmt, "dset name:\"%.*s\"", k->nk-1, k->k+1);
+		break;
 	case Ksnap:	/* name[n] => tree[24]:	snapshot root */
-		n = fmtprint(fmt, "snap name:\"%.*s\"", k->nk-1, k->k+1);
+		n = fmtprint(fmt, "snap id:\"%llx\"", GBIT64(k->k+1));
 		break;
 	case Ksuper:	/* qid[8] => pqid[8]:		parent dir */
 		n = fmtprint(fmt, "up parent:%llx ptr:%llx", GBIT64(k->k+1), GBIT64(k->k+9));
@@ -101,6 +104,9 @@
 		bp.hash = GBIT64(v->v+12);
 		bp.gen = GBIT64(v->v+20);
 		n = fmtprint(fmt, "ht:%d, ptr:%B", ht, bp);
+		break;
+	case Kdset:
+		n = fmtprint(fmt, "snap id:\"%llx\"", GBIT64(v->v+1));
 		break;
 	case Ksuper:	/* qid[8] => pqid[8]:		parent dir */
 		n = fmtprint(fmt, "parent: %llx", GBIT64(v->v));
--- a/fns.h
+++ b/fns.h
@@ -30,8 +30,8 @@
 u32int	ihash(vlong);
 void	finalize(Blk*);
 char*	fillsuper(Blk*);
-char*	snapshot(Mount*);
-char*	loadsnap(Tree*, char*);
+char*	snapshot(Tree*, char*, int);
+char*	opensnap(Tree*, char*);
 uvlong	siphash(void*, usize);
 void	reamfs(char*);
 int	loadarena(Arena*, vlong);
@@ -119,4 +119,5 @@
 void	runcons(int, void*);
 
 /* it's in libc... */
-extern int cas(long *, long, long);
+extern int cas(long*, long, long);
+extern int cas64(u64int*, u64int, u64int);
\ No newline at end of file
--- a/fs.c
+++ b/fs.c
@@ -483,10 +483,10 @@
 static void
 fsattach(Fmsg *m, int iounit)
 {
-	char *p, *ep, dbuf[Kvmax], kvbuf[Kvmax];
+	char *e, *p, *ep, dbuf[Kvmax], kvbuf[Kvmax];
 	int err;
 	Mount *mnt;
-	Dent *e;
+	Dent *de;
 	Fcall r;
 	Kvp kv;
 	Key dk;
@@ -498,34 +498,14 @@
 		return;
 	}
 
-	if(1+strlen(m->aname) >= sizeof(mnt->kbuf)){
-		rerror(m, Ename);
-		return;
-	}
 	print("attach %s\n", m->aname);
-	mnt->m.k = mnt->kbuf;
-	mnt->m.k[0] = Ksnap;
-	mnt->m.nk = 1+snprint(mnt->m.k+1, sizeof(mnt->kbuf)-1, "%s", m->aname);
-	mnt->m.v = mnt->vbuf;
-	mnt->m.nv = sizeof(mnt->vbuf);
-	if(btlookup(&fs->snap, &mnt->m, &kv, kvbuf, sizeof(kvbuf)) != nil){
-		rerror(m, Enosnap);
+	mnt->name = strdup(m->aname);
+	if((e = opensnap(&mnt->root, m->aname)) != nil){
+		rerror(m, e);
 		return;
 	}
+print("got root %B\n", mnt->root.bp);
 
-	if(kv.nv != Rootsz+Ptrsz){
-		rerror(m, Efs);
-		return;
-	}
-	p = kv.v;
-	mnt->root.ht = GBIT32(p); p += 4;
-	mnt->root.bp.addr = GBIT64(p); p += 8;
-	mnt->root.bp.hash = GBIT64(p); p += 8;
-	mnt->root.bp.gen = GBIT64(p); p += 8;
-	mnt->dead.addr = GBIT64(p); p += 8;
-	mnt->dead.hash = GBIT64(p); p += 8;
-	mnt->dead.gen = GBIT64(p);
-
 	err = 0;
 	p = dbuf;
 	ep = dbuf + sizeof(dbuf);
@@ -544,7 +524,7 @@
 		rerror(m, Efs);
 		return;
 	}
-	if((e = getdent(-1, &d)) == nil){
+	if((de = getdent(-1, &d)) == nil){
 		rerror(m, Efs);
 		return;
 	}
@@ -555,7 +535,7 @@
 	 * by one on the refcount. Adjust to
 	 * compensate for the dup.
 	 */
-	adec(&e->ref);
+	adec(&de->ref);
 
 	memset(&f, 0, sizeof(Fid));
 	f.fid = NOFID;
@@ -563,7 +543,7 @@
 	f.qpath = d.qid.path;
 	f.mode = -1;
 	f.iounit = iounit;
-	f.dent = e;
+	f.dent = de;
 	if(dupfid(m->fid, &f) == nil){
 		rerror(m, Enomem);
 		return;
@@ -808,7 +788,7 @@
 	r.type = Rcreate;
 	r.qid = d.qid;
 	r.iounit = f->iounit;
-	if((e = snapshot(f->mnt)) != nil){
+	if((e = snapshot(&f->mnt->root, f->mnt->name, 1)) != nil){
 		rerror(m, e);
 		putfid(f);
 		return;
@@ -850,7 +830,7 @@
 	runlock(f->dent);
 	clunkfid(f);
 
-	if((e = snapshot(f->mnt)) != nil){
+	if((e = snapshot(&f->mnt->root, f->mnt->name, 1)) != nil){
 		rerror(m, e);
 		putfid(f);
 		return;
@@ -1130,7 +1110,7 @@
 	}
 	wunlock(f->dent);
 
-	if((e = snapshot(f->mnt)) != nil){
+	if((e = snapshot(&f->mnt->root, f->mnt->name, 1)) != nil){
 		rerror(m, e);
 		putfid(f);
 		return;
--- a/mkfile
+++ b/mkfile
@@ -15,7 +15,6 @@
 	ream.$O\
 	sync.$O\
 	tree.$O\
-	util.$O\
 
 HFILES=\
 	dat.h\
--- a/ream.c
+++ b/ream.c
@@ -43,13 +43,23 @@
 static void
 initsnap(Blk *s, Blk *r)
 {
-	char kbuf[32], vbuf[Rootsz+Ptrsz];
+	char kbuf[Keymax], vbuf[Treesz];
 	Kvp kv;
 
+
 	kv.k = kbuf;
 	kv.v = vbuf;
-	kv.k[0] = Ksnap;
+	kv.k[0] = Kdset;
 	kv.nk = 1 + snprint(kv.k+1, sizeof(kbuf)-1, "main");
+	kv.v[0] = Ksnap;
+	PBIT64(kv.v+1, 0);
+	kv.nv = Snapsz;
+	setval(s, 0, &kv);
+	
+	kv.k[0] = Ksnap;
+	PBIT64(kv.k+1, 0);
+	kv.nk = Snapsz;
+
 	kv.nv = sizeof(vbuf);
 	PBIT32(kv.v +  0, 1);
 	PBIT64(kv.v +  4, r->bp.addr);
@@ -58,7 +68,7 @@
 	PBIT64(kv.v + 28, -1ULL);
 	PBIT64(kv.v + 36, -1ULL);
 	PBIT64(kv.v + 42, -1ULL);
-	setval(s, 0, &kv);
+	setval(s, 1, &kv);
 }
 
 static void
--- a/sync.c
+++ b/sync.c
@@ -6,6 +6,19 @@
 #include "dat.h"
 #include "fns.h"
 
+vlong
+inc64(uvlong *v, uvlong dv)
+{
+	vlong ov, nv;
+
+	while(1){
+		ov = *v;
+		nv = ov + dv;
+		if(cas64(v, ov, nv))
+			return nv;
+	}
+}
+
 int
 syncblk(Blk *b)
 {
@@ -28,23 +41,81 @@
 	}
 }
 
+char*
+opensnap(Tree *t, char *name)
+{
+	char dbuf[Keymax], buf[Kvmax];
+	char *p, *e;
+	int n;
+	Key k;
+	Kvp kv;
 
+	n = strlen(name);
+	p = dbuf;
+	p[0] = Kdset;			p += 1;
+	memcpy(p, name, n);		p += n;
+	k.k = dbuf;
+	k.nk = p - dbuf;
+	if((e = btlookup(&fs->snap, &k, &kv, buf, sizeof(buf))) != nil)
+		return e;
+	memmove(dbuf, kv.v, kv.nv);
+	k.k = dbuf;
+	k.nk = kv.nv;
+	if((e = btlookup(&fs->snap, &k, &kv, buf, sizeof(buf))) != nil)
+		return e;
+	p = kv.v;
+	t->ht = GBIT32(p);		p += 4;
+	t->bp.addr = GBIT64(p);		p += 8;
+	t->bp.hash = GBIT64(p);		p += 8;
+	t->bp.gen = GBIT64(p);		p += 8;
+	t->dp.addr = GBIT64(p);		p += 8;
+	t->dp.hash = GBIT64(p);		p += 8;
+	t->dp.gen = GBIT64(p);
+	return nil;
+}
+
 char*
-snapshot(Mount *mnt)
+snapshot(Tree *r, char *name, int update)
 {
-	char *e;
+	char dbuf[Keymax], snapbuf[Snapsz], treebuf[Treesz];
+	char *p, *e;
+	uvlong gen;
+	int n;
+	Msg m[2];
 
-	mnt->m.op = Oinsert;
-//	mnt->m.k[0] = Ksnap;
-//	PBIT64(mnt->m.k +  1, fs->nextgen++);
-	PBIT32(mnt->m.v +  0, mnt->root.ht);
-	PBIT64(mnt->m.v +  4, mnt->root.bp.addr);
-	PBIT64(mnt->m.v + 12, mnt->root.bp.hash);
-	PBIT64(mnt->m.v + 20, mnt->root.bp.gen);
-	PBIT64(mnt->m.v + 28, mnt->dead.addr);
-	PBIT64(mnt->m.v + 36, mnt->dead.hash);
-	PBIT64(mnt->m.v + 42, mnt->dead.gen);
-	if((e = btupsert(&fs->snap, &mnt->m, 1)) != nil)
+	n = strlen(name);
+	if(update)
+		gen = inc64(&fs->nextgen, 0);
+	else
+		gen = inc64(&fs->nextgen, 1);
+
+	p = dbuf;
+	m[0].op = Oinsert;
+	p[0] = Kdset;		p += 1;
+	memcpy(p, name, n);	p += n;
+	m[0].k = dbuf;
+	m[0].nk = p - dbuf;
+
+	p = snapbuf;
+	p[0] = Ksnap;		p += 1;
+	PBIT64(p, gen);		p += 8;
+	m[0].v = snapbuf;
+	m[0].nv = p - snapbuf;
+
+	m[1].op = Oinsert;
+	m[1].k = snapbuf;
+	m[1].nk = p - snapbuf;
+	p = treebuf;
+	PBIT32(p, r->ht);	p += 4;
+	PBIT64(p, r->bp.addr);	p += 8;
+	PBIT64(p, r->bp.hash);	p += 8;
+	PBIT64(p, r->bp.gen);	p += 8;
+	PBIT64(p, r->dp.addr);	p += 8;
+	PBIT64(p, r->dp.hash);	p += 8;
+	PBIT64(p, r->dp.gen);	p += 8;
+	m[1].v = treebuf;
+	m[1].nv = p - treebuf;
+	if((e = btupsert(&fs->snap, m, nelem(m))) != nil)
 		return e;
 	if(sync() == -1)
 		return Eio;
@@ -51,7 +122,6 @@
 	return 0;
 }
 
-int
 sync(void)
 {
 	int i, r;
--- a/util.c
+++ /dev/null
@@ -1,41 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <avl.h>
-
-#include "dat.h"
-#include "fns.h"
-
-void *
-emalloc(usize n)
-{
-	void *v;
-	
-	v = mallocz(n, 1);
-	if(v == nil)
-		sysfatal("malloc: %r");
-	setmalloctag(v, getcallerpc(&n));
-	return v;
-}
-
-void *
-erealloc(void *p, usize n)
-{
-	void *v;
-	
-	v = realloc(p, n);
-	if(v == nil)
-		sysfatal("realloc: %r");
-	setmalloctag(v, getcallerpc(&n));
-	return v;
-}
-
-char*
-estrdup(char *s)
-{
-	s = strdup(s);
-	if(s == nil)
-		sysfatal("strdup: %r");
-	setmalloctag(s, getcallerpc(&s));
-	return s;
-}