code: mafs

Download patch

ref: 2b599f96e0df12f7558adee2979cce0a34395412
parent: 5e92e1cebea0aa1beb274d797461e577046d9b59
author: 9ferno <gophone2015@gmail.com>
date: Tue Nov 15 00:35:22 EST 2022

using different sizes for the directory entries and others

--- a/9p.c
+++ b/9p.c
@@ -48,7 +48,7 @@
 		respond(req, "phase error");
 		return;
 	}
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	req->fid->aux = newaux(Bdroot, uid);
 	req->fid->qid = (Qid){Qproot, d->qid.version, QTDIR};
 	putbuf(dbuf);
@@ -135,9 +135,9 @@
 		return;
 	}
 
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	/* nothing to do for already zero'ed out slots */
-	if(dbuf->io->path != Qpnone)
+	if(d->path != Qpnone)
 		fsmkdir(d, &req->d, nil);
 
 	putbuf(dbuf);
@@ -198,7 +198,7 @@
 		respond(req, errstring[Eperm]);
 		return;
 	}
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	if(canaccess(((Aux*)req->fid->aux)->uid, d, DMWRITE) == 0){
 		putbuf(dbuf);
 		respond(req, errstring[Eaccess]);
@@ -396,7 +396,7 @@
 			dbuf = getbufchk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
 			if(dbuf == nil)
 				return errstring[Ephase];
-			d = &dbuf->io->d;
+			d = dbuf->d;
 			if(chatty9p > 1)
 				dprint("fswalk1 .. d->name %s d->qid.path %llud d->pdblkno %llud\n",
 						d->name, d->qid.path, d->pdblkno);
@@ -404,7 +404,7 @@
 			if(pbuf == nil)
 				return errstring[Ephase];
 			putbuf(dbuf);
-			p = &pbuf->io->d;
+			p = pbuf->d;
 			*qid = (Qid){p->qid.path, p->qid.version, (p->mode&DMDIR) ? QTDIR : QTFILE};
 			if(aux != nil)
 				aux->dblkno = pbuf->blkno;
@@ -477,7 +477,6 @@
 	Iobuf *dbuf, *cbuf;
 	u64 reli, blkno;
 	Dentry *dchild, *dparent;
-	Content *ct;
 	u64 zblkno;	/* zero'ed dentry that can be reused */
 	Aux *aux;
 	u32 perm;
@@ -531,7 +530,7 @@
 		respond(req, errstring[Ephase]);
 		return;
 	}
-	dparent = &dbuf->io->d;
+	dparent = dbuf->d;
 	if(canaccess(((Aux*)req->fid->aux)->uid, dparent, DMWRITE) == 0){
 		respond(req, errstring[Eperm]);
 		return;
@@ -582,7 +581,7 @@
 					return;
 				}
 			}
-			dchild = &cbuf->io->d;
+			dchild = cbuf->d;
 			dchild->size = 0;
 			dchild->pdblkno = dbuf->blkno;
 			dchild->pqpath = dparent->qid.path;
@@ -655,23 +654,22 @@
 			respond(req, nil);
 			return;
 		}else{
-			cbuf = getbuf(blkno, Breadonly, Bused);
+			cbuf = getbuf(blkno, Dentryunits, Breadonly, Bused);
 			if(cbuf == nil){
 				putbuf(dbuf);
 				respond(req, errstring[Ephase]);
 				return;
 			}
-			dchild = &cbuf->io->d;
-			ct = (Content*)cbuf->io;
+			dchild = cbuf->d;
 
 			/* nothing to do for already zero'ed out slots */
-			if(ct->path == Qpnone){
+			if(dchild->path == Qpnone){
 				if(zblkno == 0)
 					zblkno = cbuf->blkno;
 				goto Nextdentry;
 			}
 
-			if(ct->type != Tdentry){
+			if(dchild->type != Tdentry){
 				putbuf(cbuf);
 				putbuf(dbuf);
 				respond(req, errstring[Ephase]);
@@ -742,7 +740,7 @@
 		respond(req, errstring[Ephase]);
 		return;
 	}
-	d = &dbuf->io->d;
+	d = dbuf->d;
 
 	if((mode & OTRUNC) != 0 &&
 		canaccess(aux->uid, d, DMWRITE) == 0)
@@ -906,7 +904,7 @@
 {
 	u32 pid;
 	Work w;
-} worker[Nprocs];	/* keeps track of running procs to flush */
+} worker[Nworkers];	/* keeps track of running procs to flush */
 
 void
 initworks(Buffer *b)
@@ -924,7 +922,7 @@
 	int i, a;
 
 	a = 0;
-	for(i = 0; i<Nprocs; i++){
+	for(i = 0; i<Nworkers; i++){
 		if(worker[i].w.f == nil){
 			if(worker[i].pid > 0 && worker[i].pid != getpid()){
 				// rwakeup(&buf.isempty); TODO why can't I get this to work?
@@ -943,7 +941,7 @@
 	int n, w, inv, i;
 
 	n = w = inv = 0;
-	for(i = 0; i<Nprocs; i++){
+	for(i = 0; i<Nworkers; i++){
 		if(worker[i].pid == 0)
 			inv++;
 		else if(worker[i].w.f == nil)
@@ -951,8 +949,8 @@
 		else if(worker[i].w.f != nil)
 			w++;
 	}
-	dprint("Nprocs %d inv %d idle %d working %d buf nworks %d hd %d tl %d\n",
-			Nprocs, inv, n, w, buf.nworks, buf.hd, buf.tl);
+	dprint("Nworkers %d inv %d idle %d working %d buf nworks %d hd %d tl %d\n",
+			Nworkers, inv, n, w, buf.nworks, buf.hd, buf.tl);
 }
 
 void
@@ -1053,7 +1051,7 @@
 	initworks(&buf);
 	if(chatty9p > 1)
 	dprint("parent pid: %d\n", getpid());
-	for(i = 0; i < Nprocs; i++){
+	for(i = 0; i < Nworkers; i++){
 		startproc(&buf, i);
 	}
 }
@@ -1227,7 +1225,7 @@
 	dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(dbuf == nil)
 		return 0;
-	filesize = dbuf->io->d.size;
+	filesize = dbuf->d->size;
 	putbuf(dbuf);
 	return filesize;
 }
@@ -1242,7 +1240,7 @@
 	dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(dbuf == nil)
 		return 0;
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	filesize = d->size;
 
 	if(offset >= filesize){
@@ -1249,6 +1247,12 @@
 		putbuf(dbuf);
 		return 0;
 	}
+	if(filesize < Ddatasize){
+		n = min(filesize-offset, rbufsize);
+		memcpy(rbuf, d->buf+offset, n);
+		putbuf(dbuf);
+		return n;
+	}
 	if(filesize - offset > rbufsize)
 		tosend = rbufsize;
 	else
@@ -1269,24 +1273,6 @@
 	return sent;
 }
 
-/* obsolete */
-/*s32
-updatefullspan(Dentry *d, char *wbuf, s32 wbufsize, u64 offset)
-{
-	Iobuf *buf;
-	s32 n;
-
-	if(d == nil || wbuf == nil || wbufsize == 0)
-		return 0;
-	buf = getdatablkat(d, offset/Blocksize, Bwritable);
-	if(buf == nil)
-		return -1;
-	n = min(Blocksize, wbufsize);
-	memcpy(buf->io->buf, wbuf, n);
-	putbuf(buf);
-	return n;
-}*/
-
 /* only for updating existing data */
 s32
 update(Dentry *d, u64 /* dblkno */, char *wbuf, s32 wbufsize, u64 offset)
@@ -1335,10 +1321,9 @@
 s32
 append(Dentry *d, u64 dblkno, char *wbuf, s32 wbufsize)
 {
-	Iobuf *buf, *bufs[Ntogether];
+	Iobuf *buf;
 	s32 howmuch;
-	u64 blkno, lastblksize, written, i, nblocks, startreli;
-	u64 blknos[Ntogether];
+	u64 blkno, lastblksize;
 
 	if(d == nil || wbuf == nil || wbufsize == 0)
 		return 0;
@@ -1348,54 +1333,27 @@
 	if((lastblksize=d->size%Blocksize) == 0){
 		/* last block is full, use a new block */
 		if(chatty9p > 1)
-		dprint("append new extent rel2abs d->name %s reli d->size %llud"
+		dprint("append new data block rel2abs d->name %s reli d->size %llud"
 				" d->size/Blocksize %llud\n",
 				d->name, d->size, d->size/Blocksize);
 
-		/* can I write multiple blocks at once? */
-		if((nblocks = wbufsize/Blocksize) > 1){
-			startreli = d->size/Blocksize;
-			if(allocblocks(Tdata, d->qid.path, nblocks, bufs) == 0)
-				return -1;
-			written = 0;
-			for(i = 0; i<nblocks; i++){
-				howmuch = min(Blocksize, wbufsize-written);
-				memcpy(bufs[i]->io->buf, wbuf+written, howmuch);
-				written += howmuch;
-				blknos[i] = bufs[i]->blkno;
-			}
-			putbufs(bufs, nblocks);
-			for(i = 0; i<nblocks; i++){
-				if(addrelative(d, dblkno, startreli+i, blknos[i]) == 0){
-					panic("could not write Tdata block\n");
-					return -2;
-				}
-			}
-			return written;
-		}else{
-			/* write single block */
-			howmuch = min(Blocksize, wbufsize);
-			buf = allocblock(Tdata, d->qid.path);
-			if(buf == nil)
-				return -1;
-			blkno = buf->blkno;
-			memcpy(buf->io->buf, wbuf, howmuch);
-			putbuf(buf);
+		/* write single block */
+		howmuch = min(Blocksize, wbufsize);
+		buf = allocblock(Tdata, d->qid.path);
+		if(buf == nil)
+			return -1;
+		blkno = buf->blkno;
+		memcpy(buf->io->buf, wbuf, howmuch);
+		putbuf(buf);
 
-			if(addrelative(d, dblkno, d->size/Blocksize, blkno) == 0){
-				panic("could not write Tdata block\n");
-				freeblock(blkno, Tdata, d->qid.path);
-				return -2;
-			}
-			return howmuch;
+		if(addrelative(d, dblkno, d->size/Blocksize, blkno) == 0){
+			panic("could not write Tdata block\n");
+			freeblock(blkno, Tdata, d->qid.path);
+			return -2;
 		}
+		return howmuch;
 	}else{
 		/* last block is partially full, fill it up */
-		/*
-		get the old block and the new Span
-		copy from the old Span to the new
-		addrelative the new Span
-		free the old Span */
 
 		blkno = rel2abs(d, d->size/Blocksize);
 		if(blkno == 0)
@@ -1454,14 +1412,37 @@
 	Dentry *d;
 	s64 written;
 	s32 n;
-	Iobuf *dbuf;
+	Iobuf *dbuf, *buf;
+	u64 blkno;
 
 	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 		return 0;
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	d->muid = uid;
 	// odentry(d);
+
+	// little data, stuff it in the Dentry
+	if(d->size<=Ddatasize && offset+wbufsize < Ddatasize){
+		memcpy(d->buf+offset, wbuf, wbufsize);
+		if(offset+wbufsize > d->size)
+			d->size = offset+wbufsize;
+		written = wbufsize;
+		goto writeend;
+	}
+	// more data, relocate it to a proper data block
+	if(d->size > 0 && d->size <= Ddatasize && offset+wbufsize > Ddatasize){
+		buf = allocblock(Tdata, d->qid.path);
+		if(buf == nil){
+			written = 0;
+			goto writeend;
+		}
+		blkno = buf->blkno;
+		memcpy(buf->io->buf, d->buf, d->size);
+		putbuf(buf);
+		memset(d->buf, 0, d->size);
+		d->dblocks[0] = blkno;
+	}
 
 	for(written = 0; written < wbufsize; ){
 
--- a/TODO
+++ b/TODO
@@ -1,5 +1,6 @@
 test exclusive use file access
 test syncusers()
+fswstat TODO
 streamline the error codes
 mafswrite():
 	add user and remove user messages
--- a/all.h
+++ b/all.h
@@ -70,11 +70,13 @@
 	Ref;
 	RWLock;			/* controls access to this Iobuf */
 	u64	blkno;		/* block number on the disk, primary key */
+	u16	len;		/* number of Units */
 	Iobuf	*fore;	/* for lru */
 	Iobuf	*back;	/* for lru */
 	union{
 		u8	*xiobuf;	/* "real" buffer pointer */
 		Content *io;	/* cast'able to contents */
+		Dentry *d;
 	};
 
 	/*
@@ -100,14 +102,13 @@
 
 /* Iobuf routines - contents of the blocks in memory */
 void	initmemunitpool(u64 nunits);
-u8 *allocmemunit(void);
-void	freememunit(u8 *m);
+u8 *allocmemunits(u16 len);
+void	freememunits(u8 *m, u16 len);
 int		checktag(Iobuf *p, u16 tag, u64 qpath);
-Iobuf*	getbuf(u64 blkno, u8 readonly, u8 freshalloc);
+Iobuf*	getbuf(u64 blkno, u16 len, u8 readonly, u8 freshalloc);
 Iobuf*	getbufchk(u64 blkno, u8 readonly, int tag, u64 qpath);
 void	iobufinit(void);
 void	putbuf(Iobuf *p);
-void	putbufs(Iobuf **ps, u64 len);
 void	putbuffree(Iobuf *p);
 void	settag(Iobuf *p, int tag, u64 qpath);
 void	showbuf(Iobuf *p);
@@ -115,13 +116,11 @@
 /* writer functions */
 void	initwriter(void);
 void	putwrite(Iobuf *b);
-void	putwrites(Iobuf **bs, u64 len);
 void	stopwriter(void);
 u64		pendingwrites(void);
 
 /* routines to manipulate the contents */
 Iobuf*	allocblock(int tag, u64 qpath);
-u64	allocblocks(int tag, u64 qpath, u64 len, Iobuf **bufs);
 void	freeblockbuf(Iobuf *buf);
 void	freeblock(u64 blkno, u16 tag, u64 qpath);
 void	fsok(int ok);
--- a/blk.c
+++ b/blk.c
@@ -14,22 +14,37 @@
 		fprint(fd, "	%d %llud\n", j, lbuf[j]);
 }
 void
-showdentry(int fd, u8 *buf)
+showdentryhdr(int fd, u8 *buf)
 {
-	int j;
 	Dentry *d;
 
 	d = (Dentry*)buf;
-	fprint(fd, "qid.version %ud\n", d->qid.version);
-	fprint(fd, "qid.path %llud\n", d->qid.path);
+	fprint(fd, "name %s\n", d->name);
 	fprint(fd, "size %llud\n", d->size);
 	fprint(fd, "pdblkno %llud\n", d->pdblkno);
 	fprint(fd, "pqpath %llud\n", d->pqpath);
 	fprint(fd, "mtime %llud\n", d->mtime);
+	fprint(fd, "qid.path %llud\n", d->qid.path);
+	fprint(fd, "qid.version %ud\n", d->qid.version);
 	fprint(fd, "mode %uo\n", d->mode);
 	fprint(fd, "uid %d\n", d->uid);
 	fprint(fd, "gid %d\n", d->gid);
 	fprint(fd, "muid %d\n", d->muid);
+}
+void
+showdentry(int fd, u8 *buf)
+{
+	int j;
+	Dentry *d;
+
+	showdentryhdr(fd, buf);
+	d = (Dentry*)buf;
+	if(d->size <= Ddatasize && (d->mode&DMDIR) == 0 &&
+		d->qid.path != Qproot0 && d->qid.path != Qproot1
+		){
+		fprint(fd, "%s", d->buf);
+		return;
+	}
 	fprint(fd, "direct blocks\n");
 	for(j = 0; j<Ndblock; j++)
 		fprint(fd, "	%d %llud\n", j, d->dblocks[j]);
@@ -36,28 +51,27 @@
 	fprint(fd, "indirect blocks\n");
 	for(j = 0; j<Niblock; j++)
 		fprint(fd, "	%d %llud\n", j, d->iblocks[j]);
-	fprint(fd, "name %s\n", d->name);
 }
 void
-showmagic(int fd, u8 *buf)
+showmagic(int fd, u8 *d)
 {
-	fprint(fd, "%s", (char*)buf+256);
+	showdentryhdr(fd, d);
+	fprint(fd, "%s", ((Dentry*)d)->buf);
 }
 void
-showconfig(int fd, u8 *buf)
+showconfig(int fd, u8 *d)
 {
-	fprint(fd, "%s", (char*)buf);
+	showdentryhdr(fd, d);
+	fprint(fd, "%s", ((Dentry*)d)->buf);
 }
 void
-showsuper(int fd, u8 *buf)
+showsuper(int fd, u8 *d)
 {
-	Superb *s;
+	Super *s;
 
-	s = (Superb*)buf;
-	fprint(fd, "start %llud\n", s->start);
-	fprint(fd, "tfree %llud\n", s->tfree);
+	showdentryhdr(fd, d);
+	s = (Super*)d;
 	fprint(fd, "qidgen %llud\n", s->qidgen);
-	fprint(fd, "frees %llud\n", s->frees);
 	fprint(fd, "fsok %llud\n", s->fsok);
 }
 void
@@ -70,23 +84,34 @@
 showblock(int fd, u8 *buf)
 {
 	Content *t;
+	Dentry *d;
 
+	d = (Dentry*)buf;
+	/* this is not a fool proof way of identifying a Dentry */
+	if(d->type == Tdentry && d->len == Dentryunits){
+		if(d->path == Qpconfig || d->path == Qpconfig0 || d->path == Qpconfig1)
+			showconfig(fd, buf);
+		else if(d->path == Qpsuper || d->path == Qpsuper0 || d->path == Qpsuper1)
+			showsuper(fd, buf);
+		else if(d->path == Qpmagic)
+			showmagic(fd, buf);
+		else
+			showdentry(fd,buf);
+		return;
+	}
 	t = (Content*)buf;
 	if(t->type < Maxtind)
 		fprint(fd, "%s %llud\n", tagnames[t->type], t->path);
-	if(t->type == Tdentry){
-		showdentry(fd, buf);
-	}else if(t->path == Qpmagic){
-		showmagic(fd, buf);
-	}else if(t->path == Qpconfig || t->path == Qpconfig0 || t->path == Qpconfig1){
-		showconfig(fd, buf);
-	}else if(t->path == Qpsuper || t->path == Qpsuper0 || t->path == Qpsuper1){
-		showsuper(fd, buf);
-	}else if(t->type == Tdata){
+	else if(t->type == Tdata)
 		showdata(fd, buf);
-	}else if(t->type >= Tind0 && t->type < Maxtind){
+	else if(t->type >= Tind0 && t->type < Maxtind)
 		showind(fd, buf);
-	}else if(t->type != 0 || t->path != 0){
+	else if(t->type != 0 || t->path != 0)
 		fprint(fd, "unknown tag type %d path %llud\n", t->type, t->path);
-	}
+}
+
+u16
+blklen(u16 tag)
+{
+	return (tag == Tdentry ? Dentryunits : Rawblockunits);
 }
--- a/block.c
+++ b/block.c
@@ -18,7 +18,7 @@
 void
 main(int argc, char *argv[])
 {
-	u64 size, blkno;
+	u64 size, blkno, nunits;
 	u8 buf[Rawblocksize];
 
 	ARGBEGIN{
@@ -42,11 +42,18 @@
 		panic("null size %s", devfile);
 
 	if(debug){
-		print("Dentry1 size %d Namelen %llud\n", sizeof(Dentry1), Namelen);
 		print("Dentry size %d\n", sizeof(Dentry));
+		print("Dentryhdr size %d Ddatasize %llud Tag size %d\n",
+				sizeof(Dentryhdr), Ddatasize, sizeof(Tag));
+		print("Dentryblocks size %d Namelen %d Tag size %d\n",
+				sizeof(Dentryblocks), Namelen, sizeof(Tag));
 	}
 
-	devread(blkno, buf);
+	nunits = size/Unit;
+	if(blkno+Rawblockunits > nunits)
+		devread(blkno, buf, Dentryunits);
+	else
+		devread(blkno, buf, Rawblockunits);
 	showblock(1, buf);
 	close(devfd);
 	exits(0);
--- a/config.c
+++ b/config.c
@@ -8,10 +8,10 @@
 	char *tokens[128], cfg[Blocksize], *nl;
 	s32 n, i;
 
-	buf = getbufchk(dblkno, Breadonly, Tdata, Qpconfig);
+	buf = getbufchk(dblkno, Breadonly, Tdentry, Qpconfig);
 	if(buf == nil)
 		panic("cannot find config file in %llud block\n", dblkno);
-	memcpy(cfg, buf->io->buf, Blocksize);
+	memcpy(cfg, buf->d->buf, buf->d->size);
 	putbuf(buf);
 
 	n = tokenize(cfg, tokens, 128);
@@ -91,10 +91,10 @@
 	Iobuf *buf;
 	s32 n;
 
-	buf = getbufchk(bno, Bwritable, Tdata, Qpconfig);
+	buf = getbufchk(bno, Bwritable, Tdentry, Qpconfig);
 	if(buf == nil)
 		panic("cannot write config");
-	n = snprint((s8*)buf->io->buf, Blocksize,
+	n = snprint((s8*)buf->d->buf, Ddatasize,
 			"size %llud\n"
 			"nblocks %llud\n"
 			"backup config %llud to %llud %llud\n"
@@ -113,9 +113,10 @@
 			config.root.dest[0],
 			config.root.dest[1],
 			config.service);
-	if(n == Blocksize)
+	if(n == Ddatasize)
 		panic("config needs more blocks");
+	buf->d->size = n;
 	if(chatty9p > 1)
-		dprint("config:\n%s", buf->io->buf);
+		dprint("config:\n%s", buf->d->buf);
 	putbuf(buf);
 }
--- a/console.c
+++ b/console.c
@@ -70,8 +70,8 @@
 	dprint("(blocks) free %ulld, used %ulld, total %ulld\n",
 			free, used, config.nblocks);
 	dprint("(MiB) free %ulld, used %ulld, total %ulld\n",
-			free * Rawblocksize / 1048576,
-			used * Rawblocksize / 1048576,
+			free * Unit / 1048576,
+			used * Unit / 1048576,
 			config.size / 1048576);
 	qunlock(&superlock);
 	return 1;
--- a/ctl.c
+++ b/ctl.c
@@ -106,14 +106,14 @@
 						"(GiB) free %ulld, used %ulld, total %ulld\n"
 						"(TiB) free %ulld, used %ulld, total %ulld\n",
 						free, used, config.nblocks,
-						free * Rawblocksize / MiB,
-						used * Rawblocksize / MiB,
+						free * Unit / MiB,
+						used * Unit / MiB,
 						config.size / MiB,
-						free * Rawblocksize / GiB,
-						used * Rawblocksize / GiB,
+						free * Unit / GiB,
+						used * Unit / GiB,
 						config.size / GiB,
-						free * Rawblocksize / TiB,
-						used * Rawblocksize / TiB,
+						free * Unit / TiB,
+						used * Unit / TiB,
 						config.size / TiB
 						);
 	else if(config.size > GiB)
@@ -121,11 +121,11 @@
 						"(MiB) free %ulld, used %ulld, total %ulld\n"
 						"(GiB) free %ulld, used %ulld, total %ulld\n",
 						free, used, config.nblocks,
-						free * Rawblocksize / MiB,
-						used * Rawblocksize / MiB,
+						free * Unit / MiB,
+						used * Unit / MiB,
 						config.size / MiB,
-						free * Rawblocksize / GiB,
-						used * Rawblocksize / GiB,
+						free * Unit / GiB,
+						used * Unit / GiB,
 						config.size / GiB
 						);
 	else if(config.size > MiB)
@@ -132,8 +132,8 @@
 	n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
 						"(MiB) free %ulld, used %ulld, total %ulld\n",
 						free, used, config.nblocks,
-						free * Rawblocksize / MiB,
-						used * Rawblocksize / MiB,
+						free * Unit / MiB,
+						used * Unit / MiB,
 						config.size / MiB
 						);
 	else
@@ -140,8 +140,8 @@
 	n += snprint(buf+n, 1024-n, "(blocks) free %ulld, used %ulld, total %ulld\n"
 						"(KiB) free %ulld, used %ulld, total %ulld\n",
 						free, used, config.nblocks,
-						free * Rawblocksize / KiB,
-						used * Rawblocksize / KiB,
+						free * Unit / KiB,
+						used * Unit / KiB,
 						config.size / KiB
 						);
 	if(req->ifcall.offset < n){
--- a/dat.c
+++ b/dat.c
@@ -5,15 +5,11 @@
 char*	tagnames[] =
 {
 	[Tblank]	"Tblank",
-	[Tmagic]	"Tmagic",
 	[Tdentry]	"Tdentry",
 	[Tdata]		"Tdata",
 	[Tind0]		"Tind0",
 	[Tind1]		"Tind1",
 	[Tind2]		"Tind2",
-	[Tind3]		"Tind3",
-	[Tind4]		"Tind4",
-	[Tind5]		"Tind5",
 
 	/* add more Tind tags here ... */
 };
--- a/dat.h
+++ b/dat.h
@@ -8,6 +8,18 @@
 typedef unsigned int u32;
 typedef unsigned long long u64;
 
+typedef	struct	Config	Config;
+typedef	struct	Content	Content;
+typedef	struct	Dentryblocks	Dentryblocks;
+typedef	struct	Dentryhdr	Dentryhdr;
+typedef	struct	Dentry	Dentry;
+typedef struct	Qid9p1	Qid9p1;
+typedef	struct	Super	Super;
+typedef	struct	Tag	Tag;
+typedef	struct	Tlock	Tlock;
+typedef	struct	User	User;
+typedef struct	Aux Aux;
+
 enum
 {
 	KiB	= 1024ULL,	/* Kibibytes */
@@ -23,7 +35,6 @@
 	Nsec	= 1000ULL*1000*1000,
 	Usec	= 1000ULL*1000,
 	Msec	= 1000ULL,
-	MAXRPC	= 8192ULL,
 	Nbkp	= 2,
 };
 
@@ -36,33 +47,34 @@
  * for the system files to help me identify numbers easily.
  */
 enum {
-	Rawblocksize= 512ULL,	/* real block size */
+	Unit	= 512ULL,		/* minimum data unit size */
+	Dentryunits	= 1,		/* number of units per Tdentry */
+	Rawblockunits= 16,		/* number of units for others */
+
+	Dentrysize	= Dentryunits*Unit,		/* real block size of a Tdentry */
+	/* real block size of others. a multiple of Unit to keep the extents code uniform */
+	Rawblocksize= Rawblockunits*Unit,
+
+	Namelen = 130,	/* maximum length of a file name, calculated manually */
 	Ndblock	= 32,	/* number of direct blocks in a Dentry */
-	Niblock	= 6,	/* maximum depth of indirect blocks */
+	Niblock	= 3,	/* maximum depth of indirect blocks, can increase it to 6 without issues */
 
 	/* global block numbers. The bkp contents locations are calculated by ream() */
-	Bmagicb	= 0,	/* block number of first block. Bmagic conflicts with bio.h */
-	Bconfig	= 1,	/* block number of config contents */
-	Bsuper	= 2,	/* block number of super contents */
+	Bdmagic	= 0,	/* block number of first block. Bmagic conflicts with bio.h */
+	Bdconfig= 1,	/* block number of /adm/config dentry and contents */
+	Bdsuper	= 2,	/* block number of /adm/super dentry and contents */
 	Bdadm	= 3,	/* block number of /adm directory */
-	Bdconfig= 4,	/* block number of /adm/config dentry */
-	Bdsuper	= 5,	/* block number of /adm/super dentry */
-	Bdbkp	= 6,	/* block number of /adm/bkp directory */
-	Bdconfig0 = 7,	/* block number of /adm/bkp/config.0 dentry */
-	Bdsuper0  = 8,	/* block number of /adm/bkp/super.0 dentry */
-	Bdroot0	  = 9,	/* block number of /adm/bkp/root.0 dentry */
-	Bdconfig1 = 10,	/* block number of /adm/bkp/config.1 dentry */
-	Bdsuper1  = 11,	/* block number of /adm/bkp/super.1 dentry */
-	Bdroot1	= 12,	/* block number of /adm/bkp/root.1 dentry */
-	Bdusers	= 13,	/* block number of /adm/users/ dentry */
-	Bdusersinuse = 14,	/* block number of /adm/users/inuse dentry */
-	Busersinuse	= 15,	/* block number of /adm/users/inuse file contents */
-	Bdfrees = 16,	/* block number of /adm/frees dentry, text file of free extents */
+	Bdusers	= 4,	/* block number of /adm/users/ dentry */
 
+					/* contents of blocks below change on use */ 
+	Bdbkp	= 5,	/* block number of /adm/bkp directory */
+	Bdusersinuse = 6,	/* block number of /adm/users/inuse dentry and contents */
+	Bdfrees = 7,	/* block number of /adm/frees dentry, text file of free extents */
+
 					/* no user writes allowed on blocks below Bdctl */
-	Bdctl	= 17,	/* block number of /adm/ctl dentry, empty contents, virtual file */
-	Bdusersstaging = 18,/* block number of /adm/users/staging dentry */
-	Bdroot	= 19,	/* block number of root directory */
+	Bdctl	= 8,	/* block number of /adm/ctl dentry, empty contents, virtual file */
+	Bdusersstaging = 9,/* block number of /adm/users/staging dentry */
+	Bdroot	= 10,	/* block number of root directory */
 	Nbused,			/* blocks used up by default */
 	Nminblocks = Nbused+(Nbkp*3), /* number of blocks used by the above and the backup blocks */
 
@@ -69,19 +81,12 @@
 	/* Qpnone is the Tag.path of free blocks/extents(Tfree),
 		and zero'ed out dentry blocks */
 	Qpnone		= 0,
-	Qpmagic		= 1,		/* magic block Tag.qpath */
 	Qpconfig	= Bdconfig,	/* /adm/config block Tag.qpath */
 	Qpsuper		= Bdsuper,	/* /adm/super block Tag.qpath */
-
 	Qpadm		= Bdadm,	/* /adm */
-	Qpbkp		= Bdbkp,	/* /adm/bkp block Tag.qpath */
-	Qpconfig0	= Bdconfig0,/* /adm/bkp/config.0 block Tag.qpath */
-	Qpsuper0	= Bdsuper0,	/* /adm/bkp/super.0 block Tag.qpath */
-	Qproot0		= Bdroot0,	/* /adm/bkp/root.0 block Tag.qpath */
-	Qpconfig1	= Bdconfig1,/* /adm/bkp/config.1 block Tag.qpath */
-	Qpsuper1	= Bdsuper1,	/* /adm/bkp/super.1 block Tag.qpath */
-	Qproot1		= Bdroot1,	/* /adm/bkp/root.1 block Tag.qpath */
 	Qpusers		= Bdusers,	/* /adm/users block Tag.qpath */
+
+	Qpbkp		= Bdbkp,	/* /adm/bkp block Tag.qpath */
 	Qpusersinuse	= Bdusersinuse,	/* /adm/users/inuse block Tag.qpath */
 	Qpfrees		= Bdfrees,	/* /adm/frees block Tag.qpath */
 
@@ -89,6 +94,15 @@
 	Qpusersstaging	= Bdusersstaging,/* /adm/users/staging block Tag.qpath */
 	Qproot		= Bdroot,	/* /, so fscreate() can disallow any create's below */
 
+				/* system qpaths */
+	Qpmagic,	/* magic block Tag.qpath */
+	Qpconfig0,	/* /adm/bkp/config.0 block Tag.qpath */
+	Qpsuper0,	/* /adm/bkp/super.0 block Tag.qpath */
+	Qproot0	,	/* /adm/bkp/root.0 block Tag.qpath */
+	Qpconfig1,	/* /adm/bkp/config.1 block Tag.qpath */
+	Qpsuper1,	/* /adm/bkp/super.1 block Tag.qpath */
+	Qproot1	,	/* /adm/bkp/root.1 block Tag.qpath */
+
 	Nqidgen	= 64,
 
 	/* check qpath for overflows - TODO, should be 2^64 */
@@ -95,66 +109,52 @@
 	Maxqpath = 72057594037927936ULL, /* 2^56 */
 
 	Nthdirty = 9,	/* dirty byte is the 9th byte in the Tag */
+
 };
 
-typedef	struct	Config	Config;
-typedef	struct	Content	Content;
-typedef	struct	Dentry1	Dentry1;
-typedef	struct	Dentry	Dentry;
-typedef struct	Qid9p1	Qid9p1;
-typedef	struct	Super1	Super1;
-typedef	struct	Superb	Superb;
-typedef	struct	Tag	Tag;
-typedef	struct	Tlock	Tlock;
-typedef	struct	User	User;
-typedef struct	Aux Aux;
-
 /*
  * DONT TOUCH -- data structures stored on disk
  */
 #pragma pack on
-/* DONT TOUCH, this is the disk structure */
 struct Tag
 {
 	u8 type;	/* Tmagic, Tdentry, Tdata, Tindn */
+	u16 len;	/* number of Units */
 	u64 path;	/* Qid.path, unique identifier */
 };
+#pragma pack off
 
-/* DONT TOUCH, this is the disk structure */
-struct Super1
-{
-	u64 start;	/* starting block */
-	u64 tfree;	/* total number of free blocks - obsolete? */
-	u64 qidgen;	/* generator for unique ids. starts from 1024. */
-
-	u64 frees;	/* list of free extents was written here at halt */
-			/* make fsok a time stamp with the highest bit being the fsok flag */
-	u64 fsok;	/* fsck status, using 64 bits to keep it all aligned */
+enum {
+	Blocksize	= Rawblocksize - sizeof(Tag),
 };
 
+#pragma pack on
 /* DONT TOUCH, this is the disk structure */
 struct Qid9p1
 {
-	u32 version;
 	u64 path;	/* unique identifier */
+	u32 version;
 };
 
 /* DONT TOUCH, this is the disk structure */
 /*
- * 1 dentry per block
  * no access time
  */
-struct Dentry1
+struct Dentryhdr
 {
-	Qid9p1	qid;
-	u64 size;		/* 0 for directories. For files, size in bytes of the content */
-	u64 pdblkno; 	/* block number of the parent directory entry. Will be 0 for root. */
-	u64 pqpath; 	/* parent qid.path */
-	u64 mtime;		/* modified time in nano seconds from epoch */
-	u32 mode;		/* same bits as defined in /sys/include/libc.h:/Dir\.mode/ */
-	s16 uid;
-	s16 gid;
-	s16 muid;
+	u64 size;		/* 0 for directories. For files, size in bytes of the content - 8 */
+	u64 pdblkno; 	/* block number of the parent directory entry. Will be 0 for root. - 16 */
+	u64 pqpath; 	/* parent qid.path - 24 */
+	u64 mtime;		/* modified time in nano seconds from epoch - 32 */
+	Qid9p1	qid;	/* 44 bytes */
+	u32 mode;		/* same bits as defined in /sys/include/libc.h:/Dir\.mode/ - 48 */
+	s16 uid;		/* 50 */
+	s16 gid;		/* 52 */
+	s16 muid;		/* 54 */
+	s8  name[Namelen]; /* 184, Namelen = 130 to align to a u64 */
+};
+struct Dentryblocks
+{
 	u64 dblocks[Ndblock];	/* direct blocks. */
 						/* List of Tdata block numbers for files and
 							Tdentry block numbers for directories */
@@ -161,7 +161,33 @@
 						/* Tag.type = Tdentry for directories and Tdata for files */
 	u64 iblocks[Niblock];	/* indirect blocks */
 };
+#pragma pack off
 
+enum {
+	/* max possible size of data that can be stuffed into a Dentry */
+	Ddatasize = Dentrysize -sizeof(Tag) -sizeof(Dentryhdr),
+};
+
+#pragma pack on
+struct Dentry
+{
+	Dentryhdr;
+	union
+	{
+		struct Dentryblocks;
+		/* when size <= Dentrysize-184-sizeof(Tag), store the data here itself */
+		s8 buf[Ddatasize];
+	};
+	Tag;
+};
+/* DONT TOUCH, this is the disk structure */
+struct Super
+{
+	Dentryhdr;
+	u64 qidgen;	/* generator for unique ids. starts from 1024. */
+			/* make fsok a time stamp with the highest bit being the fsok flag */
+	u64 fsok;	/* fsck status, using 64 bits to keep it all aligned */
+};
 #pragma pack off
 
 /*
@@ -170,42 +196,24 @@
  * Nindperblock number of block pointers in a block
  */
 enum {
-	Blocksize	= Rawblocksize - sizeof(Tag),
-	Namelen	= (Blocksize-sizeof(Dentry1)),	/* maximum size of the name of a file or directory */
-
-	Iounit		= MAXRPC, /* in bytes */
-	Ntogether	= (Iounit/Blocksize)+1,		/* max probable size for jumbo writes */
-
-	Ndentryperblock	= 1, /* Blocksize/sizeof(Dentry), */
+	MAXRPC	= Blocksize,/* Tdata block size in bytes */
+	Iounit	= MAXRPC,	/* in bytes, TODO adjust for the 9p header size? */
 	Nindperblock	= Blocksize/sizeof(u64),/* number of pointers per block */
 };
 
 #pragma pack on
 /* DONT TOUCH, this is the disk structure */
-struct Dentry
-{
-	struct	Dentry1;
-	char	name[Namelen];
-};
 struct Content	/* used to unmarshall the disk contents */
 {
-	union{
+	union
+	{
 		u8 buf[Blocksize];
 		u64 bufa[Nindperblock];
-		Dentry d;
 	};
 	Tag;
 };
 #pragma pack off
 
-#pragma pack on
-/* DONT TOUCH, this is the disk structure */
-struct Superb
-{
-	Super1;
-};
-#pragma pack off
-
 /*
  * array of qids that are locked
  */
@@ -259,7 +267,7 @@
 enum
 {
 	Nworks = 1024,	/* make this a parameter? */
-	Nprocs = 32,	/* make this a parameter? */
+	Nworkers = 2 /* 32 */,	/* make this a parameter? */
 	Nlru  = 32,
 	Nuserserrmsg = 64,
 };
@@ -324,6 +332,9 @@
  * tags on block
  */
 /* DONT TOUCH, this is in disk structures */
+/* the first 512 bytes holds the magic.
+	Not bothering with a tag for 1 Unit. Use Tdentry for that.
+ */
 /* also, the order from Tdata to Tmaxind is exploited in indirck() & isdirty() */
 enum
 {
@@ -330,8 +341,7 @@
 	Tblank = 0,
 	Tfree  = 0,	/* free block */
 	Tnone  = 0,
-	Tmagic,		/* the first (zero'th) block holds the magic */
-	Tdentry,	/* directory entry */
+	Tdentry,	/* directory entry, size = Dentrysize */
 				/* Tdata & indirect blocks are last, to allow for greater depth */
 	Tdata,		/* actual file contents */
 	Tind0,		/* contains a list of Tdata block numbers for files
@@ -338,11 +348,10 @@
 					and Tdentry block numbers for directories.*/
 	Tind1,		/* contains a list of Tind0 block numbers */
 	Tind2,		/* contains a list of Tind1 block numbers */
-	Tind3,		/* contains a list of Tind2 block numbers */
-	Tind4,		/* contains a list of Tind3 block numbers */
-	Tind5,		/* contains a list of Tind4 block numbers, maximum file size 26 TiB */
+				/* gap for more indirect block depth in future.
+					It can be put upto Tind5 without needing any code changes
+				 */
 	Maxtind,	/* should be Tind0+Niblock */
-				/* gap for more indirect block depth in future */
 	MAXTAG,
 
 	Tmaxind = Maxtind - 1,
--- a/dentry.c
+++ b/dentry.c
@@ -199,7 +199,7 @@
 	Dentry *d, d1;
 	int i;
 
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	memcpy(&d1, d, sizeof(Dentry));
 	for(i=0; i<Ndblock; i++)
 		d->dblocks[i] = 0;
@@ -262,6 +262,7 @@
 	Iobuf *dbuf;
 	Dentry d;
 	int i;
+	u64 size;
 
 	if(qpath < Qpusers || dblkno == 0)
 		return;
@@ -268,11 +269,15 @@
 	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
-	memcpy(&d, &dbuf->io->d, sizeof(Dentry));
-	memset(dbuf->io->buf, 0, Blocksize);
+	size = dbuf->d->size;
+	memcpy(&d, dbuf->d, sizeof(Dentry));
+	memset(dbuf->d, 0, Dentrysize);
 	settag(dbuf, Tdentry, Qpnone);
 	putbuf(dbuf);
 
+	if(size < Ddatasize)
+		return;
+
 	for(i=0; i<Ndblock; i++){
 		if(d.dblocks[i] == 0)
 			return;
@@ -302,8 +307,8 @@
 	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
-	memcpy(&d, dbuf->io->buf, sizeof(Dentry));
-	memset(dbuf->io->buf, 0, Blocksize);
+	memcpy(&d, dbuf->d, sizeof(Dentry));
+	memset(dbuf->d, 0, Dentrysize);
 	settag(dbuf, Tdentry, Qpnone);
 	putbuf(dbuf);
 
@@ -316,12 +321,12 @@
 		if((blkno = rel2abs(&d, reli)) == 0)
 			break;
 
-		buf = getbuf(blkno, Breadonly, Bused);
-		child = &buf->io->d;
+		buf = getbuf(blkno, Dentryunits, Breadonly, Bused);
+		child = buf->d;
 		cqpath = child->qid.path;
 		mode = child->mode;
-		ct.type = buf->io->type;
-		ct.path = buf->io->path;
+		ct.type = buf->d->type;
+		ct.path = buf->d->path;
 		putbuf(buf);
 
 		/* nothing to do for already zero'ed out slots */
@@ -403,13 +408,12 @@
 {
 	u64 reli, idx;
 	Dentry *d, *ch;
-	Tag *cht;
 	u64 blkno;
 
 	*dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(*dbuf == nil)
 		return nil;
-	d = &(*dbuf)->io->d;
+	d = (*dbuf)->d;
 
 	if(canaccess(uid, d, DMEXEC) == 0){
 		putbuf(*dbuf);
@@ -431,7 +435,7 @@
 			dprint("searchdir reli %d s.blkno %llud s.len %d\n",
 					reli, blkno);
 
-		*buf = getbuf(blkno, Breadonly, Bused);
+		*buf = getbuf(blkno, Dentryunits, Breadonly, Bused);
 		if(*buf == nil){
 			putbuf(*dbuf);
 			*dbuf = nil;
@@ -439,8 +443,7 @@
 			return nil;
 		}
 
-		ch = &(*buf)->io->d;
-		cht = (Tag*)(*buf)->io;
+		ch = (*buf)->d;
 		if(chatty9p > 2)
 			dprint("searchdir: dblkno %llud qpath %llud searchname %s searchidx %d"
 					" reli %llud blkno %llud ch->qid.path %llud\n",
@@ -455,11 +458,11 @@
 		}
 
 		/* nothing to do for already zero'ed out slots */
-		if(cht->type == Tdentry && cht->path == Qpnone)
+		if(ch->type == Tdentry && ch->path == Qpnone)
 			goto Nextdentry;
 
 		if(searchname != nil){
-			if(strcmp(searchname, ch->name) == 0){
+			if(strcmp(searchname, (char*)ch->name) == 0){
 				if(chatty9p > 2)
 				dprint("searchdir: found name %s\n", searchname);
 				return ch;
@@ -565,7 +568,7 @@
 	dbuf = getbufchk(dblkno, Bwritable, Tdentry, Qpfrees);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
-	d = &dbuf->io->d;
+	d = dbuf->d;
 	d->size = 0;
 	for(i=0; i<Ndblock; i++)
 		d->dblocks[i] = 0;
--- a/dev.c
+++ b/dev.c
@@ -18,47 +18,26 @@
 	return size;
 }
 
-/* TODO proper error handling */
-int
-devread(u64 blkno, void *b)
+s32
+devread(u64 blkno, void *b, u16 len)
 {
-	int n;
+	s32 n;
 
-	if((n= pread(devfd, b, Rawblocksize, blkno*Rawblocksize)) != Rawblocksize)
+	if((n= pread(devfd, b, len*Unit, blkno*Unit)) != len*Unit)
 		panic("devread failed: %r\n");
 	/* print("devread i %d n %d\n", i, n); */
 	return n;
 }
 
-int
-devwrites(u64 blkno, void *b, u64 n)
+s32
+devwrite(u64 blkno, void *b, u16 len)
 {
-	int wn;
+	s32 wn;
 
-	if((wn = pwrite(devfd, b, n*Rawblocksize, blkno*Rawblocksize)) != n*Rawblocksize)
+	if((wn = pwrite(devfd, b, len*Unit, blkno*Unit)) != len*Unit)
 		panic("devwrite failed: %r\n");
 	return wn;
 }
-
-int
-devwrite(u64 blkno, void *b)
-{
-	return devwrites(blkno, b, 1);
-}
-
-/* obsoleted, a hack for more efficient logging */
-/*int
-devrawwrite(void *b, int len, u64 offset)
-{
-	int i, n;
-
-	qlock(&d);
-	i = (n = pwrite(devfd, b, len, offset)) != len;
-	qunlock(&d);
-	if(i)
-		panic("devrawwrite failed: %r\n");
-	return n;
-}*/
 
 u64
 devinit(char *devfile)
--- a/docs/mafs.ms
+++ b/docs/mafs.ms
@@ -1560,9 +1560,9 @@
 	echo halt >> /n/mfs_ramfs_file/adm/ctl; lc /srv
 	unmount /n/mfs_ramfs
 
-	disk/mafs -r mafs_ramafs_file /n/ramfs/file
-	mount -c /srv/mafs_ramafs_file /n/mafs_ramafs_file
-	cat /dev/zero | tput -p > /n/mafs_ramafs_file/zeros.file # throttles down to mfs speed
+	disk/mafs -r mafs_ramfs_file /n/ramfs/file
+	mount -c /srv/mafs_ramfs_file /n/mafs_ramfs_file
+	cat /dev/zero | tput -p > /n/mafs_ramfs_file/zeros.file # throttles down to mfs speed
 		33.12 MB/s
 		33.17 MB/s
 		33.08 MB/s
@@ -1575,7 +1575,7 @@
 		15.94 MB/s
 		14.94 MB/s
 		14.11 MB/s
-	echo halt >> /n/mafs_ramafs_file/adm/ctl; lc /srv
+	echo halt >> /n/mafs_ramfs_file/adm/ctl; lc /srv
 	unmount /n/ramfs
 
 	dd -if /dev/zero -of /n/ramfs/file -count 700 -bs 1m
@@ -1605,6 +1605,7 @@
 		38.56 MB/s
 		37.13 MB/s
 		35.82 MB/s
+	echo halt >>/srv/hjfs.cmd
 .fi
 .sp
 .sp
--- a/extents.c
+++ b/extents.c
@@ -331,11 +331,6 @@
 			if(e == nil)
 				break;
 		}
-		if(chatty9p > 7){
-			print(" 	belongs(e %llud %llud %llud %p %p start %llud %llud %llud) %lld\n",
-					 e->start, e->start+e->len-1, e->len, e->low, e->high,
-					 start, start+len-1, len, dir);
-		}
 		/* e->low e eprev */
 		if(dir == 0)
 			return increment(es, e, start, len);
@@ -351,10 +346,6 @@
 			e = e->high;
 			if(e == nil)
 				break;
-		}
-		if(chatty9p > 7){
-			print(" 	belongs(e %llud %llud %llud start %llud %llud %llud) %lld\n",
-				 e->start, e->start+e->len-1, e->len, start, start+len-1, len, dir);
 		}
 		/* eprev e e->high */
 		if(dir == 0)
--- a/find.c
+++ b/find.c
@@ -19,7 +19,8 @@
 u64 parents[Ndir];
 u64 findblkno;
 
-void walkdentry(u64 blkno, s8 depth);
+void walkdirectory(u64 blkno, s8 depth);
+void walkfile(u64 blkno, s8 depth);
 Tag *readtag(u64 blkno, u8 *buf);
 
 static void
@@ -62,9 +63,9 @@
 	if(size == 0)
 		panic("null size %s", devfile);
 	if(debug)
-		print("%s %llud bytes %llud blocks\n", devfile, size, size/Rawblocksize);
+		print("%s %llud bytes %llud blocks\n", devfile, size, size/Unit);
 
-	walkdentry(Bdroot, 0);
+	walkdirectory(Bdroot, 0);
 	exits(0);
 }
 
@@ -106,7 +107,7 @@
 	u64 cblkno, *bufa;
 	int i;
 
-	devread(blkno, buf);
+	devread(blkno, buf, Rawblockunits);
 	t = (Content*)buf;
 	if(checkvalid(blkno, t, tag, qpath)){
 		if(t->type == Tind0){
@@ -116,11 +117,11 @@
 				if(cblkno == 0)
 					return;
 				cbuf = malloc(Rawblocksize);
-				devread(cblkno, cbuf);
+				devread(cblkno, cbuf, Rawblockunits);
 				ct = (Content*)cbuf;
-				if(ct->type == Tdentry && ct->type == bottomtag)
+				if(Tdentry == bottomtag)
 					/* another directory */
-					walkdentry(cblkno, depth);
+					walkdirectory(cblkno, depth);
 				else
 					checkvalid(cblkno, ct, bottomtag, qpath);
 				free(cbuf);
@@ -132,7 +133,7 @@
 				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				devread(cblkno, cbuf);
+				devread(cblkno, cbuf, Rawblockunits);
 				/* check tag */
 				walkindir(cblkno, tag-1,  bottomtag, qpath, depth);
 			}
@@ -163,43 +164,94 @@
 }
 
 void
-walkdentry(u64 blkno, s8 depth)
+walkdirectory(u64 blkno, s8 depth)
 {
+	u8 buf[Dentrysize], *cbuf;
+	Dentry *d, *cd;
+	Content *ct;
+	u64 cblkno;
+	int i;
+
+	devread(blkno, buf, Dentryunits);
+	d = (Dentry*)buf;
+	showdepth(depth);
+	print("%llud:%s\n", blkno, d->name);
+	if(debug)
+		print("walkdentry %llud tag %s name %s d->qid.path %llud\n",
+				blkno, tagnames[d->type], d->name, d->qid.path);
+	if(d->type != Tdentry || d->path != d->qid.path){
+		if(debug)
+			print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
+					blkno, tagnames[Tdentry], d->qid.path, tagnames[d->type], d->path);
+		fprint(2, "%llud\n", blkno);
+	}/*else
+		print("%llud\n", blkno);*/
+	addparent(depth, blkno);
+	for(i = 0; i<Ndblock; i++){
+		cblkno = d->dblocks[i];
+		if(cblkno == 0)
+			return;
+		cbuf = malloc(Dentrysize);
+		devread(cblkno, cbuf, Dentryunits);
+		cd = (Dentry*)cbuf;
+		if((cd->mode & DMDIR) > 0)
+			walkdirectory(cblkno, depth+1);
+		else
+			walkfile(cblkno, depth+1);
+		free(cbuf);
+	}
+	cbuf = malloc(Rawblocksize);
+	for(i = 0; i<Niblock; i++){
+		cblkno = d->iblocks[i];
+		if(cblkno == 0)
+			return;
+		devread(cblkno, cbuf, Rawblockunits);
+		ct = (Content*)cbuf;
+		if(ct->type == Tind0+i){
+			walkindir(cblkno, Tind0+i, Tdentry, d->qid.path, depth);
+		}else{
+			fprint(2, "invalid indir tag %llud\n", cblkno);
+			fprint(2, "%llud\n", cblkno);
+		}
+	}
+	free(cbuf);
+	return;
+}
+
+void
+walkfile(u64 blkno, s8 depth)
+{
 	u8 buf[Rawblocksize], *cbuf;
 	Dentry *d;
-	Content *t, *ct;
+	Content *ct;
 	u64 cblkno;
 	int i;
-	u8 isdir;
 
-	devread(blkno, buf);
-	t = (Content*)buf;
+	devread(blkno, buf, Dentryunits);
 	d = (Dentry*)buf;
-	isdir = (d->mode & DMDIR) > 0;
 	showdepth(depth);
 	print("%llud:%s\n", blkno, d->name);
 	if(debug)
-		print("walkdentry %llud tag %s name %s d->qid.path %llud\n",
-				blkno, tagnames[t->type], d->name, d->qid.path);
-	if(t->type != Tdentry || t->path != d->qid.path){
+		print("walkfile %llud tag %s name %s d->qid.path %llud\n",
+				blkno, tagnames[d->type], d->name, d->qid.path);
+	if(d->type != Tdentry || d->path != d->qid.path){
 		if(debug)
 			print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
-					blkno, tagnames[Tdentry], d->qid.path, tagnames[t->type], t->path);
+					blkno, tagnames[Tdentry], d->qid.path, tagnames[d->type], d->path);
 		fprint(2, "%llud\n", blkno);
 	}/*else
 		print("%llud\n", blkno);*/
 	addparent(depth, blkno);
+	if(d->size <= Ddatasize)
+		return;
 	for(i = 0; i<Ndblock; i++){
 		cblkno = d->dblocks[i];
 		if(cblkno == 0)
 			return;
 		cbuf = malloc(Rawblocksize);
-		devread(cblkno, cbuf);
+		devread(cblkno, cbuf, Rawblockunits);
 		ct = (Content*)cbuf;
-		if(isdir)
-			walkdentry(cblkno, depth+1);
-		else
-			checkvalid(cblkno, ct, Tdata, d->qid.path);
+		checkvalid(cblkno, ct, Tdata, d->qid.path);
 		free(cbuf);
 	}
 	cbuf = malloc(Rawblocksize);
@@ -207,10 +259,10 @@
 		cblkno = d->iblocks[i];
 		if(cblkno == 0)
 			return;
-		devread(cblkno, cbuf);
+		devread(cblkno, cbuf, Rawblockunits);
 		ct = (Content*)cbuf;
 		if(ct->type == Tind0+i){
-			walkindir(cblkno, Tind0+i, isdir ? Tdentry : Tdata, d->qid.path, depth);
+			walkindir(cblkno, Tind0+i, Tdata, d->qid.path, depth);
 		}else{
 			fprint(2, "invalid indir tag %llud\n", cblkno);
 			fprint(2, "%llud\n", cblkno);
--- a/fns.h
+++ b/fns.h
@@ -8,10 +8,9 @@
 
 /* actual device i/o routines */
 u64	devinit(char *devfile);
-int	devread(u64 blkno, void *b);
+s32	devread(u64 blkno, void *b, u16 len);
 u64	devsize(void);
-int	devwrite(u64 blkno, void *b);
-int	devwrites(u64 blkno, void *b, u64 n);
+s32	devwrite(u64 blkno, void *b, u16 len);
 
 /* show blocks */
 void	showblock(int fd, u8 *buf);
@@ -22,6 +21,7 @@
 void	showdata(int fd, u8 *buf);
 void	showind0(int fd, u8 *buf);
 void	showind(int fd, u8 *buf);
+u16		blklen(u16 tag);
 
 void	panic(char*, ...);
 int	fprint(int, char*, ...);
--- a/free.c
+++ b/free.c
@@ -13,7 +13,7 @@
 int chatty9p = 0;
 char *devfile = nil;
 void walkdentry(u64 blkno);
-int checkblock(u64 blkno, s16 tag, u64 qpath);
+int checkdentry(u64 blkno, s16 tag, u64 qpath);
 void getfrees(u64 dblkno);
 
 static void
@@ -47,9 +47,9 @@
 	if(size == 0)
 		panic("null size %s", devfile);
 	if(chatty9p)
-		print("%s %llud bytes %llud blocks\n", devfile, size, size/Rawblocksize);
+		print("%s %llud bytes %llud blocks\n", devfile, size, size/Unit);
 
-	checkblock(Bdfrees, Tdentry, Qpfrees);
+	checkdentry(Bdfrees, Tdentry, Qpfrees);
 	initextents(&frees);
 	getfrees(Bdfrees);
 	showextents(1, "", &frees);
@@ -59,7 +59,7 @@
 }
 
 int
-checkvalid(u64 blkno, Content *t, s16 tag, u64 qpath)
+checkvalid(u64 blkno, Tag *t, s16 tag, u64 qpath)
 {
 	if(t->type != tag || t->path != qpath){
 		/* if(chatty9p) */
@@ -74,13 +74,13 @@
 }
 
 int
-checkblock(u64 blkno, s16 tag, u64 qpath)
+checkdentry(u64 blkno, s16 tag, u64 qpath)
 {
-	u8 buf[Rawblocksize];
-	Content *t;
+	u8 buf[Dentrysize];
+	Dentry *t;
 
-	devread(blkno, buf);
-	t = (Content*)buf;
+	devread(blkno, buf, Dentryunits);
+	t = (Dentry*)buf;
 	return checkvalid(blkno, t, tag, qpath);
 }
 
@@ -90,7 +90,7 @@
 	s8 *buf;
 
 	buf = emalloc(Rawblocksize);
-	devread(blkno, buf);
+	devread(blkno, buf, Rawblockunits);
 	loadextents(&frees, buf, (Rawblocksize)-sizeof(Tag));
 	free(buf);
 }
@@ -98,12 +98,12 @@
 void
 walkindir(u64 blkno, u16 tag, u16 bottomtag, u64 qpath)
 {
-	u8 buf[Rawblocksize], cbuf[Rawblocksize];
+	u8 buf[Rawblocksize];
 	Content *t;
 	u64 cblkno, *bufa;
 	int i;
 
-	devread(blkno, buf);
+	devread(blkno, buf, Rawblockunits);
 	t = (Content*)buf;
 	if(checkvalid(blkno, t, tag, qpath)){
 		if(t->type == Tind0){
@@ -120,7 +120,6 @@
 				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				devread(cblkno, cbuf);
 				/* check tag */
 				walkindir(cblkno, tag-1,  bottomtag, qpath);
 			}
@@ -132,20 +131,22 @@
 getfrees(u64 dblkno)
 {
 	u64 size;
-	u8 buf[Rawblocksize], cbuf[Rawblocksize];
+	u8 buf[Dentrysize];
 	Dentry *d;
-	Content *t;
 	u64 cblkno;
 	int i;
 
-	devread(dblkno, buf);
-	t = (Content*)buf;
+	devread(dblkno, buf, Dentryunits);
 	d = (Dentry*)buf;
 	size = d->size;
 	if(size == 0)
 		panic("loadfreeextents size == 0");
 
-	if(checkvalid(dblkno, t, Tdentry, d->qid.path)){
+	if(d->size <= Ddatasize){
+		loadextents(&frees, d->buf, d->size);
+		return;
+	}
+	if(checkvalid(dblkno, d, Tdentry, Qpfrees)){
 		for(i = 0; i<Ndblock; i++){
 			cblkno = d->dblocks[i];
 			if(cblkno == 0)
@@ -156,7 +157,6 @@
 			cblkno = d->iblocks[i];
 			if(cblkno == 0)
 				return;
-			devread(cblkno, cbuf);
 			walkindir(cblkno, i, Tdata, Qpfrees);
 		}
 	}
--- a/iobuf.c
+++ b/iobuf.c
@@ -6,7 +6,7 @@
 extern u8 synchronouswrites;
 
 /*
-	extents of Rawblocksize units of memory used to store
+	extents of Unit units of memory used to store
 	the disk block contents in memory for the buffer cache
 	and write queue
  */
@@ -18,36 +18,36 @@
 void
 initmemunitpool(u64 nunits)
 {
-	memunitstart = sbrk((nunits+1) * Rawblocksize);
-	memunitpool = memunitstart+Rawblocksize- ((u64)memunitstart%Rawblocksize);
+	memunitstart = sbrk((nunits+1) * Unit);
+	memunitpool = memunitstart+Unit- ((u64)memunitstart%Unit);
 	initextents(&memunits);
 	if(chatty9p > 4)
-		dprint("initmemunitpool: memunitpool %p nunits*Rawblocksize %p\n",
-				memunitpool, nunits*Rawblocksize);
+		dprint("initmemunitpool: memunitpool %p nunits*Unit %p\n",
+				memunitpool, nunits*Unit);
 	bfree(&memunits, 0, nunits);
 }
 
 u8 *
-allocmemunit(void)
+allocmemunits(u16 len)
 {
 	u64 m;
 
-	m = balloc(&memunits, 1);
+	m = balloc(&memunits, len);
 	if(chatty9p > 4)
 		dprint("allocmemunit: memunitpool %p m %p\n",
 				memunitpool, m);
-	return memunitpool+(m*Rawblocksize);
+	return memunitpool+(m*Unit);
 }
 
 void
-freememunit(u8 *m)
+freememunits(u8 *m, u16 len)
 {
 	if(m == 0)
 		panic("freememunit: m == 0\n");
-	if((m-memunitpool)%Rawblocksize)
-		panic("freememunit: (m-memunitpool)%%Rawblocksize %llud\n",
-				(u64)(m-memunitpool)%Rawblocksize);
-	bfree(&memunits, (m-memunitpool)/Rawblocksize, 1);
+	if((m-memunitpool)%Unit)
+		panic("freememunit: (m-memunitpool)%%Unit %llud\n",
+				(u64)(m-memunitpool)%Unit);
+	bfree(&memunits, (m-memunitpool)/Unit, len);
 }
 
 /*
@@ -55,7 +55,7 @@
    hp must be locked
  */
 Iobuf *
-newbuf(Hiob *hp)
+newbuf(Hiob *hp, u16 len)
 {
 	Iobuf *p, *q;
 
@@ -73,7 +73,8 @@
 		p->back = p;
 	}
 	p->blkno = 0;
-	p->xiobuf = allocmemunit();
+	p->len   = len;
+	p->xiobuf = allocmemunits(len);
 	return p;
 }
 
@@ -94,7 +95,7 @@
 	Hiob.link->back is the oldest buffer that will be reused first.
  */
 Iobuf *
-getbuf(u64 blkno, u8 readonly, u8 freshalloc)
+getbuf(u64 blkno, u16 len, u8 readonly, u8 freshalloc)
 {
 	Hiob *hp;
 	Iobuf *s, *p;
@@ -131,10 +132,33 @@
 			if(chatty9p > 4)
 				dprint("	in cache, after qunlock(hp) hp 0x%p blkno %llud\n",
 						hp, blkno);
-			if(readonly){
+			if(p->len != len){
 				if(chatty9p > 4)
-					dprint("	in cache iobuf 0x%p has blkno %llud .."
-							" rlock()\n", p, blkno);
+				dprint("getbuf refresh used blkno %llud, size in memory is %d"
+						" and not %d, caller %#p\n",
+						blkno, p->len, len, getcallerpc(&blkno));
+				if(p->len == 0 || len == 0)
+					panic("getbuf: p->len == 0 || len == 0 p->len %d len %d",
+							p->len, len);
+				wlock(p);
+				if(chatty9p > 4)
+					dprint("	after wlock() blkno %llud\n", blkno);
+				freememunits(p->xiobuf, p->len);
+				p->xiobuf = allocmemunits(len);
+				p->len = len;
+				if(freshalloc == 0)
+					devread(blkno, p->xiobuf, len);
+				if(readonly){
+					if(chkwunlock(p) == 0){
+						showbuf(p);
+						panic("getbuf chkwunlock(p) == 0 called by %#p\n", getcallerpc(&blkno));
+					}
+					rlock(p);
+				}
+			}else if(readonly){
+				if(chatty9p > 4)
+					dprint("	in cache iobuf 0x%p has len %llud blkno %llud len %llud .."
+							" rlock()\n", p, p->len, blkno, len);
 				rlock(p);
 			}else{
 				wlock(p);
@@ -173,10 +197,15 @@
 					wunlock(p);
 					goto Another;
 				}
+				if(p->len != len){
+					freememunits(p->xiobuf, p->len);
+					p->xiobuf = allocmemunits(len);
+					p->len = len;
+				}
 				hp->link = p;
 				if(chatty9p > 4)
-					dprint("	stealing iobuf 0x%p for blkno %llud\n",
-							p, blkno);
+					dprint("	stealing iobuf 0x%p for blkno %llud len %llud\n",
+							p, p->len, blkno);
 				goto found;	/* p is wlock() */
 			}
 			s = p;
@@ -187,7 +216,7 @@
 new:
 	if(chatty9p > 4)
 		dprint("	adding new Iobuf for blkno %llud\n", blkno);
-	p = newbuf(hp);
+	p = newbuf(hp, len);
 	if(chatty9p > 4)
 		dprint(" .. wlock() blkno %llud\n", blkno);
 	wlock(p);
@@ -199,7 +228,7 @@
 		dprint("	after qunlock(hp) hp 0x%p blkno %llud\n",
 				hp, blkno);
 	if(freshalloc == 0)
-		devread(blkno, p->xiobuf);
+		devread(blkno, p->xiobuf, len);
 	if(readonly){
 		if(chatty9p > 4)
 		dprint("new buffer: switching from wlock() to rlock() blkno %llud\n", blkno);
@@ -215,10 +244,15 @@
 getbufchk(u64 blkno, u8 readonly, int tag, u64 qpath)
 {
 	Iobuf *b;
+	u16 len;
 
 	if(chatty9p > 4)
 		dprint("getbufchk caller pc 0x%p\n", getcallerpc(&blkno));
-	b = getbuf(blkno, readonly, Bused);
+	if(tag == Tdentry)
+		len = Dentryunits;
+	else
+		len = Rawblockunits;
+	b = getbuf(blkno, len, readonly, Bused);
 	if(b != nil)
 		if(checktag(b, tag, qpath) == 0){
 			putbuf(b);
@@ -256,14 +290,14 @@
 		return;
 	}
 
-	buf = getbufchk(bno, Bwritable, Tdata, qpath);
+	buf = getbufchk(bno, Bwritable, Tdentry, qpath);
 	if(buf == nil){
 		panic("bkp: buf == nil\n");
 	}
-	memcpy(buf->io->buf, contents, Blocksize);
-	if(qpath == Qproot0 || qpath == Qproot1){
-		buf->io->d.mode &= ~DMDIR; /* to avoid recursive du -a */
-	}
+	memcpy(buf->d->buf, ((Dentry*)contents)->buf, ((Dentry*)contents)->size);
+//	if(qpath == Qproot0 || qpath == Qproot1){
+//		buf->d->mode &= ~DMDIR; /* to avoid recursive du -a */
+//	}
 	putbuf(buf);
 }
 
@@ -304,13 +338,12 @@
 			memcpy(buf, p->io->buf, Blocksize);
 		}
 		if(synchronouswrites){
-			if(devwrite(p->blkno, p->xiobuf) != Rawblocksize)
-				panic("putbuf: could not write block\n");
+			devwrite(p->blkno, p->xiobuf, p->len);
 			if(chkwunlock(p) == 0){
 				showbuf(p);
 				panic("putbuf: chkwunlock(p) == 0 called by %#p\n", getcallerpc(&p));
 			}
-		} else
+		}else
 			putwrite(p);
 		if(srcbno == config.config.srcbno){
 			for(i=0; i<Nbkp; i++)
@@ -325,28 +358,6 @@
 	}
 }
 
-void
-putbufs(Iobuf **ps, u64 len)
-{
-	u64 wn, i;
-	u8 *jumbo;
-
-	if(synchronouswrites){
-		jumbo = emalloc9p(len*Rawblocksize);
-		for(i = 0; i < len; i++)
-			memcpy(jumbo+(i*Rawblocksize), ps[i]->xiobuf, Rawblocksize);
-		if((wn = devwrites(ps[0]->blkno, jumbo, len)) != len*Rawblocksize){
-			dprint("%s\n", errstring[Esystem]);
-			panic("error writing jumbo block %llud: %llud bytes, written %llud: %r\n",
-					ps[0]->blkno, len, wn);
-		}
-		free(jumbo);
-		for(i = 0; i < len; i++)
-			wunlock(ps[i]);
-	}else
-		putwrites(ps, len);
-}
-
 /* only caller is freeblockbuf().
 	These blocks do not need to be written to the disk.
 	Hence, avoiding putwrite().
@@ -388,25 +399,42 @@
 checktag(Iobuf *p, u16 tag, u64 qpath)
 {
 	uintptr pc;
+	u16 len;
+	u16 plen;
+	u16 ptag;
+	u64 pqpath;
 
-	if(tag != p->io->type || (qpath != Qpnone && qpath != p->io->path)){
+	if(tag == Tdentry){
+		ptag = p->d->type;
+		pqpath = p->d->path;
+		plen = p->d->len;
+	}else{
+		ptag = p->io->type;
+		pqpath = p->io->path;
+		plen = p->io->len;
+	}
+
+	len = blklen(tag);
+	if(len != plen ||
+		tag != ptag ||
+		(qpath != Qpnone && qpath != pqpath)){
 		pc = getcallerpc(&p);
 
 		dprint("	tag = %G; expected %G; blkno = %llud\n",
-				(uint)p->io->type, (uint)tag, p->blkno);
+				(uint)ptag, (uint)tag, p->blkno);
 		if(qpath == Qpnone){
 			dprint("checktag pc=%p disk %s(block %llud) tag/path=%s/%llud;"
 					" expected %s\n",
 					pc, devfile, (u64)p->blkno,
-					tagnames[p->io->type], (u64)p->io->path,
+					tagnames[ptag], (u64)pqpath,
 					tagnames[tag]);
 		} else {
 				dprint("	tag/path = %G/%llux; expected %G/%llux\n",
-						(uint)p->io->type, p->io->path, tag, qpath);
+						(uint)ptag, pqpath, tag, qpath);
 				dprint("checktag pc=%p disk %s(block %llud) tag/path=%s/%llud;"
 						" expected %s/%llud\n",
 						pc, devfile, (u64)p->blkno,
-						tagnames[p->io->type], (u64)p->io->path,
+						tagnames[ptag], (u64)pqpath,
 						tagnames[tag], (u64)qpath);
 		}
 		return 0;
@@ -423,8 +451,15 @@
 	if(p->io == nil)
 		panic("settag %s(%llux) tag/path=%s/%llud: p->io == nil\n",
 				devfile, (u64)p->blkno, tagnames[tagtype], qpath);
-	p->io->type = tagtype;
-	p->io->path = qpath;
+	if(tagtype == Tdentry){
+		p->d->type = Tdentry;
+		p->d->path = qpath;
+		p->d->len = Dentryunits;
+	}else{
+		p->io->type = tagtype;
+		p->io->path = qpath;
+		p->io->len = Rawblockunits;
+	}
 }
 
 void *amalloc(u64 n){
@@ -474,12 +509,12 @@
 		return;
 	}
 	dprint("showbuf p 0x%p ref %d readers %d writer %d"
-			" blkno %llud"
+			" blkno %llud len %llud"
 			" fore 0x%p back 0x%p"
 			" xiobuf 0x%p"
 			" caller %#p\n",
 			p, p->ref, p->readers, p->writer,
-			p->blkno,
+			p->blkno, p->len,
 			p->fore, p->back,
 			p->xiobuf,
 			getcallerpc(&p));
--- a/mafs.c
+++ b/mafs.c
@@ -82,22 +82,19 @@
 
 	/* 2/3rds of the memory for the pending writes
 		and 1/3rd for the buffer cache
-		leaving 4*Ntogether for jumbo writes when the writer
-		queue is full
 	 */
 	if(nmemunits == 0)
-		nmemunits = size/Rawblocksize > 8*MiB ? 8*MiB : size/Rawblocksize;
+		nmemunits = size/Unit > 8*MiB ? 8*MiB : size/Unit;
 	if(nmemunits < KiB)
 		nmemunits = KiB;
 	if(npendingwrites == 0)
-		npendingwrites = 2*(nmemunits-(4*Ntogether))/3;
+		npendingwrites = (2*nmemunits)/3;
 	if(nbuckets == 0)
-		nbuckets = (nmemunits-(4*Ntogether))/(3*Ncollisions);
+		nbuckets = nmemunits/(3*Ncollisions);
 
 	if(chatty9p){
 		dprint("\nPlan 9 %d-bit file server with %d-deep indirect blocks\n",
 			sizeof(u64)*8, Niblock);
-		printsizes();
 		dprint("nmemunits %llud npendingwrites %llud nbuckets %llud\n",
 				nmemunits, npendingwrites, nbuckets);
 	}
@@ -145,27 +142,3 @@
 	return max;
 }
 
-/* also in tests/sizes.c */
-static void
-printsizes(void)
-{
-	int i;
-	u64 n, max;
-
-	dprint("Namelen %d Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
-	dprint("Blocksize %d Nindperblock %d\n",
-			Blocksize, Nindperblock);
-
-	for (i = Tind0; i < Maxtind; i++) {
-		n = nperindunit(i);
-		dprint("A %s unit points to %lld data spans (%llud bytes)\n",
-			 tagnames[i], n, n*Blocksize);
-		dprint("	block points to %lld data spans\n", nperiblock(i));
-	}
-	dprint("sizeof(Dentry1) %d Namelen %d\n",
-			sizeof(Dentry1), Namelen);
-	max = maxsize();
-	dprint("maximum possible spans %llud\n", max);
-	dprint("	(%llud*Rawblocksize = %llud bytes = %llud TiB)\n",
-			max, max*Rawblocksize, (max*Rawblocksize)/(MiB*MiB));
-}
--- a/mfs.c
+++ b/mfs.c
@@ -81,7 +81,7 @@
 
 	/* All memory for the buffer cache */
 	if(nmemunits == 0)
-		nmemunits = size/Rawblocksize > 8*MiB ? 8*MiB : size/Rawblocksize;
+		nmemunits = size/Unit > 8*MiB ? 8*MiB : size/Unit;
 	if(nmemunits < KiB)
 		nmemunits = KiB;
 	if(nbuckets == 0)
@@ -90,7 +90,6 @@
 	if(chatty9p){
 		dprint("\nPlan 9 %d-bit file server with %d-deep indirect blocks\n",
 			sizeof(u64)*8, Niblock);
-		printsizes();
 		dprint("nmemunits %llud nbuckets %llud\n",
 				nmemunits, nbuckets);
 	}
@@ -135,29 +134,4 @@
 		dprint("maxsize %s %llud max %llud\n", tagnames[Tind0+i], ind, max);
 	}
 	return max;
-}
-
-/* also in tests/sizes.c */
-static void
-printsizes(void)
-{
-	int i;
-	u64 n, max;
-
-	dprint("Namelen %d Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
-	dprint("Blocksize %d Nindperblock %d\n",
-			Blocksize, Nindperblock);
-
-	for (i = Tind0; i < Maxtind; i++) {
-		n = nperindunit(i);
-		dprint("A %s unit points to %lld data spans (%llud bytes)\n",
-			 tagnames[i], n, n*Blocksize);
-		dprint("	block points to %lld data spans\n", nperiblock(i));
-	}
-	dprint("sizeof(Dentry1) %d Namelen %d\n",
-			sizeof(Dentry1), Namelen);
-	max = maxsize();
-	dprint("maximum possible spans %llud\n", max);
-	dprint("	(%llud*Rawblocksize = %llud bytes = %llud TiB)\n",
-			max, max*Rawblocksize, (max*Rawblocksize)/(MiB*MiB));
 }
--- a/mkfile
+++ b/mkfile
@@ -32,7 +32,6 @@
 	${OFILES:%.$O=%.c}\
 
 </sys/src/cmd/mkmany
-
 # LDFLAGS=-p
 
 $O.updatefrees:	blk.$O dat.$O dev.$O misc.$O updatefrees.$O
--- a/sub.c
+++ b/sub.c
@@ -7,14 +7,20 @@
 {
 	u64 qpath;
 	Iobuf *sb;
-	Superb *s;
+	Super *s;
+	s32 on, nn;
+	s8 buf[Ddatasize-16];
 
-	sb = getbufchk(Bsuper, Bwritable, Tdata, Qpsuper);
+	sb = getbufchk(Bdsuper, Bwritable, Tdentry, Qpsuper);
 	if(sb == nil){
 		panic("newqpath: sb == nil\n");
 	}
-	s = (Superb*)sb->io->buf;
+	s = (Super*)sb->io->buf;
+	on = snprint(buf, Ddatasize-16, "%llud", s->qidgen);
 	qpath = s->qidgen++;
+	nn = snprint(buf, Ddatasize-16, "%llud", s->qidgen);
+	if(on != nn)
+		s->size += nn-on;
 	putbuf(sb);
 	return qpath;
 }
@@ -72,8 +78,10 @@
 {
 	u64 blkno;
 	Iobuf *buf;
+	u16 len;
 
-	blkno = balloc(&frees, 1);
+	len = blklen(tag);
+	blkno = balloc(&frees, len);
 	if(blkno == 0)
 		return nil;	/* the caller should trigger an Efull message */
 
@@ -80,37 +88,13 @@
 	if(chatty9p > 1)
 		dprint("alloc %llud\n", blkno);
 	/* cannot do getbufchk() unless we ream the whole disk at start */
-	buf = getbuf(blkno, Bwritable, Bfreshalloc);
+	buf = getbuf(blkno, len, Bwritable, Bfreshalloc);
 	/* clear the buf to avoid leaks on reuse */
-	memset(buf->xiobuf, 0, Rawblocksize);
+	memset(buf->xiobuf, 0, len*Unit);
 	settag(buf, tag, qpath);
 	return buf;
 }
 
-u64
-allocblocks(int tag, u64 qpath, u64 len, Iobuf **bufs)
-{
-	u64 blkno, i;
-	Iobuf *buf;
-
-	blkno = balloc(&frees, len);
-	if(blkno == 0)
-		return 0;	/* the caller should trigger an Efull message */
-
-	if(chatty9p > 1)
-		dprint("alloc %llud\n", blkno);
-
-	for(i = 0; i < len; i++){
-		/* cannot do getbufchk() unless we ream the whole disk at start */
-		bufs[i] = buf = getbuf(blkno+i, Bwritable, Bfreshalloc);
-		/* clear the buf to avoid leaks on reuse */
-		memset(buf->xiobuf, 0, Rawblocksize);
-		settag(buf, tag, qpath);
-	}
-
-	return len;
-}
-
 /* the buf should have been wlock()'ed */
 void
 freeblockbuf(Iobuf *buf)
@@ -119,8 +103,8 @@
 		panic("freeblockbuf without Bwritable");
 
 	/* clear the buf to avoid leaks on reuse */
-	memset(buf->xiobuf, 0, Rawblocksize);
-	bfree(&frees, buf->blkno, 1);
+	memset(buf->xiobuf, 0, buf->len*Unit);
+	bfree(&frees, buf->blkno, buf->len);
 	putbuffree(buf);
 }
 
@@ -135,6 +119,7 @@
 				 blkno, config.nblocks);
 		return;
 	}
+
 	buf = getbufchk(blkno, Bwritable, tag, qpath);
 	if(buf == nil)
 		dprint("%s",errstring[Ephase]);
@@ -164,13 +149,13 @@
 fsok(int ok)
 {
 	Iobuf *sb;
-	Superb *s;
+	Super *s;
 
-	sb = getbufchk(Bsuper, Bwritable, Tdata, Qpsuper);
+	sb = getbufchk(Bdsuper, Bwritable, Tdentry, Qpsuper);
 	if(sb == nil){
-		panic("newqpath: sb == nil\n");
+		panic("fsok: sb == nil\n");
 	}
-	s = (Superb*)sb->io->buf;
+	s = (Super*)sb->d;
 	s->fsok = ok;
 	if(chatty9p > 1){
 		dprint("fsok ok %d\n", ok);
@@ -187,26 +172,15 @@
 }
 
 void
-reamdata(u64 bno, u64 qpath)
-{
-	Iobuf *b;
-
-	b = getbuf(bno, Bwritable, Bfreshalloc);
-	memset(b->io, 0, Rawblocksize);
-	settag(b, Tdata, qpath);
-	putbuf(b);
-}
-
-void
 reamfile(u64 dblkno, u64 qpath, char *name, u64 size, u64 pdblkno, u64 pqpath, u64 contentblkno)
 {
 	Iobuf *b;
 	Dentry *d;
 
-	b = getbuf(dblkno, Bwritable, Bfreshalloc);
-	memset(b->io, 0, Rawblocksize);
+	b = getbuf(dblkno, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->io, 0, Dentrysize);
 	settag(b, Tdentry, qpath);
-	d = &b->io->d;
+	d = b->d;
 	strcpy(d->name, name);
 	d->uid = d->muid = d->gid = -1;
 	d->mode =
@@ -225,20 +199,21 @@
 }
 
 /*
-	TODO
-	The reamer is added to the sys group.
-	The ctl file is owned by the ream'er and the sys group.
+	The reamer is added to the adm group.
+	The ctl file is owned by the ream'er and the adm group.
  */
+char magic[] = "m[a]fs device\n";
 void
-reamdefaults(void)
+reamdefaults(u64 bdconfig0, u64 bdsuper0, u64 bdroot0, u64 bdconfig1, u64 bdsuper1, u64 bdroot1)
 {
 	Iobuf *b;
 	Dentry *d;
 	char users[128+Userlen*3];
 	char *user;
+	int userslen, n;
 
 	user = getuser();
-	snprint(users, 128+Userlen*3, "-1:adm:adm:%s\n"
+	userslen = snprint(users, 128+Userlen*3, "-1:adm:adm:%s\n"
 					"0:none:adm:\n"		/* user ID for "none" */
 					"9999:noworld::\n"	/* conventional id for "noworld" group */
 					"10000:sys::\n"
@@ -245,10 +220,31 @@
 					"10001:upas:upas:\n"	/* what is this for? */
 					"10006:%s:%s:\n", user, user, user);
 
-	b = getbuf(Bdadm, Bwritable, Bfreshalloc);
-	memset(b->io, 0, Rawblocksize);
+	/* cannot show this in /adm though as the block number is 0 */
+	b = getbuf(Bdmagic, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->d, 0, Dentrysize);
+	settag(b, Tdentry, Qpmagic);
+	d = b->d;
+	strncpy(d->name, "magic", 6);
+	d->uid = d->muid = d->gid = -1;
+	d->mode = DMDIR |
+		((DMREAD|DMWRITE|DMEXEC) << 6) |
+		((DMREAD|DMWRITE|DMEXEC) << 3) |
+		((DMREAD|DMWRITE|DMEXEC) << 0);
+	d->qid.path = Qpmagic;
+	d->qid.version = 0;
+	d->mtime = nsec();
+	d->pdblkno = Bdadm;
+	d->pqpath = Qpadm;
+	n = snprint((s8*)d->buf, Ddatasize, "%s%llud\n",
+			magic, Unit);
+	d->size = n;
+	putbuf(b);
+
+	b = getbuf(Bdadm, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->d, 0, Dentrysize);
 	settag(b, Tdentry, Qpadm);
-	d = &b->io->d;
+	d = b->d;
 	strncpy(d->name, "adm", 4);
 	d->uid = d->muid = d->gid = -1;
 	d->mode = DMDIR |
@@ -268,10 +264,10 @@
 	d->dblocks[5] = Bdctl;
 	putbuf(b);
 
-	b = getbuf(Bdbkp, Bwritable, Bfreshalloc);
-	memset(b->io, 0, Rawblocksize);
+	b = getbuf(Bdbkp, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->d, 0, Dentrysize);
 	settag(b, Tdentry, Qpbkp);
-	d = &b->io->d;
+	d = b->d;
 	strncpy(d->name, "bkp", 4);
 	d->uid = d->muid = d->gid = -1;
 	d->mode = DMDIR |
@@ -284,18 +280,18 @@
 	d->size = strlen(users)+1;
 	d->pdblkno = Bdadm;
 	d->pqpath = Qpadm;
-	d->dblocks[0] = Bdconfig0;
-	d->dblocks[1] = Bdsuper0;
-	d->dblocks[2] = Bdroot0;
-	d->dblocks[3] = Bdconfig1;
-	d->dblocks[4] = Bdsuper1;
-	d->dblocks[5] = Bdroot1;
+	d->dblocks[0] = bdconfig0;
+	d->dblocks[1] = bdsuper0;
+	d->dblocks[2] = bdroot0;
+	d->dblocks[3] = bdconfig1;
+	d->dblocks[4] = bdsuper1;
+	d->dblocks[5] = bdroot1;
 	putbuf(b);
 
-	b = getbuf(Bdusers, Bwritable, Bfreshalloc);
-	memset(b->io, 0, Rawblocksize);
+	b = getbuf(Bdusers, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->d, 0, Dentrysize);
 	settag(b, Tdentry, Qpusers);
-	d = &b->io->d;
+	d = b->d;
 	strncpy(d->name, "users", 6);
 	d->uid = d->muid = d->gid = -1;
 	d->mode = DMDIR |
@@ -312,52 +308,29 @@
 	d->dblocks[1] = Bdusersstaging;
 	putbuf(b);
 
-	reamfile(Bdconfig, Qpconfig, "config", 0, Bdadm, Qpadm, Bconfig);
-	reamfile(Bdctl, Qpctl, "ctl", 0, Bdadm, Qpadm, 0);
-	reamfile(Bdsuper, Qpsuper, "super", 0, Bdadm, Qpadm, Bsuper);
-	reamfile(Bdfrees, Qpfrees, "frees", 0, Bdadm, Qpadm, 0);
-
-	reamfile(Bdconfig0, Qpconfig0, "config.0",
-			 Blocksize, Bdbkp, Qpbkp, config.config.dest[0]);
-	reamfile(Bdsuper0, Qpsuper0, "super.0",
-			 Blocksize, Bdbkp, Qpbkp, config.super.dest[0]);
-	reamfile(Bdroot0, Qproot0, "root.0",
-			 Blocksize, Bdbkp, Qpbkp, config.root.dest[0]);
-
-	reamfile(Bdconfig1, Qpconfig1, "config.1",
-			 Blocksize, Bdbkp, Qpbkp, config.config.dest[1]);
-	reamfile(Bdsuper1, Qpsuper1, "super.1",
-			 Blocksize, Bdbkp, Qpbkp, config.super.dest[1]);
-	reamfile(Bdroot1, Qproot1, "root.1",
-			 Blocksize, Bdbkp, Qpbkp, config.root.dest[1]);
-
-	reamfile(Bdusersinuse, Qpusersinuse, "inuse",
-			 Blocksize, Bdusers, Qpusers, Busersinuse);
-	reamfile(Bdusersstaging, Qpusersstaging, "staging",
-			 Blocksize, Bdusers, Qpusers, 0);
-
-	b = getbuf(Busersinuse, Bwritable, Bfreshalloc);
-	if(b == nil)
-		panic("cannot get Busers");
-	memset(b->io, 0, Rawblocksize);
-	settag(b, Tdata, Qpusersinuse);
-	strcpy((char*)b->io->buf, users);
+	b = getbuf(Bdusersinuse, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->d, 0, Dentrysize);
+	settag(b, Tdentry, Qpusersinuse);
+	d = b->d;
+	strncpy(d->name, "inuse", 6);
+	d->uid = d->muid = d->gid = -1;
+	d->mode =
+		((DMREAD) << 6) |
+		((DMREAD) << 3) |
+		((DMREAD) << 0);
+	d->qid.path = Qpusersinuse;
+	d->qid.version = 0;
+	d->mtime = nsec();
+	d->size = userslen;
+	d->pdblkno = Bdusers;
+	d->pqpath = Qpusers;
+	strcpy((s8*)d->buf, users);
 	putbuf(b);
-}
 
-void
-rootream(void)
-{
-	Iobuf *b;
-	Dentry *d;
-
-	b = getbuf(Bdroot, Bwritable, Bfreshalloc);
-	if(b == nil)
-		panic("rootream b == nil");
-	memset(b->io, 0, Rawblocksize);
+	b = getbuf(Bdroot, Dentryunits, Bwritable, Bfreshalloc);
+	memset(b->d, 0, Dentrysize);
 	settag(b, Tdentry, Qproot);
-
-	d = &b->io->d;
+	d = b->d;
 	strncpy(d->name, "/", 5);
 	d->uid = d->muid = -1;
 	d->gid = -1;
@@ -370,6 +343,13 @@
 	d->mtime = nsec();
 	d->dblocks[0] = Bdadm;
 	putbuf(b);
+
+	reamfile(Bdconfig, Qpconfig, "config", 0, Bdadm, Qpadm, 0);
+	reamfile(Bdctl, Qpctl, "ctl", 0, Bdadm, Qpadm, 0);
+	reamfile(Bdfrees, Qpfrees, "frees", 0, Bdadm, Qpadm, 0);
+
+	reamfile(Bdusersstaging, Qpusersstaging, "staging",
+			 0, Bdusers, Qpusers, 0);
 }
 
 void
@@ -376,16 +356,28 @@
 superream(u64 size, u64 nblocks)
 {
 	Iobuf *sbuf;
-	Superb *s;
-	u64 i, nbused;
+	Super *s;
+	u64 nbused;
 
 	nbused = Nbused;
-	sbuf = getbuf(Bsuper, Bwritable, Bfreshalloc);
+	sbuf = getbuf(Bdsuper, Dentryunits, Bwritable, Bfreshalloc);
 	if(sbuf == nil)
 		panic("superream: sbuf == nil");
-	memset(sbuf->io, 0, Rawblocksize);
-	settag(sbuf, Tdata, Qpsuper);
-	s = (Superb*)sbuf->io->buf;
+	memset(sbuf->d, 0, Dentrysize);
+	settag(sbuf, Tdentry, Qpsuper);
+	s = (Super*)sbuf->d;
+	strncpy(s->name, "super", 6);
+	s->uid = s->muid = s->gid = -1;
+	s->mode =
+		((DMREAD) << 6) |
+		((DMREAD) << 3) |
+		((DMREAD) << 0);
+	s->qid.path = Qpsuper;
+	s->qid.version = 0;
+	s->mtime = nsec();
+	s->size = 18;
+	s->pdblkno = Bdadm;
+	s->pqpath = Qpadm;
 	s->qidgen = Nqidgen;
 	s->fsok = 1;
 
@@ -393,17 +385,26 @@
 		they will be overwritten almost immediately anyway */
 	config.size = size;
 	config.nblocks = nblocks;
-	config.config.dest[0] = nblocks-Bconfig;
-	config.config.dest[1] = nbused+((nblocks-nbused)/2)-Bconfig;
-	config.super.dest[0] = nblocks-Bsuper;
-	config.super.dest[1] = nbused+((nblocks-nbused)/2)-Bsuper;
+	config.config.dest[0] = nblocks-Bdconfig;
+	config.config.dest[1] = nbused+((nblocks-nbused)/2)-Bdconfig;
+	config.super.dest[0] = nblocks-Bdsuper;
+	config.super.dest[1] = nbused+((nblocks-nbused)/2)-Bdsuper;
 	config.root.dest[0] = nblocks-3;
 	config.root.dest[1] = nbused+((nblocks-nbused)/2)-3;
-	for(i=0; i<Nbkp; i++){
-		reamdata(config.config.dest[i], Qpconfig0+3*i);
-		reamdata(config.super.dest[i], Qpsuper0+3*i);
-		reamdata(config.root.dest[i], Qproot0+3*i);
-	}
+
+	reamfile(config.config.dest[0], Qpconfig0, "config.0",
+			 0, Bdbkp, Qpbkp, config.config.dest[0]);
+	reamfile(config.super.dest[0], Qpsuper0, "super.0",
+			 0, Bdbkp, Qpbkp, config.super.dest[0]);
+	reamfile(config.root.dest[0], Qproot0, "root.0",
+			 0, Bdbkp, Qpbkp, config.root.dest[0]);
+
+	reamfile(config.config.dest[1], Qpconfig1, "config.1",
+			 0, Bdbkp, Qpbkp, config.config.dest[1]);
+	reamfile(config.super.dest[1], Qpsuper1, "super.1",
+			 0, Bdbkp, Qpbkp, config.super.dest[1]);
+	reamfile(config.root.dest[1], Qproot1, "root.1",
+			 0, Bdbkp, Qpbkp, config.root.dest[1]);
 	putbuf(sbuf);
 
 	if(chatty9p > 1)
@@ -414,9 +415,8 @@
 				config.super.dest[0], config.super.dest[1],
 				config.root.dest[0], config.root.dest[1]);
 
-	reamdata(Bconfig, Qpconfig);
-	reamdefaults();
-	rootream();
+	reamdefaults(config.config.dest[0], config.super.dest[0], config.root.dest[0],
+				 config.config.dest[1], config.super.dest[1], config.root.dest[1]);
 
 	bfree(&frees, config.config.dest[1]+1, config.root.dest[0]-config.config.dest[1]-1);
 	bfree(&frees, nbused, config.root.dest[1]-nbused);
@@ -426,8 +426,8 @@
 		dprint("done\n");
 
 	/* this will enable backups */
-	config.config.srcbno = Bconfig;
-	config.super.srcbno = Bsuper;
+	config.config.srcbno = Bdconfig;
+	config.super.srcbno = Bdsuper;
 	config.root.srcbno = Bdroot;
 	strncpy(config.service, service, Namelen);
 
@@ -434,42 +434,37 @@
 	fsok(0);
 }
 
-char magic[] = "m[a]fs device\n";
-/* TODO open the dev file OEXCL? */
+/*
+	open the dev file OEXCL?
+		cannot do exclusive use file as the fd could get invalid
+		if no I/O is done for an extended period.
+ */
 void
 ream(u64 size)
 {
-	char buf[Rawblocksize];
+	char buf[Unit];
 	int i;
 	u64 nblocks;
-	Iobuf *iob;
 
-	nblocks = size/Rawblocksize;
+	nblocks = size/Unit;
 	if(nblocks <= Nminblocks)
 		panic("not enough space");
 
 	if(chatty9p > 1){
-		dprint("%s %s ream %llud bytes into %llud blocks\n",
-				service, devfile, size, nblocks);
-		dprint("	(block size: raw %d bytes, usable %d bytes)\n",
+		dprint("%s %s ream %llud bytes into %llud units of %d bytes\n",
+				service, devfile, size, nblocks, Unit);
+		dprint("	(dentry size: raw %d bytes)\n", Dentrysize);
+		dprint("	(data block size: raw %d bytes, usable %d bytes)\n",
 				Rawblocksize, Blocksize);
 		dprint("	(name length: %d bytes)\n", Namelen);
 	}
 
-	memset(buf, 0, Rawblocksize);
+	memset(buf, 0, Unit);
 	for(i = 0; i < Nbused; i++)
-		devwrite(i, buf);
+		devwrite(i, buf, 1);
 
 	superream(size, nblocks);
-
-	iob = getbuf(Bmagicb, Bwritable, Bfreshalloc);
-	snprint((s8*)iob->io->buf+256, Rawblocksize-256, "%s%llud\n",
-			magic, Rawblocksize);
-	settag(iob, Tmagic, Qpmagic);
-	putbuf(iob);
-
-	writeconfig(Bconfig);
-
+	writeconfig(Bdconfig);
 	fsok(1);
 }
 
@@ -478,66 +473,46 @@
  * wipe some of the file systems, or all if ream is set
  * this code really assumes that only one file system exists
  */
-/* TODO open the file OEXCL? */
-u64
-readbkpblock(u64 dblkno, u64 qpath) /* obsolete, using Bconfig for this info */
-{
-	Iobuf *b;
-	Dentry *d;
-	u64 ret;
-
-	b = getbufchk(dblkno, Breadonly, Tdentry, qpath);
-	if(b == nil){
-		putbuf(b);
-		panic("%s",errstring[Ephase]);
-		return 0;
-	}
-	d = &b->io->d;
-	ret = d->dblocks[0];
-	putbuf(b);
-	return ret;
-}
-
 void
 init(int doream, u64 size)
 {
-	u32 rbufsize;
+	u32 unitsize;
 	Iobuf *sb, *b;
-	Superb *s;
+	Super *s;
 	s8 *rptr;
 
 	if(doream)
 		ream(size);
 	else{
-		initconfig(Bconfig);
+		initconfig(Bdconfig);
 		loadfrees(Bdfrees);
 	}
 
 	/* check magic */
-	b = getbufchk(Bmagicb, Breadonly, Tmagic, Qpmagic);
+	b = getbufchk(Bdmagic, Breadonly, Tdentry, Qpmagic);
 	if(b == nil){
 		panic("Invalid magic: %s",errstring[Ephase]);
 		return;
 	}
-	if(strncmp((s8*)b->io->buf+256,magic,strlen(magic)) != 0){
+	if(strncmp((s8*)b->d->buf,magic,strlen(magic)) != 0){
 		print("init: bad magic -%s-", (s8*)b->io+256);
 		panic("bad magic");
 	}
-	rbufsize = strtoul((s8*)b->io->buf+256+strlen(magic), &rptr, 10);
-	if(rbufsize != Rawblocksize){
-		print("init incorrect block size Rawblocksize %llud rbufsize %d\n",
-				Rawblocksize, rbufsize);
-		panic("bad Rawblocksize != rbufsize");
+	unitsize = strtoul((s8*)b->d->buf+strlen(magic), &rptr, 10);
+	if(unitsize != Unit){
+		print("init incorrect block size Unit %llud unitsize %d\n",
+				Unit, unitsize);
+		panic("bad Unit != unitsize");
 	}
 	putbuf(b);
 
 	/* check super */
-	sb = getbufchk(Bsuper, Breadonly, Tdata, Qpsuper);
+	sb = getbufchk(Bdsuper, Breadonly, Tdentry, Qpsuper);
 	if(sb == nil){
 		panic("Invalid super: %s",errstring[Ephase]);
 		return;
 	}
-	s = (Superb*)sb->io->buf;
+	s = (Super*)sb->io;
 	if(s->fsok != 1 || config.size != size)
 		panic(errstring[Edirty]);
 
--- a/tests/sizes.c
+++ b/tests/sizes.c
@@ -9,7 +9,13 @@
 	int t;
 	u64 n;
 
-	print("Namelen %llud Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
+	print("Unit %llud Dentrysize %llud Rawblocksize %llud\n",
+			Unit, Dentrysize, Rawblocksize);
+	print("Dentryhdr size %d Ddatasize %llud Tag size %d\n",
+			sizeof(Dentryhdr), Ddatasize, sizeof(Tag));
+	print("Dentryblocks size %d Namelen %d Tag size %d\n",
+			sizeof(Dentryblocks), Namelen, sizeof(Tag));
+	print("Namelen %d Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
 	print("Blocksize %llud Nindperblock %llud\n",
 			Blocksize, Nindperblock);
 
--- a/tests/test.0/blocks/0
+++ b/tests/test.0/blocks/0
@@ -1,3 +1,13 @@
-Tmagic 1
+name magic
+size 18
+pdblkno 3
+pqpath 3
+mtime 1668539885153438699
+qid.path 11
+qid.version 0
+mode 20000000777
+uid -1
+gid -1
+muid -1
 m[a]fs device
 512
--- a/tests/test.0/blocks/1
+++ b/tests/test.0/blocks/1
@@ -1,7 +1,17 @@
-Tdata 4
+name config
+size 110
+pdblkno 3
+pqpath 3
+mtime 1668539885153467273
+qid.path 1
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 size 16384
 nblocks 32
-backup config 1 to 31 25
-backup super 2 to 30 24
-backup root 19 to 29 23
+backup config 1 to 31 20
+backup super 2 to 30 19
+backup root 10 to 29 18
 service test.0
--- a/tests/test.0/blocks/10
+++ b/tests/test.0/blocks/10
@@ -1,16 +1,16 @@
-Tdentry 10
-qid.version 0
+name /
+size 0
+pdblkno 0
+pqpath 0
+mtime 1668539885153465148
 qid.path 10
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267709989672410
-mode 444
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 25
+	0 3
 	1 0
 	2 0
 	3 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name config.1
--- a/tests/test.0/blocks/11
+++ b/tests/test.0/blocks/11
@@ -1,52 +1,1 @@
-Tdentry 11
-qid.version 0
-qid.path 11
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267709989674670
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 24
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name super.1
+Tblank 0
--- a/tests/test.0/blocks/12
+++ b/tests/test.0/blocks/12
@@ -1,52 +1,1 @@
-Tdentry 12
-qid.version 0
-qid.path 12
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267709989676866
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 23
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.1
+Tblank 0
--- a/tests/test.0/blocks/13
+++ b/tests/test.0/blocks/13
@@ -1,52 +1,1 @@
-Tdentry 13
-qid.version 0
-qid.path 13
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668267709989650115
-mode 20000000777
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 14
-	1 18
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name users
+Tblank 0
--- a/tests/test.0/blocks/14
+++ b/tests/test.0/blocks/14
@@ -1,52 +1,1 @@
 Tdentry 14
-qid.version 0
-qid.path 14
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668267709989682862
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 15
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name inuse
--- a/tests/test.0/blocks/15
+++ b/tests/test.0/blocks/15
@@ -1,7 +1,1 @@
-Tdata 14
--1:adm:adm:glenda
-0:none:adm:
-9999:noworld::
-10000:sys::
-10001:upas:upas:
-10006:glenda:glenda:
+Tdentry 13
--- a/tests/test.0/blocks/16
+++ b/tests/test.0/blocks/16
@@ -1,52 +1,1 @@
-Tdentry 16
-qid.version 0
-qid.path 16
-size 17
-pdblkno 3
-pqpath 3
-mtime 1668267808446584890
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 20
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name frees
+Tdentry 12
--- a/tests/test.0/blocks/17
+++ b/tests/test.0/blocks/17
@@ -1,52 +1,1 @@
-Tdentry 17
-qid.version 0
-qid.path 17
-size 0
-pdblkno 3
-pqpath 3
-mtime 1668267709989655296
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name ctl
+Tblank 0
--- a/tests/test.0/blocks/18
+++ b/tests/test.0/blocks/18
@@ -1,16 +1,16 @@
-Tdentry 18
+name root.1
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668539885153398050
+qid.path 17
 qid.version 0
-qid.path 18
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668267709989687520
 mode 444
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 0
+	0 18
 	1 0
 	2 0
 	3 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name staging
--- a/tests/test.0/blocks/19
+++ b/tests/test.0/blocks/19
@@ -1,52 +1,13 @@
-Tdentry 19
-qid.version 0
-qid.path 19
+name super.1
 size 0
-pdblkno 0
-pqpath 0
-mtime 1668267709989691269
-mode 20000000777
+pdblkno 5
+pqpath 5
+mtime 1668539885153395797
+qid.path 16
+qid.version 0
+mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 3
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name /
+qidgen 64
+fsok 1
--- a/tests/test.0/blocks/2
+++ b/tests/test.0/blocks/2
@@ -1,6 +1,13 @@
-Tdata 5
-start 0
-tfree 0
+name super
+size 18
+pdblkno 3
+pqpath 3
+mtime 1668539885153362490
+qid.path 2
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 qidgen 64
-frees 0
 fsok 1
--- a/tests/test.0/blocks/20
+++ b/tests/test.0/blocks/20
@@ -1,3 +1,17 @@
-Tdata 16
-20 22 3
-26 28 3
+name config.1
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668539885153393655
+qid.path 15
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+size 16384
+nblocks 32
+backup config 1 to 31 20
+backup super 2 to 30 19
+backup root 10 to 29 18
+service test.0
--- a/tests/test.0/blocks/23
+++ b/tests/test.0/blocks/23
@@ -1,1 +1,1 @@
-Tdata 12
+Tblank 0
--- a/tests/test.0/blocks/24
+++ b/tests/test.0/blocks/24
@@ -1,6 +1,1 @@
-Tdata 11
-start 0
-tfree 0
-qidgen 64
-frees 0
-fsok 1
+Tblank 0
--- a/tests/test.0/blocks/25
+++ b/tests/test.0/blocks/25
@@ -1,7 +1,1 @@
-Tdata 10
-size 16384
-nblocks 32
-backup config 1 to 31 25
-backup super 2 to 30 24
-backup root 19 to 29 23
-service test.0
+Tblank 0
--- a/tests/test.0/blocks/29
+++ b/tests/test.0/blocks/29
@@ -1,1 +1,48 @@
-Tdata 9
+name root.0
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668539885153388202
+qid.path 14
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+direct blocks
+	0 29
+	1 0
+	2 0
+	3 0
+	4 0
+	5 0
+	6 0
+	7 0
+	8 0
+	9 0
+	10 0
+	11 0
+	12 0
+	13 0
+	14 0
+	15 0
+	16 0
+	17 0
+	18 0
+	19 0
+	20 0
+	21 0
+	22 0
+	23 0
+	24 0
+	25 0
+	26 0
+	27 0
+	28 0
+	29 0
+	30 0
+	31 0
+indirect blocks
+	0 0
+	1 0
+	2 0
--- a/tests/test.0/blocks/3
+++ b/tests/test.0/blocks/3
@@ -1,21 +1,21 @@
-Tdentry 3
-qid.version 0
-qid.path 3
+name adm
 size 0
-pdblkno 19
-pqpath 19
-mtime 1668267709989637868
+pdblkno 10
+pqpath 10
+mtime 1668539885153455702
+qid.path 3
+qid.version 0
 mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 4
-	1 5
-	2 6
-	3 13
-	4 16
-	5 17
+	0 1
+	1 2
+	2 5
+	3 4
+	4 7
+	5 8
 	6 0
 	7 0
 	8 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name adm
--- a/tests/test.0/blocks/30
+++ b/tests/test.0/blocks/30
@@ -1,6 +1,13 @@
-Tdata 8
-start 0
-tfree 0
+name super.0
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668539885153378887
+qid.path 13
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 qidgen 64
-frees 0
 fsok 1
--- a/tests/test.0/blocks/31
+++ b/tests/test.0/blocks/31
@@ -1,7 +1,17 @@
-Tdata 7
+name config.0
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668539885153366728
+qid.path 12
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 size 16384
 nblocks 32
-backup config 1 to 31 25
-backup super 2 to 30 24
-backup root 19 to 29 23
+backup config 1 to 31 20
+backup super 2 to 30 19
+backup root 10 to 29 18
 service test.0
--- a/tests/test.0/blocks/4
+++ b/tests/test.0/blocks/4
@@ -1,17 +1,17 @@
-Tdentry 4
-qid.version 0
-qid.path 4
-size 0
+name users
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668267709989653016
-mode 444
+mtime 1668539885153460519
+qid.path 4
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 1
-	1 0
+	0 6
+	1 9
 	2 0
 	3 0
 	4 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name config
--- a/tests/test.0/blocks/5
+++ b/tests/test.0/blocks/5
@@ -1,21 +1,21 @@
-Tdentry 5
-qid.version 0
-qid.path 5
-size 0
+name bkp
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668267709989657428
-mode 444
+mtime 1668539885153458041
+qid.path 5
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 2
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
+	0 31
+	1 30
+	2 29
+	3 20
+	4 19
+	5 18
 	6 0
 	7 0
 	8 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name super
--- a/tests/test.0/blocks/6
+++ b/tests/test.0/blocks/6
@@ -1,52 +1,17 @@
-Tdentry 6
-qid.version 0
+name inuse
+size 95
+pdblkno 4
+pqpath 4
+mtime 1668539885153462861
 qid.path 6
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668267709989643837
-mode 20000000777
+qid.version 0
+mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 7
-	1 8
-	2 9
-	3 10
-	4 11
-	5 12
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name bkp
+-1:adm:adm:glenda
+0:none:adm:
+9999:noworld::
+10000:sys::
+10001:upas:upas:
+10006:glenda:glenda:
--- a/tests/test.0/blocks/7
+++ b/tests/test.0/blocks/7
@@ -1,52 +1,13 @@
-Tdentry 7
-qid.version 0
+name frees
+size 17
+pdblkno 3
+pqpath 3
+mtime 1668539887275618276
 qid.path 7
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267709989663903
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 31
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name config.0
+11 17 7
+21 28 8
--- a/tests/test.0/blocks/8
+++ b/tests/test.0/blocks/8
@@ -1,52 +1,11 @@
-Tdentry 8
-qid.version 0
+name ctl
+size 0
+pdblkno 3
+pqpath 3
+mtime 1668539885153472052
 qid.path 8
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267709989666061
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 30
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name super.0
--- a/tests/test.0/blocks/9
+++ b/tests/test.0/blocks/9
@@ -1,52 +1,11 @@
-Tdentry 9
-qid.version 0
+name staging
+size 0
+pdblkno 4
+pqpath 4
+mtime 1668539885153483592
 qid.path 9
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267709989668118
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 29
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.0
--- a/tests/test.1/blocks/0
+++ b/tests/test.1/blocks/0
@@ -1,3 +1,13 @@
-Tmagic 1
+name magic
+size 18
+pdblkno 3
+pqpath 3
+mtime 1668540127356872451
+qid.path 11
+qid.version 0
+mode 20000000777
+uid -1
+gid -1
+muid -1
 m[a]fs device
 512
--- a/tests/test.1/blocks/1
+++ b/tests/test.1/blocks/1
@@ -1,7 +1,17 @@
-Tdata 4
+name config
+size 110
+pdblkno 3
+pqpath 3
+mtime 1668540127356901604
+qid.path 1
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 size 16384
 nblocks 32
-backup config 1 to 31 25
-backup super 2 to 30 24
-backup root 19 to 29 23
+backup config 1 to 31 20
+backup super 2 to 30 19
+backup root 10 to 29 18
 service test.1
--- a/tests/test.1/blocks/10
+++ b/tests/test.1/blocks/10
@@ -1,17 +1,17 @@
-Tdentry 10
-qid.version 0
+name /
+size 0
+pdblkno 0
+pqpath 0
+mtime 1668540127356899518
 qid.path 10
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267958478899561
-mode 444
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 25
-	1 0
+	0 3
+	1 11
 	2 0
 	3 0
 	4 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name config.1
--- a/tests/test.1/blocks/11
+++ b/tests/test.1/blocks/11
@@ -1,16 +1,16 @@
-Tdentry 11
+name dir1
+size 0
+pdblkno 10
+pqpath 10
+mtime 1668540128490501997
+qid.path 64
 qid.version 0
-qid.path 11
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267958478902502
-mode 444
-uid -1
+mode 20000000777
+uid 10006
 gid -1
-muid -1
+muid 10006
 direct blocks
-	0 24
+	0 12
 	1 0
 	2 0
 	3 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name super.1
--- a/tests/test.1/blocks/12
+++ b/tests/test.1/blocks/12
@@ -1,52 +1,12 @@
-Tdentry 12
+name file1
+size 5
+pdblkno 11
+pqpath 64
+mtime 1668540128492461592
+qid.path 65
 qid.version 0
-qid.path 12
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267958478904853
-mode 444
-uid -1
+mode 666
+uid 10006
 gid -1
-muid -1
-direct blocks
-	0 23
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.1
+muid 10006
+test
--- a/tests/test.1/blocks/13
+++ b/tests/test.1/blocks/13
@@ -1,52 +1,1 @@
-Tdentry 13
-qid.version 0
-qid.path 13
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668267958478865472
-mode 20000000777
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 14
-	1 18
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name users
+Tblank 0
--- a/tests/test.1/blocks/14
+++ b/tests/test.1/blocks/14
@@ -1,52 +1,1 @@
 Tdentry 14
-qid.version 0
-qid.path 14
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668267958478907115
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 15
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name inuse
--- a/tests/test.1/blocks/15
+++ b/tests/test.1/blocks/15
@@ -1,7 +1,1 @@
-Tdata 14
--1:adm:adm:glenda
-0:none:adm:
-9999:noworld::
-10000:sys::
-10001:upas:upas:
-10006:glenda:glenda:
+Tdentry 13
--- a/tests/test.1/blocks/16
+++ b/tests/test.1/blocks/16
@@ -1,52 +1,1 @@
-Tdentry 16
-qid.version 0
-qid.path 16
-size 9
-pdblkno 3
-pqpath 3
-mtime 1668267960619603517
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 26
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name frees
+Tdentry 12
--- a/tests/test.1/blocks/17
+++ b/tests/test.1/blocks/17
@@ -1,52 +1,1 @@
-Tdentry 17
-qid.version 0
-qid.path 17
-size 0
-pdblkno 3
-pqpath 3
-mtime 1668267958478874732
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name ctl
+Tblank 0
--- a/tests/test.1/blocks/18
+++ b/tests/test.1/blocks/18
@@ -1,16 +1,16 @@
-Tdentry 18
+name root.1
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668540127356833806
+qid.path 17
 qid.version 0
-qid.path 18
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668267958478911556
 mode 444
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 0
+	0 18
 	1 0
 	2 0
 	3 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name staging
--- a/tests/test.1/blocks/19
+++ b/tests/test.1/blocks/19
@@ -1,52 +1,13 @@
-Tdentry 19
-qid.version 0
-qid.path 19
+name super.1
 size 0
-pdblkno 0
-pqpath 0
-mtime 1668267958478915664
-mode 20000000777
+pdblkno 5
+pqpath 5
+mtime 1668540127356831723
+qid.path 16
+qid.version 0
+mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 3
-	1 20
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name /
+qidgen 66
+fsok 1
--- a/tests/test.1/blocks/2
+++ b/tests/test.1/blocks/2
@@ -1,6 +1,13 @@
-Tdata 5
-start 0
-tfree 0
+name super
+size 18
+pdblkno 3
+pqpath 3
+mtime 1668540127356777579
+qid.path 2
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 qidgen 66
-frees 0
 fsok 1
--- a/tests/test.1/blocks/20
+++ b/tests/test.1/blocks/20
@@ -1,52 +1,17 @@
-Tdentry 64
-qid.version 0
-qid.path 64
+name config.1
 size 0
-pdblkno 19
-pqpath 19
-mtime 1668267959614455311
-mode 20000000777
-uid 10006
+pdblkno 5
+pqpath 5
+mtime 1668540127356829437
+qid.path 15
+qid.version 0
+mode 444
+uid -1
 gid -1
-muid 10006
-direct blocks
-	0 21
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name dir1
+muid -1
+size 16384
+nblocks 32
+backup config 1 to 31 20
+backup super 2 to 30 19
+backup root 10 to 29 18
+service test.1
--- a/tests/test.1/blocks/21
+++ b/tests/test.1/blocks/21
@@ -1,52 +1,1 @@
-Tdentry 65
-qid.version 0
-qid.path 65
-size 5
-pdblkno 20
-pqpath 64
-mtime 1668267959616332542
-mode 666
-uid 10006
-gid -1
-muid 10006
-direct blocks
-	0 22
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name file1
+Tblank 0
--- a/tests/test.1/blocks/22
+++ b/tests/test.1/blocks/22
@@ -1,2 +1,1 @@
-Tdata 65
-test
+Tblank 0
--- a/tests/test.1/blocks/23
+++ b/tests/test.1/blocks/23
@@ -1,1 +1,1 @@
-Tdata 12
+Tblank 0
--- a/tests/test.1/blocks/24
+++ b/tests/test.1/blocks/24
@@ -1,6 +1,1 @@
-Tdata 11
-start 0
-tfree 0
-qidgen 66
-frees 0
-fsok 1
+Tblank 0
--- a/tests/test.1/blocks/25
+++ b/tests/test.1/blocks/25
@@ -1,7 +1,1 @@
-Tdata 10
-size 16384
-nblocks 32
-backup config 1 to 31 25
-backup super 2 to 30 24
-backup root 19 to 29 23
-service test.1
+Tblank 0
--- a/tests/test.1/blocks/26
+++ b/tests/test.1/blocks/26
@@ -1,2 +1,1 @@
-Tdata 16
-26 28 3
+Tblank 0
--- a/tests/test.1/blocks/29
+++ b/tests/test.1/blocks/29
@@ -1,1 +1,48 @@
-Tdata 9
+name root.0
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668540127356820790
+qid.path 14
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+direct blocks
+	0 29
+	1 0
+	2 0
+	3 0
+	4 0
+	5 0
+	6 0
+	7 0
+	8 0
+	9 0
+	10 0
+	11 0
+	12 0
+	13 0
+	14 0
+	15 0
+	16 0
+	17 0
+	18 0
+	19 0
+	20 0
+	21 0
+	22 0
+	23 0
+	24 0
+	25 0
+	26 0
+	27 0
+	28 0
+	29 0
+	30 0
+	31 0
+indirect blocks
+	0 0
+	1 0
+	2 0
--- a/tests/test.1/blocks/3
+++ b/tests/test.1/blocks/3
@@ -1,21 +1,21 @@
-Tdentry 3
-qid.version 0
-qid.path 3
+name adm
 size 0
-pdblkno 19
-pqpath 19
-mtime 1668267958478834785
+pdblkno 10
+pqpath 10
+mtime 1668540127356889912
+qid.path 3
+qid.version 0
 mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 4
-	1 5
-	2 6
-	3 13
-	4 16
-	5 17
+	0 1
+	1 2
+	2 5
+	3 4
+	4 7
+	5 8
 	6 0
 	7 0
 	8 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name adm
--- a/tests/test.1/blocks/30
+++ b/tests/test.1/blocks/30
@@ -1,6 +1,13 @@
-Tdata 8
-start 0
-tfree 0
+name super.0
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668540127356799904
+qid.path 13
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 qidgen 66
-frees 0
 fsok 1
--- a/tests/test.1/blocks/31
+++ b/tests/test.1/blocks/31
@@ -1,7 +1,17 @@
-Tdata 7
+name config.0
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668540127356789088
+qid.path 12
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 size 16384
 nblocks 32
-backup config 1 to 31 25
-backup super 2 to 30 24
-backup root 19 to 29 23
+backup config 1 to 31 20
+backup super 2 to 30 19
+backup root 10 to 29 18
 service test.1
--- a/tests/test.1/blocks/4
+++ b/tests/test.1/blocks/4
@@ -1,17 +1,17 @@
-Tdentry 4
-qid.version 0
-qid.path 4
-size 0
+name users
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668267958478871986
-mode 444
+mtime 1668540127356894780
+qid.path 4
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 1
-	1 0
+	0 6
+	1 9
 	2 0
 	3 0
 	4 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name config
--- a/tests/test.1/blocks/5
+++ b/tests/test.1/blocks/5
@@ -1,21 +1,21 @@
-Tdentry 5
-qid.version 0
-qid.path 5
-size 0
+name bkp
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668267958478877355
-mode 444
+mtime 1668540127356892267
+qid.path 5
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 2
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
+	0 31
+	1 30
+	2 29
+	3 20
+	4 19
+	5 18
 	6 0
 	7 0
 	8 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name super
--- a/tests/test.1/blocks/6
+++ b/tests/test.1/blocks/6
@@ -1,52 +1,17 @@
-Tdentry 6
-qid.version 0
+name inuse
+size 95
+pdblkno 4
+pqpath 4
+mtime 1668540127356897130
 qid.path 6
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668267958478839637
-mode 20000000777
+qid.version 0
+mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 7
-	1 8
-	2 9
-	3 10
-	4 11
-	5 12
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name bkp
+-1:adm:adm:glenda
+0:none:adm:
+9999:noworld::
+10000:sys::
+10001:upas:upas:
+10006:glenda:glenda:
--- a/tests/test.1/blocks/7
+++ b/tests/test.1/blocks/7
@@ -1,52 +1,13 @@
-Tdentry 7
-qid.version 0
+name frees
+size 17
+pdblkno 3
+pqpath 3
+mtime 1668540129495975093
 qid.path 7
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267958478885492
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 31
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name config.0
+13 17 5
+21 28 8
--- a/tests/test.1/blocks/8
+++ b/tests/test.1/blocks/8
@@ -1,52 +1,11 @@
-Tdentry 8
-qid.version 0
+name ctl
+size 0
+pdblkno 3
+pqpath 3
+mtime 1668540127356906100
 qid.path 8
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267958478887649
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 30
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name super.0
--- a/tests/test.1/blocks/9
+++ b/tests/test.1/blocks/9
@@ -1,52 +1,11 @@
-Tdentry 9
-qid.version 0
+name staging
+size 0
+pdblkno 4
+pqpath 4
+mtime 1668540127356916679
 qid.path 9
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668267958478889704
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 29
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.0
--- a/tests/test.2/blocks/0
+++ b/tests/test.2/blocks/0
@@ -1,3 +1,13 @@
-Tmagic 1
+name magic
+size 18
+pdblkno 3
+pqpath 3
+mtime 1668545342185811391
+qid.path 11
+qid.version 0
+mode 20000000777
+uid -1
+gid -1
+muid -1
 m[a]fs device
 512
--- a/tests/test.2/blocks/1
+++ b/tests/test.2/blocks/1
@@ -1,7 +1,17 @@
-Tdata 4
-size 20480
-nblocks 40
-backup config 1 to 39 29
-backup super 2 to 38 28
-backup root 19 to 37 27
+name config
+size 110
+pdblkno 3
+pqpath 3
+mtime 1668545342185839743
+qid.path 1
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+size 24576
+nblocks 48
+backup config 1 to 47 28
+backup super 2 to 46 27
+backup root 10 to 45 26
 service test.2
--- a/tests/test.2/blocks/10
+++ b/tests/test.2/blocks/10
@@ -1,17 +1,17 @@
-Tdentry 10
-qid.version 0
+name /
+size 0
+pdblkno 0
+pqpath 0
+mtime 1668545342185837664
 qid.path 10
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268165996723514
-mode 444
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 29
-	1 0
+	0 3
+	1 11
 	2 0
 	3 0
 	4 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name config.1
--- a/tests/test.2/blocks/11
+++ b/tests/test.2/blocks/11
@@ -1,52 +1,11 @@
-Tdentry 11
+name 
+size 0
+pdblkno 0
+pqpath 0
+mtime 0
+qid.path 0
 qid.version 0
-qid.path 11
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268165996735329
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 28
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name super.1
+mode 0
+uid 0
+gid 0
+muid 0
--- a/tests/test.2/blocks/12
+++ b/tests/test.2/blocks/12
@@ -1,52 +1,1 @@
-Tdentry 12
-qid.version 0
-qid.path 12
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268165996738003
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 27
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.1
+Tdentry 16
--- a/tests/test.2/blocks/13
+++ b/tests/test.2/blocks/13
@@ -1,52 +1,1 @@
-Tdentry 13
-qid.version 0
-qid.path 13
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668268165996702062
-mode 20000000777
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 14
-	1 18
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name users
+Tdentry 15
--- a/tests/test.2/blocks/14
+++ b/tests/test.2/blocks/14
@@ -1,52 +1,1 @@
-Tdentry 14
-qid.version 0
-qid.path 14
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668268165996740186
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 15
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name inuse
+unknown tag type 54 path 2617
--- a/tests/test.2/blocks/15
+++ b/tests/test.2/blocks/15
@@ -1,7 +1,1 @@
-Tdata 14
--1:adm:adm:glenda
-0:none:adm:
-9999:noworld::
-10000:sys::
-10001:upas:upas:
-10006:glenda:glenda:
+Tblank 0
--- a/tests/test.2/blocks/16
+++ b/tests/test.2/blocks/16
@@ -1,52 +1,1 @@
-Tdentry 16
-qid.version 0
-qid.path 16
-size 17
-pdblkno 3
-pqpath 3
-mtime 1668268168265482931
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 21
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name frees
+Tblank 0
--- a/tests/test.2/blocks/17
+++ b/tests/test.2/blocks/17
@@ -1,52 +1,1 @@
-Tdentry 17
-qid.version 0
-qid.path 17
-size 0
-pdblkno 3
-pqpath 3
-mtime 1668268165996707789
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name ctl
+Tblank 0
--- a/tests/test.2/blocks/18
+++ b/tests/test.2/blocks/18
@@ -1,52 +1,1 @@
-Tdentry 18
-qid.version 0
-qid.path 18
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668268165996742342
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name staging
+Tblank 0
--- a/tests/test.2/blocks/19
+++ b/tests/test.2/blocks/19
@@ -1,52 +1,1 @@
-Tdentry 19
-qid.version 0
-qid.path 19
-size 0
-pdblkno 0
-pqpath 0
-mtime 1668268165996748935
-mode 20000000777
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 3
-	1 20
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name /
+Tblank 0
--- a/tests/test.2/blocks/2
+++ b/tests/test.2/blocks/2
@@ -1,6 +1,13 @@
-Tdata 5
-start 0
-tfree 0
+name super
+size 18
+pdblkno 3
+pqpath 3
+mtime 1668545342185727298
+qid.path 2
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
 qidgen 72
-frees 0
 fsok 1
--- a/tests/test.2/blocks/23
+++ b/tests/test.2/blocks/23
@@ -1,1 +1,1 @@
-Tdata 71
+Tblank 0
--- a/tests/test.2/blocks/26
+++ b/tests/test.2/blocks/26
@@ -1,1 +1,48 @@
-Tblank 0
+name root.1
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668545342185769551
+qid.path 17
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+direct blocks
+	0 26
+	1 0
+	2 0
+	3 0
+	4 0
+	5 0
+	6 0
+	7 0
+	8 0
+	9 0
+	10 0
+	11 0
+	12 0
+	13 0
+	14 0
+	15 0
+	16 0
+	17 0
+	18 0
+	19 0
+	20 0
+	21 0
+	22 0
+	23 0
+	24 0
+	25 0
+	26 0
+	27 0
+	28 0
+	29 0
+	30 0
+	31 0
+indirect blocks
+	0 0
+	1 0
+	2 0
--- a/tests/test.2/blocks/27
+++ b/tests/test.2/blocks/27
@@ -1,1 +1,13 @@
-Tdata 12
+name super.1
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668545342185767247
+qid.path 16
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+qidgen 72
+fsok 1
--- a/tests/test.2/blocks/28
+++ b/tests/test.2/blocks/28
@@ -1,6 +1,17 @@
-Tdata 11
-start 0
-tfree 0
-qidgen 72
-frees 0
-fsok 1
+name config.1
+size 0
+pdblkno 5
+pqpath 5
+mtime 1668545342185764644
+qid.path 15
+qid.version 0
+mode 444
+uid -1
+gid -1
+muid -1
+size 24576
+nblocks 48
+backup config 1 to 47 28
+backup super 2 to 46 27
+backup root 10 to 45 26
+service test.2
--- a/tests/test.2/blocks/29
+++ b/tests/test.2/blocks/29
@@ -1,7 +1,1 @@
-Tdata 10
-size 20480
-nblocks 40
-backup config 1 to 39 29
-backup super 2 to 38 28
-backup root 19 to 37 27
-service test.2
+Tdata 71
--- a/tests/test.2/blocks/3
+++ b/tests/test.2/blocks/3
@@ -1,21 +1,21 @@
-Tdentry 3
-qid.version 0
-qid.path 3
+name adm
 size 0
-pdblkno 19
-pqpath 19
-mtime 1668268165996672815
+pdblkno 10
+pqpath 10
+mtime 1668545342185828484
+qid.path 3
+qid.version 0
 mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 4
-	1 5
-	2 6
-	3 13
-	4 16
-	5 17
+	0 1
+	1 2
+	2 5
+	3 4
+	4 7
+	5 8
 	6 0
 	7 0
 	8 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name adm
--- a/tests/test.2/blocks/30
+++ b/tests/test.2/blocks/30
@@ -1,1 +1,1 @@
-Tblank 0
+Tdentry 14
--- a/tests/test.2/blocks/31
+++ b/tests/test.2/blocks/31
@@ -1,1 +1,1 @@
-Tblank 0
+Tdentry 13
--- a/tests/test.2/blocks/32
+++ b/tests/test.2/blocks/32
@@ -1,1 +1,1 @@
-Tblank 0
+Tdentry 12
--- a/tests/test.2/blocks/37
+++ b/tests/test.2/blocks/37
@@ -1,1 +1,1 @@
-Tdata 9
+Tblank 0
--- a/tests/test.2/blocks/38
+++ b/tests/test.2/blocks/38
@@ -1,6 +1,1 @@
-Tdata 8
-start 0
-tfree 0
-qidgen 72
-frees 0
-fsok 1
+Tblank 0
--- a/tests/test.2/blocks/39
+++ b/tests/test.2/blocks/39
@@ -1,7 +1,1 @@
-Tdata 7
-size 20480
-nblocks 40
-backup config 1 to 39 29
-backup super 2 to 38 28
-backup root 19 to 37 27
-service test.2
+Tblank 0
--- a/tests/test.2/blocks/4
+++ b/tests/test.2/blocks/4
@@ -1,17 +1,17 @@
-Tdentry 4
-qid.version 0
-qid.path 4
-size 0
+name users
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668268165996705316
-mode 444
+mtime 1668545342185833203
+qid.path 4
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 1
-	1 0
+	0 6
+	1 9
 	2 0
 	3 0
 	4 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name config
--- a/tests/test.2/blocks/5
+++ b/tests/test.2/blocks/5
@@ -1,21 +1,21 @@
-Tdentry 5
-qid.version 0
-qid.path 5
-size 0
+name bkp
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668268165996710403
-mode 444
+mtime 1668545342185830807
+qid.path 5
+qid.version 0
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 2
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
+	0 47
+	1 46
+	2 45
+	3 28
+	4 27
+	5 26
 	6 0
 	7 0
 	8 0
@@ -46,7 +46,3 @@
 	0 0
 	1 0
 	2 0
-	3 0
-	4 0
-	5 0
-name super
--- a/tests/test.2/blocks/6
+++ b/tests/test.2/blocks/6
@@ -1,52 +1,17 @@
-Tdentry 6
-qid.version 0
+name inuse
+size 95
+pdblkno 4
+pqpath 4
+mtime 1668545342185835427
 qid.path 6
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668268165996683342
-mode 20000000777
+qid.version 0
+mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 7
-	1 8
-	2 9
-	3 10
-	4 11
-	5 12
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name bkp
+-1:adm:adm:glenda
+0:none:adm:
+9999:noworld::
+10000:sys::
+10001:upas:upas:
+10006:glenda:glenda:
--- a/tests/test.2/blocks/7
+++ b/tests/test.2/blocks/7
@@ -1,52 +1,13 @@
-Tdentry 7
-qid.version 0
+name frees
+size 19
+pdblkno 3
+pqpath 3
+mtime 1668545344439983629
 qid.path 7
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268165996717290
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 39
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name config.0
+12 25 14
+29 44 16
--- a/tests/test.2/blocks/8
+++ b/tests/test.2/blocks/8
@@ -1,52 +1,11 @@
-Tdentry 8
-qid.version 0
+name ctl
+size 0
+pdblkno 3
+pqpath 3
+mtime 1668545342185844480
 qid.path 8
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268165996719501
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 38
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name super.0
--- a/tests/test.2/blocks/9
+++ b/tests/test.2/blocks/9
@@ -1,52 +1,11 @@
-Tdentry 9
-qid.version 0
+name staging
+size 0
+pdblkno 4
+pqpath 4
+mtime 1668545342185855739
 qid.path 9
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268165996721532
+qid.version 0
 mode 444
 uid -1
 gid -1
 muid -1
-direct blocks
-	0 37
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.0
--- a/tests/test.2/params
+++ b/tests/test.2/params
@@ -1,1 +1,1 @@
-nblocks=40
+nblocks=48
--- a/tests/test.3/blocks/11
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 11
-qid.version 0
-qid.path 11
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268616172911650
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 20488
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name super.1
--- a/tests/test.3/blocks/12
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 12
-qid.version 0
-qid.path 12
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268616172914257
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 20487
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name root.1
--- a/tests/test.3/blocks/13
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 13
-qid.version 0
-qid.path 13
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668268616172875707
-mode 20000000777
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 14
-	1 18
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name users
--- a/tests/test.3/blocks/14
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 14
-qid.version 0
-qid.path 14
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668268616172916463
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 15
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name inuse
--- a/tests/test.3/blocks/15
+++ /dev/null
@@ -1,7 +1,0 @@
-Tdata 14
--1:adm:adm:glenda
-0:none:adm:
-9999:noworld::
-10000:sys::
-10001:upas:upas:
-10006:glenda:glenda:
--- a/tests/test.3/blocks/16
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 16
-qid.version 0
-qid.path 16
-size 34
-pdblkno 3
-pqpath 3
-mtime 1668268654717936930
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 21
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name frees
--- a/tests/test.3/blocks/17
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 17
-qid.version 0
-qid.path 17
-size 0
-pdblkno 3
-pqpath 3
-mtime 1668268616172881003
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name ctl
--- a/tests/test.3/blocks/18
+++ /dev/null
@@ -1,52 +1,0 @@
-Tdentry 18
-qid.version 0
-qid.path 18
-size 503
-pdblkno 13
-pqpath 13
-mtime 1668268616172918640
-mode 444
-uid -1
-gid -1
-muid -1
-direct blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-	6 0
-	7 0
-	8 0
-	9 0
-	10 0
-	11 0
-	12 0
-	13 0
-	14 0
-	15 0
-	16 0
-	17 0
-	18 0
-	19 0
-	20 0
-	21 0
-	22 0
-	23 0
-	24 0
-	25 0
-	26 0
-	27 0
-	28 0
-	29 0
-	30 0
-	31 0
-indirect blocks
-	0 0
-	1 0
-	2 0
-	3 0
-	4 0
-	5 0
-name staging
--- a/tests/test.3/blocks/4
+++ b/tests/test.3/blocks/4
@@ -1,17 +1,17 @@
-Tdentry 4
+Tdentry 13
 qid.version 0
-qid.path 4
-size 0
+qid.path 13
+size 96
 pdblkno 3
 pqpath 3
-mtime 1668268616172879046
-mode 444
+mtime 1668268616172875707
+mode 20000000777
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 1
-	1 0
+	0 14
+	1 18
 	2 0
 	3 0
 	4 0
@@ -49,4 +49,4 @@
 	3 0
 	4 0
 	5 0
-name config
+name users
--- a/tests/test.3/blocks/6
+++ b/tests/test.3/blocks/6
@@ -1,21 +1,21 @@
-Tdentry 6
+Tdentry 14
 qid.version 0
-qid.path 6
-size 96
-pdblkno 3
-pqpath 3
-mtime 1668268616172860576
-mode 20000000777
+qid.path 14
+size 503
+pdblkno 13
+pqpath 13
+mtime 1668268616172916463
+mode 444
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 7
-	1 8
-	2 9
-	3 10
-	4 11
-	5 12
+	0 15
+	1 0
+	2 0
+	3 0
+	4 0
+	5 0
 	6 0
 	7 0
 	8 0
@@ -49,4 +49,4 @@
 	3 0
 	4 0
 	5 0
-name bkp
+name inuse
--- a/tests/test.3/blocks/7
+++ b/tests/test.3/blocks/7
@@ -1,16 +1,16 @@
-Tdentry 7
+Tdentry 16
 qid.version 0
-qid.path 7
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268616172890675
+qid.path 16
+size 34
+pdblkno 3
+pqpath 3
+mtime 1668268654717936930
 mode 444
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 40959
+	0 21
 	1 0
 	2 0
 	3 0
@@ -49,4 +49,4 @@
 	3 0
 	4 0
 	5 0
-name config.0
+name frees
--- a/tests/test.3/blocks/8
+++ b/tests/test.3/blocks/8
@@ -1,16 +1,16 @@
-Tdentry 8
+Tdentry 17
 qid.version 0
-qid.path 8
-size 503
-pdblkno 6
-pqpath 6
-mtime 1668268616172893347
+qid.path 17
+size 0
+pdblkno 3
+pqpath 3
+mtime 1668268616172881003
 mode 444
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 40958
+	0 0
 	1 0
 	2 0
 	3 0
@@ -49,4 +49,4 @@
 	3 0
 	4 0
 	5 0
-name super.0
+name ctl
--- a/tests/test.3/blocks/9
+++ b/tests/test.3/blocks/9
@@ -1,16 +1,16 @@
-Tdentry 9
+Tdentry 18
 qid.version 0
-qid.path 9
+qid.path 18
 size 503
-pdblkno 6
-pqpath 6
-mtime 1668268616172895606
+pdblkno 13
+pqpath 13
+mtime 1668268616172918640
 mode 444
 uid -1
 gid -1
 muid -1
 direct blocks
-	0 40957
+	0 0
 	1 0
 	2 0
 	3 0
@@ -49,4 +49,4 @@
 	3 0
 	4 0
 	5 0
-name root.0
+name staging
--- a/updatefrees.c
+++ b/updatefrees.c
@@ -26,9 +26,10 @@
 {
 	u64 size, freeblkno;
 	s32 nfreesize;
-	u8 buf[Rawblocksize], frees[Rawblocksize];
+	s8 buf[Dentrysize], frees[Rawblocksize];
 	int fd;
 	Content *c;
+	Dentry *d;
 
 	ARGBEGIN{
 	default:	usage();
@@ -46,7 +47,7 @@
 	if(freesfile == nil)
 		sysfatal("no frees file");
 
-	memset(buf,0,Rawblocksize);
+	memset(buf,0,Dentrysize);
 	memset(frees, 0, Rawblocksize);
 
 	fd = open(freesfile, OREAD);
@@ -71,28 +72,32 @@
 		panic("null size %s", devfile);
 
 	if(debug){
-		print("Dentry1 size %d Namelen %llud\n", sizeof(Dentry1), Namelen);
+		print("Dentryblocks size %d Namelen %d\n", sizeof(Dentryblocks), Namelen);
 		print("Dentry size %d\n", sizeof(Dentry));
 	}
 
-	devread(Bdfrees, buf);
+	devread(Bdfrees, buf, Dentryunits);
 	// showblock(1, buf);
 
-	c = (Content*)buf;
-	if(c->d.size != nfreesize)
-		print("changed size: %llud to %d\n", c->d.size, nfreesize);
-	c->d.size = nfreesize;
-	if(c->d.dblocks[0] != freeblkno)
-		print("changed dblocks[0]: %llud to %llud\n", c->d.dblocks[0], freeblkno);
-	c->d.dblocks[0] = freeblkno;
+	d = (Dentry*)buf;
+	if(d->size != nfreesize)
+		print("changed size: %llud to %d\n", d->size, nfreesize);
+	d->size = nfreesize;
+	if(nfreesize < Ddatasize){
+		strncpy(d->buf, frees, nfreesize);
+		devwrite(Bdfrees, buf, Dentryunits);
+	}else{
+		if(d->dblocks[0] != freeblkno)
+			print("changed dblocks[0]: %llud to %llud\n", d->dblocks[0], freeblkno);
+		d->dblocks[0] = freeblkno;
 
-	c = (Content*)frees;
-	c->type = Tdata;
-	c->path = Qpfrees;
+		c = (Content*)frees;
+		c->type = Tdata;
+		c->path = Qpfrees;
 
-	devwrite(Bdfrees, buf);
-	devwrite(freeblkno, frees);
-
+		devwrite(Bdfrees, buf, Dentryunits);
+		devwrite(freeblkno, frees, Rawblockunits);
+	}
 	close(devfd);
 	exits(0);
 }
--- a/used.c
+++ b/used.c
@@ -13,8 +13,9 @@
 Extents useds = {0};
 int chatty9p = 0;
 char *devfile = nil;
-void walkdentry(u64 blkno);
-int checkblock(u64 blkno, s16 tag, u64 qpath);
+void walkdirectory(u64 blkno);
+void walkfile(u64 blkno);
+int checkdentry(u64 blkno, s16 tag, u64 qpath);
 
 static void
 usage(void)
@@ -48,11 +49,11 @@
 	if(size == 0)
 		panic("null size %s", devfile);
 	if(chatty9p)
-		print("%s %llud bytes %llud blocks\n", devfile, size, size/Rawblocksize);
+		print("%s %llud bytes %llud blocks\n", devfile, size, size/Unit);
 
 	initextents(&useds);
-	checkblock(Bmagicb, Tmagic, Qpmagic);
-	walkdentry(Bdroot);
+	checkdentry(Bdmagic, Tdentry, Qpmagic);
+	walkdirectory(Bdroot);
 	close(devfd);
 	showextents(1, "", &useds);
 	exits(0);
@@ -59,7 +60,7 @@
 }
 
 int
-checkvalid(u64 blkno, Content *t, s16 tagtype, u64 qpath)
+checkvalid(u64 blkno, Tag *t, s16 tagtype, u64 qpath)
 {
 	if(t->type != tagtype || t->path != qpath){
 		/* if(chatty9p) */
@@ -71,19 +72,19 @@
 	if(chatty9p)
 		print("blkno %llud tag %s\n", blkno, tagnames[t->type]);
 	// print("%llud\n", blkno);
-	add(&useds, blkno, 1);
+	add(&useds, blkno, blklen(tagtype));
 	return 1;
 }
 
 int
-checkblock(u64 blkno, s16 tag, u64 qpath)
+checkdentry(u64 blkno, s16 tag, u64 qpath)
 {
 	u8 buf[Rawblocksize];
-	Content *t;
+	Dentry *d;
 
-	devread(blkno, buf);
-	t = (Content*)buf;
-	return checkvalid(blkno, t, tag, qpath);
+	devread(blkno, buf, Dentryunits);
+	d = (Dentry*)buf;
+	return checkvalid(blkno, d, tag, qpath);
 }
 
 void
@@ -94,7 +95,7 @@
 	u64 cblkno, *bufa;
 	int i;
 
-	devread(blkno, buf);
+	devread(blkno, buf, blklen(tag));
 	t = (Content*)buf;
 	if(checkvalid(blkno, t, tag, qpath)){
 		if(t->type == Tind0){
@@ -104,10 +105,10 @@
 				if(cblkno == 0)
 					return;
 				cbuf = malloc(Rawblocksize);
-				devread(cblkno, cbuf);
+				devread(cblkno, cbuf, blklen(tag));
 				ct = (Content*)cbuf;
 				if(ct->type == Tdentry && ct->type == bottomtag)
-					walkdentry(cblkno);
+					walkdirectory(cblkno);
 				else
 					checkvalid(cblkno, ct, bottomtag, qpath);
 				free(cbuf);
@@ -119,7 +120,7 @@
 				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				devread(cblkno, cbuf);
+				devread(cblkno, cbuf, blklen(tag));
 				/* check tag */
 				walkindir(cblkno, tag-1,  bottomtag, qpath);
 			}
@@ -130,46 +131,100 @@
 }
 
 void
-walkdentry(u64 blkno)
+walkdirectory(u64 blkno)
 {
 	u8 buf[Rawblocksize], *cbuf;
+	Dentry *d, *cd;
+	Content *ct;
+	u64 cblkno;
+	int i;
+
+	devread(blkno, buf, Dentryunits);
+	d = (Dentry*)buf;
+	if(chatty9p)
+		print("walkdirectory %llud tag %s name %s d->qid.path %llud\n",
+				blkno, tagnames[d->type], d->name, d->qid.path);
+	if(d->type != Tdentry || d->path != d->qid.path){
+		if(chatty9p)
+			print("walkdirectory invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
+					blkno, tagnames[Tdentry], d->qid.path, tagnames[d->type], d->path);
+		fprint(2, "%llud\n", blkno);
+	}else{
+		// print("%llud\n", blkno);
+		add(&useds, blkno, Dentryunits);
+	}
+	/* do not list the data blocks used by /adm/frees
+		as they are considered to be free blocks */
+	if(blkno == Bdfrees)
+		return;
+	for(i = 0; i<Ndblock; i++){
+		cblkno = d->dblocks[i];
+		if(cblkno == 0)
+			return;
+		cbuf = malloc(Dentrysize);
+		devread(cblkno, cbuf, Dentryunits);
+		cd = (Dentry*)cbuf;
+		if((cd->mode & DMDIR) > 0)
+			walkdirectory(cblkno);
+		else
+			walkfile(cblkno);
+		free(cbuf);
+	}
+	cbuf = malloc(Rawblocksize);
+	for(i = 0; i<Niblock; i++){
+		cblkno = d->iblocks[i];
+		if(cblkno == 0)
+			return;
+		devread(cblkno, cbuf, Dentryunits);
+		ct = (Content*)cbuf;
+		if(ct->type == Tind0+i){
+			walkindir(cblkno, Tind0+i, Tdentry, d->qid.path);
+		}else{
+			fprint(2, "invalid indir tag %llud\n", cblkno);
+			fprint(2, "%llud\n", cblkno);
+		}
+	}
+	free(cbuf);
+	return;
+}
+
+void
+walkfile(u64 blkno)
+{
+	u8 buf[Rawblocksize], *cbuf;
 	Dentry *d;
-	Content *t, *ct;
+	Content *ct;
 	u64 cblkno;
 	int i;
-	u8 isdir;
 
-	devread(blkno, buf);
-	t = (Content*)buf;
+	devread(blkno, buf, Dentryunits);
 	d = (Dentry*)buf;
-	isdir = (d->mode & DMDIR) > 0;
 	if(chatty9p)
-		print("walkdentry %llud tag %s name %s d->qid.path %llud\n",
-				blkno, tagnames[t->type], d->name, d->qid.path);
-	if(t->type != Tdentry || t->path != d->qid.path){
+		print("walkfile %llud tag %s name %s d->qid.path %llud\n",
+				blkno, tagnames[d->type], d->name, d->qid.path);
+	if(d->type != Tdentry || d->path != d->qid.path){
 		if(chatty9p)
-			print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
-					blkno, tagnames[Tdentry], d->qid.path, tagnames[t->type], t->path);
+			print("walkfile invalid %llud tag/path expected %s/%llud actual %s/%llud\n",
+					blkno, tagnames[Tdentry], d->qid.path, tagnames[d->type], d->path);
 		fprint(2, "%llud\n", blkno);
 	}else{
 		// print("%llud\n", blkno);
-		add(&useds, blkno, 1);
+		add(&useds, blkno, Dentryunits);
 	}
 	/* do not list the data blocks used by /adm/frees
 		as they are considered to be free blocks */
 	if(blkno == Bdfrees)
 		return;
+	if(d->size <= Ddatasize)
+		return;
 	for(i = 0; i<Ndblock; i++){
 		cblkno = d->dblocks[i];
 		if(cblkno == 0)
 			return;
 		cbuf = malloc(Rawblocksize);
-		devread(cblkno, cbuf);
+		devread(cblkno, cbuf, Rawblockunits);
 		ct = (Content*)cbuf;
-		if(isdir)
-			walkdentry(cblkno);
-		else
-			checkvalid(cblkno, ct, Tdata, d->qid.path);
+		checkvalid(cblkno, ct, Tdata, d->qid.path);
 		free(cbuf);
 	}
 	cbuf = malloc(Rawblocksize);
@@ -177,10 +232,10 @@
 		cblkno = d->iblocks[i];
 		if(cblkno == 0)
 			return;
-		devread(cblkno, cbuf);
+		devread(cblkno, cbuf, Rawblockunits);
 		ct = (Content*)cbuf;
 		if(ct->type == Tind0+i){
-			walkindir(cblkno, Tind0+i, isdir ? Tdentry : Tdata, d->qid.path);
+			walkindir(cblkno, Tind0+i, Tdata, d->qid.path);
 		}else{
 			fprint(2, "invalid indir tag %llud\n", cblkno);
 			fprint(2, "%llud\n", cblkno);
--- a/user.c
+++ b/user.c
@@ -424,7 +424,7 @@
 	int rv;
 
 	ubuf = getbufchk(Bdusersinuse, Breadonly, Tdentry, Qpusersinuse);
-	usize = ubuf->io->d.size+1;
+	usize = ubuf->d->size+1;
 	buf = emalloc9p(usize);
 	putbuf(ubuf);
 
@@ -452,7 +452,7 @@
 	User *us, *old;
 
 	ubuf = getbufchk(Bdusersstaging, Breadonly, Tdentry, Qpusersstaging);
-	usize = ubuf->io->d.size+1;
+	usize = ubuf->d->size+1;
 	buf = emalloc9p(usize);
 	putbuf(ubuf);
 
--- a/writer.c
+++ b/writer.c
@@ -22,6 +22,7 @@
 struct Wbuf
 {
 	u64	blkno;		/* block number on the disk, primary key */
+	u16 len;
 	Wbuf *prev, *next;	/* writer queue */
 	Iobuf *iobuf;	/* pointer to the used Iobuf in the buffer cache */
 	union{
@@ -91,8 +92,9 @@
 	}
 	w = emalloc9p(sizeof(Wbuf));
 	w->blkno = b->blkno;
-	w->payload = allocmemunit();
-	memcpy(w->payload, b->xiobuf, Rawblocksize);
+	w->len = b->len;
+	w->payload = allocmemunits(b->len);
+	memcpy(w->payload, b->xiobuf, b->len*Unit);
 	incref(&b->dirties);
 	w->iobuf = b;
 
@@ -119,50 +121,7 @@
 		stats();
 	}
 }
-void
-putwrites(Iobuf **bs, u64 len)
-{
-	Wbuf *w, *ws[Ntogether];
-	u8 empty;
-	u64 i;
-	Iobuf *b;
 
-	if(len == 0)
-		return;
-	empty = 0;
-	for(i = 0; i < len; i++){
-		b = bs[i];
-		ws[i] = w = emalloc9p(sizeof(Wbuf));
-		w->blkno = b->blkno;
-		w->payload = allocmemunit();
-		memcpy(w->payload, b->xiobuf, Rawblocksize);
-		incref(&b->dirties);
-		w->iobuf = b;
-	}
-	qlock(&drts.lck);
-	if(drts.n >= npendingwrites)
-		rsleep(&drts.isfull);
-	if(drts.n == 0)
-		empty = 1;
-	for(i = 0; i < len; i++){
-		if(chkwunlock(bs[i]) == 0){
-			showbuf(bs[i]);
-			panic("putwrite chkwunlock(p) == 0 called by %#p\n", getcallerpc(&bs));
-		}
-		if(drts.head == nil){
-			drts.head = drts.tail = ws[i];
-		}else{
-			drts.tail->next = ws[i];
-			ws[i]->prev = drts.tail;
-			drts.tail = ws[i];
-		}
-		drts.n++;
-	}
-	if(empty)
-		rwakeup(&drts.isempty);
-	qunlock(&drts.lck);
-}
-
 /*
 	dirties is decremented without a wlock() on the buffer in dowrite().
 	Using a wlock() in dowrite() deadlocks with putwrite().
@@ -174,11 +133,9 @@
 void
 dowrite(void)
 {
-	Wbuf *b, *blks[Ntogether];
-	u64 prevblkno, startblkno, n, wn, i;
-	u8 full, *jumbo;
+	Wbuf *b;
+	u64 n;
 
-	full = 0;
 	qlock(&drts.lck);
 	if(drts.n == 0){
 		if(stopwrites){
@@ -197,79 +154,24 @@
 		return;
 	}
 
-	if(drts.n >= npendingwrites)
-		full = 1;
-	if(drts.n > 1){
-		/* trying to write consecutive blocks with a write() call */
-		n = 1;
-		prevblkno = startblkno = drts.head->blkno;
-		for(b = drts.head->next;
-				n <= drts.n && b != nil && b->blkno == prevblkno+1 && n < Ntogether;
-				b = b->next){
-			prevblkno=b->blkno;
-			n++;
-		}
-		if(n > 1){
-			for(i = 0; i < n; i++)
-				blks[i] = pluck(drts.head);
-			if(full && drts.n < npendingwrites)
-				rwakeup(&drts.isfull);
-			// dprint("dowrite: at return drts.n %llud\n", drts.n);
-			qunlock(&drts.lck);
+	b = pluck(drts.head);
+	if(drts.n == npendingwrites-1)
+		rwakeup(&drts.isfull);
+	qunlock(&drts.lck);
 
-			if(chatty9p > 4){
-				if(b != nil)
-				dprint("getwrite jumbo drts.n %llud > 1 n %llud start %llud next %llud\n",
-						drts.n, n, startblkno, b->blkno);
-				else
-				dprint("getwrite jumbo drts.n %llud > 1 n %llud start %llud\n",
-						drts.n, n, startblkno);
-			}
-			jumbo = emalloc9p(n*Rawblocksize);
-			for(i = 0; i < n; i++){
-				b = blks[i];
-				memcpy(jumbo+(i*Rawblocksize), b->payload, Rawblocksize);
-				if(chatty9p > 4 && b!=nil)
-					dprint("getwrite b->blkno %llud\n", b->blkno);
-			}
-			if((wn = devwrites(startblkno, jumbo, n)) != n*Rawblocksize){
-				dprint("%s\n", errstring[Esystem]);
-				panic("error writing jumbo block %llud: %llud bytes, written %llud: %r\n",
-						startblkno, n, wn);
-			}
-			free(jumbo);
-			for(i = 0; i < n; i++){
-				b = blks[i];
-				if(chatty9p > 4)
-					dprint("dowrite %llud wunlock()'ed\n", b->blkno);
-				decref(&b->iobuf->dirties);
-				freememunit(b->payload);
-				free(b);
-				blks[i] = 0;
-			}
-			return;
-		}else
-			goto single;
-	}else{
-single:
-		b = pluck(drts.head);
-		if(full && drts.n < npendingwrites)
-			rwakeup(&drts.isfull);
-		qunlock(&drts.lck);
-
-		if(chatty9p > 4 && b!=nil)
-			dprint("getwrite done b->blkno %llud\n", b->blkno);
-		if((n = devwrite(b->blkno, b->payload)) != Rawblocksize){
-			dprint("%s\n", errstring[Esystem]);
-			panic("error writing block %llud: %llud bytes: %r\n",
-					b->blkno, n);
-		}
-		if(chatty9p > 4)
-			dprint("dowrite %llud wunlock()'ed\n", b->blkno);
-		decref(&b->iobuf->dirties);
-		freememunit(b->payload);
-		free(b);
+	if(chatty9p > 4 && b!=nil)
+		dprint("getwrite done b->blkno %llud\n", b->blkno);
+	if((n = devwrite(b->blkno, b->payload, b->len)) != b->len*Unit){
+		dprint("%s\n", errstring[Esystem]);
+		panic("error writing block %llud: %llud bytes: %r\n",
+				b->blkno, n);
 	}
+	if(chatty9p > 4)
+		dprint("dowrite %llud wunlock()'ed\n", b->blkno);
+	decref(&b->iobuf->dirties);
+	freememunits(b->payload, b->len);
+	free(b);
+
 	if(chatty9p > 4 && b!=nil)
 		stats();
 }