code: mafs

Download patch

ref: bcab1344b36df26aa0508e65eafd0d7b9626a0b5
parent: 508c4a4206a5c92ce5d8cb6bf394d11af881b270
author: 9ferno <gophone2015@gmail.com>
date: Thu Oct 20 19:52:55 EDT 2022

replaced Span with a block to reduce complexity

--- a/9p.c
+++ b/9p.c
@@ -40,7 +40,7 @@
 		return;
 	}
 
-	dbuf = getbufchk(Broot, 1, Breadonly, Tdentry, Qproot);
+	dbuf = getbufchk(Broot, Breadonly, Tdentry, Qproot);
 	if(dbuf == nil){
 		respond(req, "phase error");
 		return;
@@ -95,7 +95,7 @@
 	Dentry *d;
 	Iobuf *dbuf;
 
-	dbuf = getbufchk(((Aux*)req->fid->aux)->dblkno, 1, Breadonly,
+	dbuf = getbufchk(((Aux*)req->fid->aux)->dblkno, Breadonly,
 						Tdentry, req->fid->qid.path);
 	if(dbuf == nil){
 		dprint("fsstat dbuf == nil dblkno %llud qpath %llud\n",
@@ -157,7 +157,7 @@
 
 	/* TODO cwfs/9p2.c, hjfs/fs2.c and kfs64.b do more here. Get that stuff in. */
 
-	dbuf = getbufchk(((Aux*)req->fid->aux)->dblkno, 1, Bwritable,
+	dbuf = getbufchk(((Aux*)req->fid->aux)->dblkno, Bwritable,
 						Tdentry, req->fid->qid.path);
 	if(dbuf == nil){
 		respond(req, errstring[Eperm]);
@@ -352,7 +352,7 @@
 			if(chatty9p > 1)
 				dprint("fswalk1 .. fid->qid.path %llud aux->dblkno %llud\n",
 						fid->qid.path, aux->dblkno);
-			dbuf = getbufchk(aux->dblkno, 1, Breadonly, Tdentry, fid->qid.path);
+			dbuf = getbufchk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
 			if(dbuf == nil)
 				return errstring[Ephase];
 			d = &dbuf->io->d;
@@ -359,7 +359,7 @@
 			if(chatty9p > 1)
 				dprint("fswalk1 .. d->name %s d->qid.path %llud d->pdblkno %llud\n",
 						d->name, d->qid.path, d->pdblkno);
-			pbuf = getbufchk(d->pdblkno, 1, Breadonly, Tdentry, d->pqpath);
+			pbuf = getbufchk(d->pdblkno, Breadonly, Tdentry, d->pqpath);
 			if(pbuf == nil)
 				return errstring[Ephase];
 			putbuf(dbuf);
@@ -441,7 +441,6 @@
 	Aux *aux;
 	u32 perm;
 	Fid *fid;
-	Spanid s;
 
 	/* no create's when shutting down */
 	if(shuttingdown){
@@ -485,7 +484,7 @@
 	cbuf = nil;
 	USED(cbuf);
 	zblkno = 0;
-	dbuf = getbufchk(aux->dblkno, 1, Bwritable, Tdentry, fid->qid.path);
+	dbuf = getbufchk(aux->dblkno, Bwritable, Tdentry, fid->qid.path);
 	if(dbuf == nil){
 		respond(req, errstring[Ephase]);
 		return;
@@ -520,8 +519,7 @@
 			return;
 	}
 	for(reli = 0, blkno = 1; blkno > 0; reli++){
-		rel2abs(dparent, reli, &s);
-		blkno = s.blkno;
+		blkno = rel2abs(dparent, reli);
 		/* if(reli >= Max)
 			error(Etoobig); */
 
@@ -528,7 +526,7 @@
 		if(blkno == 0){
 			/* end reached, nothing found, create */
 			if(zblkno != 0){
-				cbuf = getbufchk(zblkno, 1,Bwritable, Tdentry, Qpnone);
+				cbuf = getbufchk(zblkno, Bwritable, Tdentry, Qpnone);
 				if(cbuf == nil){
 					putbuf(dbuf);
 					respond(req, errstring[Ephase]);
@@ -535,7 +533,7 @@
 					return;
 				}
 			}else{
-				cbuf = allocblocks(1, Tdentry, fid->qid.path);
+				cbuf = allocblock(Tdentry, fid->qid.path);
 				if(cbuf == nil){
 					putbuf(dbuf);
 					respond(req, errstring[Efull]);
@@ -589,7 +587,7 @@
 				directory dentry
 			 */
 			if(zblkno == 0 &&
-				addrelative(dparent, dbuf->blkno, reli, aux->dblkno,1) == 0){
+				addrelative(dparent, dbuf->blkno, reli, aux->dblkno) == 0){
 				putbuf(dbuf);
 				respond(req, errstring[Ephase]);
 				return;
@@ -598,7 +596,7 @@
 			respond(req, nil);
 			return;
 		}else{
-			cbuf = getbuf(blkno, 1,Breadonly, Bused);
+			cbuf = getbuf(blkno, Breadonly, Bused);
 			if(cbuf == nil){
 				putbuf(dbuf);
 				respond(req, errstring[Ephase]);
@@ -679,7 +677,7 @@
 	if(readonly && (mode & (ORCLOSE | OTRUNC | OWRITE | ORDWR)) != 0)
 		goto inval;
 
-	dbuf = getbufchk(aux->dblkno, 1, Breadonly, Tdentry, fid->qid.path);
+	dbuf = getbufchk(aux->dblkno, Breadonly, Tdentry, fid->qid.path);
 	if(dbuf == nil){
 		respond(req, errstring[Ephase]);
 		return;
@@ -1037,7 +1035,7 @@
 	.auth = auth9p,
 	.attach = fsattach,
 	.destroyfid = fsdestroyfid,
-	.msize = Maxspansize,
+	.msize = Iounit,
 
 	.walk1 = fswalk1,
 	.clone = fsclone,
@@ -1059,7 +1057,7 @@
 	.auth = auth9p,
 	.attach = fsattach,
 	.destroyfid = fsdestroyfid,
-	.msize = Maxspansize,
+	.msize = Iounit,
 
 	.walk1 = fswalk1,
 	.clone = fsclone,
@@ -1142,7 +1140,7 @@
 	u64 filesize;
 	Iobuf *dbuf;
 
-	dbuf = getbufchk(dblkno, 1, Breadonly, Tdentry, qpath);
+	dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(dbuf == nil)
 		return 0;
 	filesize = dbuf->io->d.size;
@@ -1157,7 +1155,7 @@
 	s32 n;
 	Iobuf *dbuf, *buf;
 
-	dbuf = getbufchk(dblkno, 1, Breadonly, Tdentry, qpath);
+	dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(dbuf == nil)
 		return 0;
 	d = &dbuf->io->d;
@@ -1173,13 +1171,13 @@
 		tosend = filesize - offset;
 
 	for(sent = 0; sent < tosend && offset+sent < d->size; ){
-		buf = getdataspanat(d, (offset+sent)/Maxspansize, Breadonly);
+		buf = getdatablkat(d, (offset+sent)/Blocksize, Breadonly);
 		if(buf == nil){
 			putbuf(dbuf);
 			return -1;
 		}
-		n = min(Maxspansize-((offset+sent)%Maxspansize), tosend-sent);
-		memcpy(rbuf+sent, buf->io->buf+((offset+sent)%Maxspansize), n);
+		n = min(Blocksize-((offset+sent)%Blocksize), tosend-sent);
+		memcpy(rbuf+sent, buf->io->buf+((offset+sent)%Blocksize), n);
 		sent += n;
 		putbuf(buf);
 	}
@@ -1188,7 +1186,7 @@
 }
 
 /* obsolete */
-s32
+/*s32
 updatefullspan(Dentry *d, char *wbuf, s32 wbufsize, u64 offset)
 {
 	Iobuf *buf;
@@ -1196,14 +1194,14 @@
 
 	if(d == nil || wbuf == nil || wbufsize == 0)
 		return 0;
-	buf = getdataspanat(d, offset/Maxspansize, Bwritable);
+	buf = getdatablkat(d, offset/Rawblocksize, Bwritable);
 	if(buf == nil)
 		return -1;
-	n = min(Maxspansize, wbufsize);
+	n = min(Rawblocksize, wbufsize);
 	memcpy(buf->io->buf, wbuf, n);
 	putbuf(buf);
 	return n;
-}
+}*/
 
 /* only for updating existing data */
 s32
@@ -1210,9 +1208,8 @@
 update(Dentry *d, u64 /* dblkno */, char *wbuf, s32 wbufsize, u64 offset)
 {
 	Iobuf *buf;
-	s32 howmuch, nblocks;
+	s32 howmuch;
 	u64 blkno, to;
-	Spanid s;
 
 	if(d == nil || wbuf == nil || wbufsize == 0)
 		return 0;
@@ -1225,20 +1222,18 @@
 		overlay data
 	 */
 
-	rel2abs(d, offset/Maxspansize, &s);
+	blkno = rel2abs(d, offset/Rawblocksize);
 	if(chatty9p > 1)
 	dprint("update rel2abs d->name %s d->size %llud reli offset %llud\n"
-				"	offset/Maxspansize %llud s.blkno %llud s.len %d\n",
-				d->name, d->size, offset, offset/Maxspansize, s.blkno, s.len);
-	blkno = s.blkno;
-	nblocks = s.len;
-	buf = getbufchk(blkno, nblocks, Bwritable, Tdata, d->qid.path);
+				"	offset/Blocksize %llud blkno %llud\n",
+				d->name, d->size, offset, offset/Blocksize, blkno);
+	buf = getbufchk(blkno, Bwritable, Tdata, d->qid.path);
 	if(buf == nil)
 		return -1;
 
 	/* overlay the new contents */
-	to = offset%Maxspansize;
-	howmuch = min(Maxspansize-to, wbufsize);
+	to = offset%Blocksize;
+	howmuch = min(Blocksize-to, wbufsize);
 	memcpy(buf->io->buf+to, wbuf, howmuch);
 	putbuf(buf);
 	return howmuch;
@@ -1247,10 +1242,9 @@
 s32
 append(Dentry *d, u64 dblkno, char *wbuf, s32 wbufsize)
 {
-	Iobuf *buf, *nbuf;
-	s32 howmuch, oldnblocks, newnblocks, nblocks;
-	u64 blkno, nblkno, lastspansize;
-	Spanid s;
+	Iobuf *buf;
+	s32 howmuch;
+	u64 blkno, lastblksize;
 
 	if(d == nil || wbuf == nil || wbufsize == 0)
 		return 0;
@@ -1257,96 +1251,55 @@
 	if(chatty9p > 1)
 		dprint("append wbufsize %d\n", wbufsize);
 
-	if((lastspansize=d->size%Maxspansize) == 0){
-		/* last extent is full, use a new extent */
+	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"
-				" d->size/Maxspansize %llud\n",
-				d->name, d->size, d->size/Maxspansize);
-		nblocks = min(Maxspanlen, (wbufsize+sizeof(Tag))/Rawblocksize);
-		if((wbufsize+sizeof(Tag))%Rawblocksize > 0)
-			nblocks++;
+				" d->size/Blocksize %llud\n",
+				d->name, d->size, d->size/Blocksize);
 
-		buf = allocblocks(nblocks, Tdata, d->qid.path);
+		buf = allocblock(Tdata, d->qid.path);
 		if(buf == nil)
 			return -1;
 		blkno = buf->blkno;
-		howmuch = min((nblocks*Rawblocksize)-sizeof(Tag), wbufsize);
+		howmuch = min(Blocksize, wbufsize);
 		memcpy(buf->io->buf, wbuf, howmuch);
 		putbuf(buf);
 
-		if(addrelative(d, dblkno, d->size/Maxspansize, blkno,nblocks) == 0){
-			freeblocks(blkno, nblocks, Tdata, d->qid.path);
+		if(addrelative(d, dblkno, d->size/Blocksize, blkno) == 0){
+			freeblock(blkno, Tdata, d->qid.path);
 			return -2;
 		}
 		return howmuch;
 	}else{
-		/* last Span is partially full */
+		/* last block is partially full, fill it up */
 		/*
-		get the old Span and the new Span
+		get the old block and the new Span
 		copy from the old Span to the new
 		addrelative the new Span
 		free the old Span */
 
-		rel2abs(d, d->size/Maxspansize, &s);
-		blkno = s.blkno;
-		oldnblocks = s.len;
-		if(s.len == 0)
-			panic("append update rel2abs s.len == 0"
+		blkno = rel2abs(d, d->size/Blocksize);
+		if(blkno == 0)
+			panic("append update rel2abs blkno == 0"
 					" d->name %s reli d->size %llud"
-					" d->size/Maxspansize %llud s.blkno %llud s.len %d\n",
-					d->name, d->size, d->size/Maxspansize, s.blkno, s.len);
+					" d->size/Blocksize %llud s.blkno %llud\n",
+					d->name, d->size, d->size/Blocksize, blkno);
 		if(chatty9p > 1)
 		dprint("append update rel2abs d->name %s reli d->size %llud"
-				" d->size/Maxspansize %llud s.blkno %llud s.len %d\n",
-				d->name, d->size, d->size/Maxspansize, s.blkno, s.len);
-		buf = getbufchk(blkno, oldnblocks, Bwritable, Tdata, d->qid.path);
+				" d->size/Blocksize %llud blkno %llud\n",
+				d->name, d->size, d->size/Blocksize, blkno);
+		buf = getbufchk(blkno, Bwritable, Tdata, d->qid.path);
 		if(buf == nil)
 			return -1;
 
-		if(lastspansize+wbufsize >= Maxspansize)
-			newnblocks = Maxspanlen;
-		else{
-			newnblocks = (lastspansize+wbufsize+sizeof(Tag))/Rawblocksize;
-			if((lastspansize+wbufsize+sizeof(Tag))%Rawblocksize > 0)
-				newnblocks++;
-		}
 
-		/* Filling up the old Span. No new blocks are added. */
-		if(oldnblocks == newnblocks){
-			howmuch = min(Maxspansize-lastspansize, wbufsize);
-			if(chatty9p > 1)
-			dprint("fill lastspansize %llud nblocks %llud howmuch %llud\n",
-					lastspansize, newnblocks, howmuch);
-			memcpy(buf->io->buf+lastspansize, wbuf, howmuch);
-			putbuf(buf);
-			return howmuch;
-		}
-
-		nbuf = allocblocks(newnblocks, Tdata, d->qid.path);
-		if(nbuf == nil){
-			putbuf(buf);
-			return -1;
-		}
-		nblkno = nbuf->blkno;
-		memcpy(nbuf->io->buf, buf->io->buf, lastspansize);
-		howmuch = min(Maxspansize-lastspansize, wbufsize);
+		howmuch = min(Blocksize-lastblksize, wbufsize);
 		if(chatty9p > 1)
-		dprint("update lastspansize %llud newnblocks %llud"
-				" nblkno %llud howmuch %llud\n",
-				lastspansize, newnblocks, nblkno, howmuch);
-		memcpy(nbuf->io->buf+lastspansize, wbuf, howmuch);
-		// if(chatty9p > 1)
-		//	dprint("append contents: %s\n", nbuf->io->buf);
-		putbuf(nbuf);
+		dprint("fill lastblksize %llud howmuch %llud\n",
+				lastblksize, howmuch);
+		memcpy(buf->io->buf+lastblksize, wbuf, howmuch);
 		putbuf(buf);
-
-		/* rel2abs() rlock's while reading */
-		if(addrelative(d, dblkno, d->size/Maxspansize, nblkno,newnblocks) == 0){
-			freeblocks(nblkno, newnblocks, Tdata, d->qid.path);
-			return -2;
-		}
-		freeblocks(blkno, oldnblocks, Tdata, d->qid.path);
 		return howmuch;
 	}
 }
@@ -1360,7 +1313,7 @@
 
 	if(d == nil || size <= 0)
 		return 0;
-	n = min(size, Maxspansize - d->size%Maxspansize);
+	n = min(size, Blocksize - d->size%Blocksize);
 	buf = emalloc9p(n);
 	n = append(d, dblkno, buf, n);
 	free(buf);
@@ -1386,7 +1339,7 @@
 	s32 n;
 	Iobuf *dbuf;
 
-	dbuf = getbufchk(dblkno, 1, Bwritable, Tdentry, qpath);
+	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 		return 0;
 	d = &dbuf->io->d;
--- a/all.h
+++ b/all.h
@@ -73,8 +73,8 @@
 
 /* Iobuf routines - contents of the blocks in memory */
 int		checktag(Iobuf *p, u16 tag, u64 qpath);
-Iobuf*	getbuf(u64 blkno, u16 len, u8 readonly, u8 freshalloc);
-Iobuf*	getbufchk(u64 blkno, u16 len, u8 readonly, int tag, u64 qpath);
+Iobuf*	getbuf(u64 blkno, u8 readonly, u8 freshalloc);
+Iobuf*	getbufchk(u64 blkno, u8 readonly, int tag, u64 qpath);
 void	iobufinit(void);
 void	putbuf(Iobuf *p);
 void	putbuffree(Iobuf *p);
@@ -88,15 +88,15 @@
 u64		pendingwrites(void);
 
 /* routines to manipulate the contents */
-Iobuf*	allocblocks(u16 len, int tag, u64 qpath);
+Iobuf*	allocblock(int tag, u64 qpath);
 void	freeblockbuf(Iobuf *buf);
-void	freeblocks(u64 blkno, u16 len, u16 tag, u64 qpath);
+void	freeblock(u64 blkno, u16 tag, u64 qpath);
 void	fsok(int ok);
 void	init(int doream);
 u64		newqpath();
 u64		nperiblock(u16 tag);
 void	ream(u64 size);
-void	rel2abs(Dentry *d, u64 reli, Spanid *s);
+u64	rel2abs(Dentry *d, u64 reli);
 void	rmfile(u64 qpath, u64 dblkno);
 void	rmdirectory(u64 qpath, u64 dblkno);
 void	rootream(void);
@@ -107,8 +107,8 @@
 Tlock*	tlocked(Iobuf*, Dentry*);
 
 /* dentry routines */
-u64 	addrelative(Dentry *d, u64 dblkno, u64 reli, u64 blkno, u16 len);
-Iobuf*	getdataspanat(Dentry *d, u64 reli, int flags);
+u64 	addrelative(Dentry *d, u64 dblkno, u64 reli, u64 blkno);
+Iobuf*	getdatablkat(Dentry *d, u64 reli, int flags);
 void	loadfrees(u64 dblkno);
 s32		readfile(u64 dblkno, u64 qpath, char *rbuf, s32 rbufsize, u64 offset);
 s32		readfilesize(u64 dblkno, u64 qpath);
--- a/blk.c
+++ b/blk.c
@@ -4,15 +4,6 @@
 #include "fns.h"
 
 void
-showind0(int fd, u8 *buf)
-{
-	int j;
-	Spanid *s;
-
-	for(j = 0, s=(Spanid*)buf; j<Nspanidperblock; j++)
-		fprint(fd, "	%d %llud %d\n", j, s[j].blkno, s[j].len);
-}
-void
 showind(int fd, u8 *buf)
 {
 	int j;
@@ -40,8 +31,8 @@
 	fprint(fd, "gid %d\n", d->gid);
 	fprint(fd, "muid %d\n", d->muid);
 	fprint(fd, "direct spans\n");
-	for(j = 0; j<Ndspanid; j++)
-		fprint(fd, "	%d %llud %d\n", j, d->dspans[j].blkno, d->dspans[j].len);
+	for(j = 0; j<Ndblock; j++)
+		fprint(fd, "	%d %llud\n", j, d->dblocks[j]);
 	fprint(fd, "indirect blocks\n");
 	for(j = 0; j<Niblock; j++)
 		fprint(fd, "	%d %llud\n", j, d->iblocks[j]);
@@ -93,9 +84,7 @@
 		showsuper(fd, buf+sizeof(Tag));
 	}else if(t->type == Tdata){
 		showdata(fd, buf+sizeof(Tag));
-	}else if(t->type == Tind0){
-		showind0(fd, buf+sizeof(Tag));
-	}else if(t->type > Tind0 && t->type < Maxtind){
+	}else if(t->type >= Tind0 && t->type < Maxtind){
 		showind(fd, buf+sizeof(Tag));
 	}else if(t->type != 0 || t->path != 0 || t->dirty != 0 || t->len != 0){
 		fprint(fd, "unknown tag type %d path %llud\n", t->type, t->path);
--- a/block.c
+++ b/block.c
@@ -46,7 +46,7 @@
 		print("Dentry size %d\n", sizeof(Dentry));
 	}
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	showblock(1, buf);
 	exits(0);
 }
--- a/chktag.c
+++ b/chktag.c
@@ -43,7 +43,7 @@
 
 	reli = atoll(argv[0]);
 	print("--- reli %llud ---\n", reli);
-	if(reli < Ndspanid){
+	if(reli < Ndblock){
 		print("Direct span %llud\n", reli);
 	}else{
 		tag = rel2tind(reli);
--- a/config.c
+++ b/config.c
@@ -8,7 +8,7 @@
 	char *tokens[128], cfg[Blocksize], *nl;
 	s32 n, i;
 
-	buf = getbufchk(dblkno, 1, Breadonly, Tdata, Qpconfig);
+	buf = getbufchk(dblkno, Breadonly, Tdata, Qpconfig);
 	if(buf == nil)
 		panic("cannot find config file in %llud block\n", dblkno);
 	memcpy(cfg, buf->io->buf, Blocksize);
@@ -91,7 +91,7 @@
 	Iobuf *buf;
 	s32 n;
 
-	buf = getbufchk(bno, 1, Bwritable, Tdata, Qpconfig);
+	buf = getbufchk(bno, Bwritable, Tdata, Qpconfig);
 	if(buf == nil)
 		panic("cannot write config");
 	n = snprint((s8*)buf->io->buf, Blocksize,
--- a/dat.h
+++ b/dat.h
@@ -30,7 +30,7 @@
 		using small numbers for testing
 		using Nbuckets=2 for testing.
 
-	Size of buffer cache = Nbuckets * Ncollisions * Maxspansize
+	Size of buffer cache = Nbuckets * Ncollisions * Rawblocksize
 		= 256 * 10 * 1MiB = 2.5GiB
 	 */
 	Nbuckets = 256,	/* number of Hiob */
@@ -67,9 +67,9 @@
  * The very first block (index = 0) has the magic written at offset 256.
  */
 enum {
-	Rawblocksize= 512,	/* real block size */
-	Ndspanid	= 24,	/* number of direct Spanid identifiers in a Dentry */
-	Niblock		= 4,	/* max depth of indirect blocks */
+	Rawblocksize= 512ULL,	/* real block size */
+	Ndblock		= 32,	/* number of direct blocks in a Dentry */
+	Niblock		= 6,	/* max depth of indirect blocks */
 	/* from tests/sizes.c, this provides 12M data spans */
 
 	/* global block numbers. The bkp contents locations are calculated by ream() */
@@ -157,22 +157,6 @@
 };
 
 /* DONT TOUCH, this is the disk structure */
-/* code gets less confusing when we store the length of
-	the extent in the dentry. If not, we have to keep
-	checking if the data extent is the last extent
-	for each extent. This makes the code more convoluted
-	as we need to track the file size any time we work on any
-	data extent. Another option is to use the 64th bit as
-	a flag to indicate if this is the last extent. That
-	appears hacky. The name Extent is used by extents.h, hence,
-	using Spanid. */
-struct Spanid	/* Spanid identifier */
-{
-	u64 blkno;	/* starting block number */
-	u16 len;	/* number of blocks */
-};
-
-/* DONT TOUCH, this is the disk structure */
 /*
  * 1 dentry per block
  * no access time
@@ -188,7 +172,7 @@
 	s16 uid;
 	s16 gid;
 	s16 muid;
-	Spanid dspans[Ndspanid];	/* direct Spanids */
+	u64 dblocks[Ndblock];	/* direct blocks */
 						/* Tag.type = Tdentry for directories and Tdata for files */
 	u64 iblocks[Niblock];	/* indirect blocks */
 };
@@ -199,19 +183,15 @@
  * derived constants
  * Ndentriesperblock number of Dentry's in a block
  * Nindperblock number of block pointers in a block
- * Nspanidperblock number of Spanid identifiers in a Tind0 block
  */
 enum {
 	Blocksize	= Rawblocksize - sizeof(Tag),
 	Namelen		= (Blocksize-sizeof(Dentry1)),/* max size of file name components */
 
-	Iounit		= MAXRPC-sizeof(Tag), /* in bytes */
-	Maxspanlen	= MAXRPC/Rawblocksize,	/* in blocks */
-	Maxspansize	= (Maxspanlen*Rawblocksize)-sizeof(Tag), /* in bytes */
+	Iounit		= MAXRPC, /* in bytes */
 
 	Ndentryperblock	= 1, /* Blocksize / sizeof(Dentry), */
-	Nindperblock	= Blocksize / sizeof(u64),
-	Nspanidperblock	= Blocksize / sizeof(Spanid),
+	Nindperblock	= Blocksize / sizeof(u64), /* number of pointers per block */
 };
 
 #pragma pack on
@@ -227,7 +207,6 @@
 	union{
 		u8 buf[Blocksize];
 		u64 bufa[Nindperblock];
-		Spanid s[Nspanidperblock];
 		Dentry d;
 	};
 };
@@ -379,7 +358,9 @@
 	Tind0,		/* points to Tdata blocks for files or Tdentry blocks for directories. */
 	Tind1,		/* points to Tind0 blocks */
 	Tind2,		/* points to Tind1 blocks */
-	Tind3,		/* list of Tind2 blocks. we can have a 92 GiB file */
+	Tind3,		/* list of Tind2 blocks */
+	Tind4,		/* list of Tind3 blocks */
+	Tind5,		/* list of Tind4 blocks */
 	Maxtind,	/* should be Tind0+Niblock */
 				/* gap for more indirect block depth in future */
 	MAXTAG,
--- a/dentry.c
+++ b/dentry.c
@@ -1,39 +1,35 @@
 #include	"all.h"
 
-void
-getindspan(u64 blkno, u64 reli, u16 tag, u64 path, Spanid *s)
+u64
+getindblk(u64 blkno, u64 reli, u16 tag, u64 path)
 {
 	Iobuf *buf;
-	u64 n;
+	u64 n, b;
 
 	if(chatty9p > 2)
-	dprint("getindspan blkno %llud reli %llud tag %d path %llud\n",
+	dprint("getindblk blkno %llud reli %llud tag %d path %llud\n",
 			blkno, reli, tag, path);
-	if(tag > Tmaxind || reli > nperindunit(tag+1)){
+	if(tag < Tind0 || tag > Tmaxind || reli > nperindunit(tag+1)){
 		panic("devmafs: getindblock() wrong reli %llud for %s\n",
 			reli, tagnames[tag]);
-		s->blkno = s->len = 0;
-		return;
+		return 0;
 	}
 	if(blkno == 0){
-		s->blkno = s->len = 0;
-		return;
+		return 0;
 	}
-	if((buf = getbufchk(blkno, 1,Breadonly, tag, path)) == nil){
+	if((buf = getbufchk(blkno, Breadonly, tag, path)) == nil){
 		dprint("%s",errstring[Ephase]);
-		s->blkno = s->len = 0;
-		return;
+		return 0;
 	}
 	if(tag > Tind0){
 		n = nperindunit(tag);
-		getindspan(buf->io->bufa[reli/n],
-						reli%n, tag-1, path, s);
+		b = getindblk(buf->io->bufa[reli/n],
+						reli%n, tag-1, path);
 	}else{
-		s->blkno = buf->io->s[reli].blkno;
-		s->len = buf->io->s[reli].len;
+		b = buf->io->bufa[reli];
 	}
 	putbuf(buf);
-	return;
+	return b;
 }
 
 /*
@@ -50,39 +46,36 @@
 	The Iobuf holding the d should be rlock'ed else it creates
 	inconsistencies.
  */
-void
-rel2abs(Dentry *d, u64 reli, Spanid *s)
+u64
+rel2abs(Dentry *d, u64 reli)
 {
 	u8 tag;
 
-	if(reli < Ndspanid){
-		s->blkno = d->dspans[reli].blkno;
-		s->len = d->dspans[reli].len;
-		return;
-	}
+	if(reli < Ndblock)
+		return d->dblocks[reli];
 
 	tag = rel2tind(reli);
-	getindspan(d->iblocks[tag-Tind0], reli-tagstartreli(tag), tag, d->qid.path, s);
+	return getindblk(d->iblocks[tag-Tind0], reli-tagstartreli(tag), tag, d->qid.path);
 }
 
 u64
-updateindblock(u64 indblkno, u64 reli, u16 tag, u64 path, u64 blkno, u16 len)
+updateindblock(u64 indblkno, u64 reli, u16 tag, u64 path, u64 blkno)
 {
 	Iobuf *buf;
 	u64 n, childindblkno;
 
-	if(tag > Tmaxind || reli > nperindunit(tag+1)){
-		print("devmafs: updateindblock() wrong reli %llud for %s\n", reli, tagnames[tag]);
+	if(tag < Tind0 || tag > Tmaxind || reli > nperindunit(tag+1)){
+		panic("devmafs: updateindblock() wrong reli %llud for %s\n", reli, tagnames[tag]);
 		return 0;
 	}
 	if(indblkno == 0){
-		if((buf = allocblocks(1, tag, path)) == nil){
+		if((buf = allocblock(tag, path)) == nil){
 			dprint("%s",errstring[Efull]);
 			return 0;
 		}
 		indblkno = buf->blkno;
 	}else{
-		if((buf = getbufchk(indblkno, 1, Bwritable, tag, path)) == nil){
+		if((buf = getbufchk(indblkno, Bwritable, tag, path)) == nil){
 			dprint("updateindblock: %s",errstring[Ephase]);
 			return 0;
 		}
@@ -101,25 +94,24 @@
 		n = nperindunit(tag);
 		if(reli/n >= Nindperblock){
 			panic("updateindblock invalid reli: indblkno %llud reli %llud tag %s"
-					" directblkno %llud len %ud reli/n %llud nperindunit(tag) %d\n",
-					indblkno, reli, tagnames[tag], blkno, len, reli/n, Nindperblock);
+					" directblkno %llud reli/n %llud nperindunit(tag) %d\n",
+					indblkno, reli, tagnames[tag], blkno, reli/n, Nindperblock);
 			dprint("%s",errstring[Ephase]);
 			return 0;
 		}
 		childindblkno = updateindblock(buf->io->bufa[reli/n],
 								reli%n, tag-1, path,
-								blkno, len);
+								blkno);
 		buf->io->bufa[reli/n] = childindblkno;
 	}else{
-		if(reli >= Nspanidperblock){
+		if(reli >= Nindperblock){
 			panic("updateindblock invalid reli: indblkno %llud reli %llud tag %s"
-					" directblkno %llud len %ud Nspanidperblock %d\n",
-					indblkno, reli, tagnames[tag], blkno, len, Nspanidperblock);
+					" directblkno %llud Nindperblock %d\n",
+					indblkno, reli, tagnames[tag], blkno, Nindperblock);
 			dprint("%s",errstring[Ephase]);
 			return 0;
 		}
-		buf->io->s[reli].blkno = blkno;
-		buf->io->s[reli].len = len;
+		buf->io->bufa[reli] = blkno;
 	}
 	putbuf(buf);
 	return indblkno;
@@ -126,7 +118,7 @@
 }
 
 /*
-	store Spanid at the relitive location, reli, of the Dentry in dbuf.
+	store the block number at the relitive location, reli, of the Dentry in dbuf.
 	The contents buffer is already stored and we store that from the leaf
 	to the root. If there is a crash during this process, there are no
 	dangling unfilled slots below.
@@ -134,27 +126,26 @@
 	dbuf should be wlock'ed.
  */
 u64
-addrelative(Dentry *d, u64 dblkno, u64 reli, u64 blkno, u16 len)
+addrelative(Dentry *d, u64 dblkno, u64 reli, u64 blkno)
 {
 	u64 path, nblkno;
 	u16 tag;
 
 	if(chatty9p > 2)
-	dprint("addrelative %llud:%s reli %llud blkno %llud len %llud\n",
-			dblkno, d->name, reli, blkno, len);
+	dprint("addrelative %llud:%s reli %llud blkno %llud\n",
+			dblkno, d->name, reli, blkno);
 
 	path = d->qid.path;
-	if(reli < Ndspanid){
-		d->dspans[reli].blkno = blkno;
-		d->dspans[reli].len = len;
+	if(reli < Ndblock){
+		d->dblocks[reli] = blkno;
 		return blkno;
 	}
 
 	tag = rel2tind(reli);
 	if(chatty9p > 2)
-	dprint("	reli %llud tag %s d->iblocks[tag-Tind0] %llud blkno %llud len %llud\n",
-			reli, tagnames[tag], d->iblocks[tag-Tind0], blkno, len);
-	if((nblkno = updateindblock(d->iblocks[tag-Tind0], reli-tagstartreli(tag), tag, path, blkno, len)) == 0){
+	dprint("	reli %llud tag %s d->iblocks[tag-Tind0] %llud blkno %llud\n",
+			reli, tagnames[tag], d->iblocks[tag-Tind0], blkno);
+	if((nblkno = updateindblock(d->iblocks[tag-Tind0], reli-tagstartreli(tag), tag, path, blkno)) == 0){
 			dprint("%s",errstring[Ephase]);
 			return 0;
 		}
@@ -171,33 +162,30 @@
 	and removed by it on a crash.
  */
 void
-freeindblocks(u64 iblkno, u16 tag, u64 qpath, u16 directtag)
+freeindblock(u64 iblkno, u16 tag, u64 qpath, u16 directtag)
 {
 	Iobuf *ibuf;
 	int i;
 	u64 blkno;
-	u16 len;
 
 	if(iblkno == 0)
 		return;
-	ibuf = getbufchk(iblkno, 1, Bwritable, tag, qpath);
+	ibuf = getbufchk(iblkno, Bwritable, tag, qpath);
 	if(ibuf == nil)
 			dprint("%s",errstring[Ephase]);
 	if(tag == Tind0)
-		for(i=Nspanidperblock-1; i >= 0; i--){
-			blkno = ibuf->io->s[i].blkno;
+		for(i=Nindperblock-1; i >= 0; i--){
+			blkno = ibuf->io->bufa[i];
 			if(blkno == 0)
 				continue;
-			len = ibuf->io->s[i].len;
-			freeblocks(blkno, len, directtag, qpath);
-			ibuf->io->s[i].blkno = 0;
-			ibuf->io->s[i].len = 0;
+			freeblock(blkno, directtag, qpath);
+			ibuf->io->bufa[i] = 0;
 		}
 	else
 		for(i=Nindperblock-1; i >= 0; i--){
 			if(ibuf->io->bufa[i] == 0)
 				continue;
-			freeindblocks(ibuf->io->bufa[i], tag-1, qpath, directtag);
+			freeindblock(ibuf->io->bufa[i], tag-1, qpath, directtag);
 			ibuf->io->bufa[i] = 0;
 		}
 	freeblockbuf(ibuf);
@@ -212,8 +200,8 @@
 
 	d = &dbuf->io->d;
 	memcpy(&d1, d, sizeof(Dentry));
-	for(i=0; i<Ndspanid; i++)
-		d->dspans[i] = (Spanid){0,0};
+	for(i=0; i<Ndblock; i++)
+		d->dblocks[i] = 0;
 	for(i=0;i<Niblock; i++)
 		d->iblocks[i] = 0;
 	d->size = 0;
@@ -224,12 +212,12 @@
 	for(i=Niblock-1; i >= 0; i--){
 		if(d1.iblocks[i] == 0)
 			continue;
-		freeindblocks(d1.iblocks[i], Tind0+i, d1.qid.path, Tdata);
+		freeindblock(d1.iblocks[i], Tind0+i, d1.qid.path, Tdata);
 	}
-	for(i=Ndspanid-1; i >= 0; i--){
-		if(d1.dspans[i].blkno == 0)
+	for(i=Ndblock-1; i >= 0; i--){
+		if(d1.dblocks[i] == 0)
 			continue;
-		freeblocks(d1.dspans[i].blkno, d1.dspans[i].len, Tdata, d1.qid.path);
+		freeblock(d1.dblocks[i], Tdata, d1.qid.path);
 	}
 }
 
@@ -248,7 +236,7 @@
 
 	if(qpath < Qpusers || dblkno == 0)
 		return;
-	dbuf = getbufchk(dblkno, 1, Bwritable, Tdentry, qpath);
+	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
 
@@ -276,7 +264,7 @@
 
 	if(qpath < Qpusers || dblkno == 0)
 		return;
-	dbuf = getbufchk(dblkno, 1, Bwritable, Tdentry, qpath);
+	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
 	memcpy(&d, &dbuf->io->d, sizeof(Dentry));
@@ -284,15 +272,15 @@
 	settag(dbuf, Tdentry, Qpnone);
 	putbuf(dbuf);
 
-	for(i=0; i<Ndspanid; i++){
-		if(d.dspans[i].blkno == 0)
+	for(i=0; i<Ndblock; i++){
+		if(d.dblocks[i] == 0)
 			continue;
-		freeblocks(d.dspans[i].blkno, d.dspans[i].len, Tdata, qpath);
+		freeblock(d.dblocks[i], Tdata, qpath);
 	}
 	for(i=0;i<Niblock; i++){
 		if(d.iblocks[i] == 0)
 			continue;
-		freeindblocks(d.iblocks[i], Tind0+i, qpath, Tdata);
+		freeindblock(d.iblocks[i], Tind0+i, qpath, Tdata);
 	}
 }
 
@@ -306,12 +294,11 @@
 	u64 blkno, reli;
 	int i;
 	u16 mode;
-	Spanid s;
 
 	if(qpath < Qpusers || dblkno == 0)
 		return;
 	/* clear the dentry to avoid links to removed content */
-	dbuf = getbufchk(dblkno, 1, Bwritable, Tdentry, qpath);
+	dbuf = getbufchk(dblkno, Bwritable, Tdentry, qpath);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
 	memcpy(&d, dbuf->io->buf, sizeof(Dentry));
@@ -325,11 +312,10 @@
 	 */
 	for(reli = 0, blkno = 1; blkno > 0; reli++){
 
-		rel2abs(&d, reli, &s);
-		if(s.blkno == 0)
+		if((blkno = rel2abs(&d, reli)) == 0)
 			break;
 
-		buf = getbuf(s.blkno, 1, Breadonly, Bused);
+		buf = getbuf(blkno, Breadonly, Bused);
 		child = &buf->io->d;
 		cqpath = child->qid.path;
 		mode = child->mode;
@@ -341,9 +327,9 @@
 			continue;
 
 		if(mode & DMDIR)
-			rmdirectory(cqpath, s.blkno);
+			rmdirectory(cqpath, blkno);
 		else
-			rmfile(cqpath, s.blkno);
+			rmfile(cqpath, blkno);
 	}
 
 	/*
@@ -350,15 +336,15 @@
 		free the chain of blocks to zero'ed dentries and
 		the zero'ed dentries
 	 */
-	for(i=0; i<Ndspanid; i++){
-		if(d.dspans[i].blkno == 0)
+	for(i=0; i<Ndblock; i++){
+		if(d.dblocks[i] == 0)
 			continue;
-		freeblocks(d.dspans[i].blkno, d.dspans[i].len, Tdentry, Qpnone);
+		freeblock(d.dblocks[i], Tdentry, Qpnone);
 	}
 	for(i=0;i<Niblock; i++){
 		if(d.iblocks[i] == 0)
 			continue;
-		freeindblocks(d.iblocks[i], Tind0+i, qpath, Tdentry);
+		freeindblock(d.iblocks[i], Tind0+i, qpath, Tdentry);
 	}
 }
 
@@ -416,9 +402,9 @@
 	u64 reli, idx;
 	Dentry *d, *ch;
 	Tag *cht;
-	Spanid s;
+	u64 blkno;
 
-	*dbuf = getbufchk(dblkno, 1, Breadonly, Tdentry, qpath);
+	*dbuf = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(*dbuf == nil)
 		return nil;
 	d = &(*dbuf)->io->d;
@@ -433,8 +419,8 @@
 	/* using idx to not include zero'ed out slots in our search */
 	for(reli = 0, idx = 0; ; reli++){
 
-		rel2abs(d, reli, &s);
-		if(s.blkno == 0){
+		
+		if((blkno = rel2abs(d, reli)) == 0){
 			putbuf(*dbuf);
 			*dbuf = nil;
 			return nil;
@@ -441,9 +427,9 @@
 		}
 		if(chatty9p>2)
 			dprint("searchdir reli %d s.blkno %llud s.len %d\n",
-					reli, s.blkno, s.len);
+					reli, blkno);
 
-		*buf = getbuf(s.blkno, s.len, Breadonly, Bused);
+		*buf = getbuf(blkno, Breadonly, Bused);
 		if(*buf == nil){
 			putbuf(*dbuf);
 			*dbuf = nil;
@@ -455,8 +441,8 @@
 		cht = (Tag*)(*buf)->io;
 		if(chatty9p > 2)
 			dprint("searchdir: dblkno %llud qpath %llud searchname %s searchidx %d"
-					" reli %llud s.blkno %llud s.len %d ch->qid.path %llud\n",
-					dblkno, qpath, searchname, searchidx, reli, s.blkno, s.len,
+					" reli %llud blkno %llud ch->qid.path %llud\n",
+					dblkno, qpath, searchname, searchidx, reli, blkno,
 					ch->qid.path);
 		if(checktag(*buf, Tdentry, ch->qid.path) == 0){
 			putbuf(*buf);
@@ -502,18 +488,17 @@
 	only for file contents. not for directory contents.
  */
 Iobuf *
-getdataspanat(Dentry *d, u64 reli, int flags)
+getdatablkat(Dentry *d, u64 reli, int flags)
 {
 	Iobuf *buf;
-	Spanid s;
+	u64 blkno;
 
 	/* rel2abs() rlock's while reading.
 	   not necessary, as the dbuf is locked anyway.
 	 */
-	rel2abs(d, reli, &s);
-	if(s.blkno == 0)
+	if((blkno = rel2abs(d, reli)) == 0)
 		return nil;
-	buf = getbufchk(s.blkno, s.len, flags, Tdata, d->qid.path);
+	buf = getbufchk(blkno, flags, Tdata, d->qid.path);
 	if(buf == nil){
 		putbuf(buf);
 		dprint("%s",errstring[Ephase]);
@@ -575,13 +560,13 @@
 	/* I cannot use truncatefile() below as it would
 		bfree() the blocks (which are already in the Extents frees)
 		and that would cause an inconsistency/panic */
-	dbuf = getbufchk(dblkno, 1, Bwritable, Tdentry, Qpfrees);
+	dbuf = getbufchk(dblkno, Bwritable, Tdentry, Qpfrees);
 	if(dbuf == nil)
 			dprint("%s",errstring[Ephase]);
 	d = &dbuf->io->d;
 	d->size = 0;
-	for(i=0; i<Ndspanid; i++)
-		d->dspans[i] = (Spanid){0,0};
+	for(i=0; i<Ndblock; i++)
+		d->dblocks[i] = 0;
 	for(i=0;i<Niblock; i++)
 		d->iblocks[i] = 0;
 	d->mtime = nsec();
--- a/dev.c
+++ b/dev.c
@@ -20,11 +20,11 @@
 
 /* TODO proper error handling */
 int
-devread(u64 blkno, void *b, u16 len)
+devread(u64 blkno, void *b)
 {
 	int n;
 
-	if((n= pread(devfd, b, len*Rawblocksize, blkno*Rawblocksize)) != len*Rawblocksize)
+	if((n= pread(devfd, b, Rawblocksize, blkno*Rawblocksize)) != Rawblocksize)
 		panic("devread failed: %r\n");
 	/* print("devread i %d n %d\n", i, n); */
 	return n;
@@ -55,11 +55,11 @@
 */
 
 int
-devwrite(u64 blkno, void *b, u16 len)
+devwrite(u64 blkno, void *b)
 {
 	int n;
 
-	if((n = pwrite(devfd, b, len*Rawblocksize, blkno*Rawblocksize)) != len*Rawblocksize)
+	if((n = pwrite(devfd, b, Rawblocksize, blkno*Rawblocksize)) != Rawblocksize)
 		panic("devwrite failed: %r\n");
 	return n;
 }
--- a/extents.c
+++ b/extents.c
@@ -428,9 +428,9 @@
 	return oldblkno;
 }
 
-/* allocate n blocks and return that block number */
+/* allocate a block and return that block number */
 u64
-balloc(Extents *es, u64 n)
+balloc(Extents *es)
 {
 	Extent *e;
 	u64 blkno;
@@ -444,7 +444,7 @@
 		snprint(msg, 64, "balloc() %llud blocks:\n", n);
 		showextents(msg, es);
 	}*/
-	for(e = smallest(es); e != nil && e->len < n; e = e->big)
+	for(e = smallest(es); e != nil; e = e->big)
 		;
 	if(e == nil){
 		// snprint(msg, 64, "balloc() %llud blocks:\n", n);
@@ -451,10 +451,10 @@
 		// showextents(msg, es);
 		panic("balloc: out of free blocks");
 	}
-	else if(e->len == n)
+	else if(e->len == 1)
 		blkno = pluck(es, e);
 	else /* found something bigger */
-		blkno = slice(es, e, n);
+		blkno = slice(es, e, 1);
 
 	qunlock(&es->el);
 	return blkno;
--- a/extents.h
+++ b/extents.h
@@ -36,7 +36,7 @@
 s32	saveextents(Extents *es, s8 *buf, u32 nbuf);
 s32	loadextents(Extents *es, s8 *buf, u32 nbuf);
 
-u64	 balloc(Extents *es, u64 n);
+u64	 balloc(Extents *es);
 void bfree(Extents *es, u64 blkno, u64 len);
 u64	 nfrees(Extents *es);
 
--- a/find.c
+++ b/find.c
@@ -105,21 +105,18 @@
 	Tag *t, *ct;
 	u64 cblkno, *bufa;
 	int i;
-	Spanid *s;
-	u16 len;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	if(checkvalid(blkno, t, tag, qpath)){
 		if(t->type == Tind0){
-			s = (Spanid*)(buf+sizeof(Tag));
-			for(i = 0; i<Nspanidperblock; i++){
-				cblkno = s[i].blkno;
-				len = s[i].len;
+			bufa = (u64*)(buf+sizeof(Tag));
+			for(i = 0; i<Nindperblock; i++){
+				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				cbuf = malloc(len*Rawblocksize);
-				devread(cblkno, cbuf, len);
+				cbuf = malloc(Rawblocksize);
+				devread(cblkno, cbuf);
 				ct = (Tag*)cbuf;
 				if(ct->type == Tdentry && ct->type == bottomtag)
 					/* another directory */
@@ -135,7 +132,7 @@
 				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				devread(cblkno, cbuf, 1);
+				devread(cblkno, cbuf);
 				/* check tag */
 				walkindir(cblkno, tag-1,  bottomtag, qpath, depth);
 			}
@@ -174,9 +171,8 @@
 	u64 cblkno;
 	int i;
 	u8 isdir;
-	u16 len;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	d = (Dentry*)(buf+sizeof(Tag));
 	isdir = (d->mode & DMDIR) > 0;
@@ -193,13 +189,12 @@
 	}/*else
 		print("%llud\n", blkno);*/
 	addparent(depth, blkno);
-	for(i = 0; i<Ndspanid; i++){
-		cblkno = d->dspans[i].blkno;
-		len = d->dspans[i].len;
+	for(i = 0; i<Ndblock; i++){
+		cblkno = d->dblocks[i];
 		if(cblkno == 0)
 			return;
-		cbuf = malloc(len*Rawblocksize);
-		devread(cblkno, cbuf, len);
+		cbuf = malloc(Rawblocksize);
+		devread(cblkno, cbuf);
 		ct = (Tag*)cbuf;
 		if(isdir)
 			walkdentry(cblkno, depth+1);
@@ -212,7 +207,7 @@
 		cblkno = d->iblocks[i];
 		if(cblkno == 0)
 			return;
-		devread(cblkno, cbuf, 1);
+		devread(cblkno, cbuf);
 		ct = (Tag*)cbuf;
 		if(ct->type == Tind0+i){
 			walkindir(cblkno, Tind0+i, isdir ? Tdentry : Tdata, d->qid.path, depth);
--- a/fns.h
+++ b/fns.h
@@ -8,9 +8,9 @@
 
 /* actual device i/o routines */
 u64	devinit(char *devfile);
-int	devread(u64 blkno, void *b, u16 len);
+int	devread(u64 blkno, void *b);
 u64	devsize(void);
-int	devwrite(u64 blkno, void *b, u16 len);
+int	devwrite(u64 blkno, void *b);
 int devwritedirtyclear(u64 blkno);
 
 /* show blocks */
--- a/free.c
+++ b/free.c
@@ -77,19 +77,19 @@
 	u8 buf[Rawblocksize];
 	Tag *t;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	return checkvalid(blkno, t, tag, qpath);
 }
 
 void
-loadfreeextents(u64 blkno, u16 len)
+loadfreeextents(u64 blkno)
 {
 	s8 *buf;
 
-	buf = emalloc(len*Rawblocksize);
-	devread(blkno, buf, len);
-	loadextents(&frees, buf+sizeof(Tag), (len*Rawblocksize)-sizeof(Tag));
+	buf = emalloc(Rawblocksize);
+	devread(blkno, buf);
+	loadextents(&frees, buf+sizeof(Tag), (Rawblocksize)-sizeof(Tag));
 	free(buf);
 }
 
@@ -99,21 +99,18 @@
 	u8 buf[Rawblocksize], cbuf[Rawblocksize];
 	Tag *t;
 	u64 cblkno, *bufa;
-	Spanid *s;
-	u16 len;
 	int i;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	if(checkvalid(blkno, t, tag, qpath)){
 		if(t->type == Tind0){
-			s = (Spanid*)(buf+sizeof(Tag));
-			for(i = 0; i<Nspanidperblock; i++){
-				cblkno = s[i].blkno;
-				len = s[i].len;
+			bufa = (u64*)(buf+sizeof(Tag));
+			for(i = 0; i<Nindperblock; i++){
+				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				loadfreeextents(cblkno, len);
+				loadfreeextents(cblkno);
 			}
 		}else{
 			bufa = (u64*)(buf+sizeof(Tag));
@@ -121,7 +118,7 @@
 				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				devread(cblkno, cbuf, 1);
+				devread(cblkno, cbuf);
 				/* check tag */
 				walkindir(cblkno, tag-1,  bottomtag, qpath);
 			}
@@ -138,9 +135,8 @@
 	Tag *t;
 	u64 cblkno;
 	int i;
-	u16 len;
 
-	devread(dblkno, buf, 1);
+	devread(dblkno, buf);
 	t = (Tag*)buf;
 	d = (Dentry*)(buf+sizeof(Tag));
 	size = d->size;
@@ -148,18 +144,17 @@
 		panic("loadfreeextents size == 0");
 
 	if(checkvalid(dblkno, t, Tdentry, d->qid.path)){
-		for(i = 0; i<Ndspanid; i++){
-			cblkno = d->dspans[i].blkno;
-			len = d->dspans[i].len;
+		for(i = 0; i<Ndblock; i++){
+			cblkno = d->dblocks[i];
 			if(cblkno == 0)
 				return;
-			loadfreeextents(cblkno, len);
+			loadfreeextents(cblkno);
 		}
 		for(i = Tind0; i<Niblock+Tind0; i++){
 			cblkno = d->iblocks[i];
 			if(cblkno == 0)
 				return;
-			devread(cblkno, cbuf, 1);
+			devread(cblkno, cbuf);
 			walkindir(cblkno, i, Tdata, Qpfrees);
 		}
 	}
--- a/iobuf.c
+++ b/iobuf.c
@@ -9,14 +9,10 @@
    hp must be locked
  */
 Iobuf *
-newbuf(Hiob *hp, u16 len)
+newbuf(Hiob *hp)
 {
 	Iobuf *p, *q;
 
-	if(len == 0){
-		panic("newbuf len == 0 caller %#p\n",
-				getcallerpc(&hp));
-	}
 	p = emalloc9p(sizeof(Iobuf));
 
 	q = hp->link;
@@ -31,8 +27,7 @@
 		p->back = p;
 	}
 	p->blkno = 0;
-	p->len   = len;
-	p->xiobuf = emalloc9p(len*Rawblocksize);
+	p->xiobuf = emalloc9p(Rawblocksize);
 	return p;
 }
 
@@ -53,22 +48,18 @@
 	Hiob.link->back is the oldest buffer that will be reused first.
  */
 Iobuf *
-getbuf(u64 blkno, u16 len, u8 readonly, u8 freshalloc)
+getbuf(u64 blkno, u8 readonly, u8 freshalloc)
 {
 	Hiob *hp;
 	Iobuf *s, *p;
 	s8 ncollisions;
 
-	if(len == 0){
-		panic("getbuf len == 0 blkno %llud readonly %d caller %#p\n",
-				blkno, readonly, getcallerpc(&blkno));
-	}
 	hp = &hiob[blkno%nbuckets];
 
 	if(chatty9p > 4)
-		dprint("getbuf blkno %llud len %d blkno%%nbuckets %llud pc 0x%p"
+		dprint("getbuf blkno %llud blkno%%nbuckets %llud pc 0x%p"
 				" hiob 0x%p hp 0x%p readonly %d\n",
-			blkno, len, blkno%nbuckets, getcallerpc(&blkno),
+			blkno, blkno%nbuckets, getcallerpc(&blkno),
 			hiob, hp, readonly);
 	qlock(hp);
 	s = hp->link;
@@ -94,33 +85,10 @@
 			if(chatty9p > 4)
 				dprint("	in cache, after qunlock(hp) hp 0x%p blkno %llud\n",
 						hp, blkno);
-			if(p->len != len){
+			if(readonly){
 				if(chatty9p > 4)
-				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);
-				free(p->xiobuf);
-				p->xiobuf = emalloc9p(len*Rawblocksize);
-				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);
+					dprint("	in cache iobuf 0x%p has blkno %llud .."
+							" rlock()\n", p, blkno);
 				rlock(p);
 			}else{
 				wlock(p);
@@ -148,16 +116,10 @@
 					wunlock(p);
 					goto Another;
 				}
-				if(p->len != len){
-					free(p->xiobuf);
-					p->xiobuf = emalloc9p(len*Rawblocksize);
-					p->len = len;
-				}
 				hp->link = p;
 				if(chatty9p > 4)
-					dprint("	stealing iobuf 0x%p of %llud blocks"
-							" for blkno %llud len %llud\n",
-							p, p->len, blkno, len);
+					dprint("	stealing iobuf 0x%p for blkno %llud\n",
+							p, blkno);
 				goto found;	/* p is wlock() */
 			}
 			s = p;
@@ -168,7 +130,7 @@
 new:
 	if(chatty9p > 4)
 		dprint("	adding new Iobuf for blkno %llud\n", blkno);
-	p = newbuf(hp, len);
+	p = newbuf(hp);
 	if(chatty9p > 4)
 		dprint(" .. wlock() blkno %llud\n", blkno);
 	wlock(p);
@@ -180,7 +142,7 @@
 		dprint("	after qunlock(hp) hp 0x%p blkno %llud\n",
 				hp, blkno);
 	if(freshalloc == 0)
-		devread(blkno, p->xiobuf, len);
+		devread(blkno, p->xiobuf);
 	if(readonly){
 		if(chatty9p > 4)
 		dprint("new buffer: switching from wlock() to rlock() blkno %llud\n", blkno);
@@ -193,18 +155,13 @@
 }
 
 Iobuf *
-getbufchk(u64 blkno, u16 len, u8 readonly, int tag, u64 qpath)
+getbufchk(u64 blkno, u8 readonly, int tag, u64 qpath)
 {
 	Iobuf *b;
 
 	if(chatty9p > 4)
 		dprint("getbufchk caller pc 0x%p\n", getcallerpc(&blkno));
-	if(len == 0){
-		panic("getbufchk len == 0 blkno %llud readonly %d tag %d"
-				" qpath %llud caller %#p\n",
-				blkno, readonly, tag, qpath, getcallerpc(&blkno));
-	}
-	b = getbuf(blkno, len, readonly, Bused);
+	b = getbuf(blkno, readonly, Bused);
 	if(b != nil)
 		if(checktag(b, tag, qpath) == 0){
 			putbuf(b);
@@ -212,8 +169,8 @@
 		}
 	if(b->io == nil)
 		panic("b->io == nil blkno %llud readonly %d tag %d"
-				" qpath %llud b->blkno %llud %d caller %#p\n",
-				blkno, readonly, tag, qpath, b->blkno, b->len,
+				" qpath %llud b->blkno %llud caller %#p\n",
+				blkno, readonly, tag, qpath, b->blkno,
 				getcallerpc(&blkno));
 	return b;
 }
@@ -242,7 +199,7 @@
 		return;
 	}
 
-	buf = getbufchk(bno, 1, Bwritable, Tdata, qpath);
+	buf = getbufchk(bno, Bwritable, Tdata, qpath);
 	if(buf == nil){
 		panic("bkp: buf == nil\n");
 	}
@@ -271,12 +228,6 @@
 		dprint("%s\n", errstring[Ephase]);
 		return;
 	}
-	if(p->len == 0){
-		showbuf(p);
-		panic("putbuf p->len == 0 by %#p\n", getcallerpc(&p));
-		dprint("%s\n", errstring[Ephase]);
-		return;
-	}
 	
 	if(chatty9p > 4)
 		dprint("putbuf p->blkno %llud\n", p->blkno);
@@ -327,12 +278,6 @@
 		dprint("%s\n", errstring[Ephase]);
 		return;
 	}
-	if(p->len == 0){
-		showbuf(p);
-		panic("putbuffree p->len == 0 by %#p\n", getcallerpc(&p));
-		dprint("%s\n", errstring[Ephase]);
-		return;
-	}
 
 	if(chatty9p > 4)
 		dprint("putbuffree p->blkno %llud\n", p->blkno);
@@ -443,12 +388,12 @@
 		return;
 	}
 	dprint("showbuf p 0x%p ref %d readers %d writer %d"
-			" blkno %llud len %d"
+			" blkno %llud"
 			" fore 0x%p back 0x%p"
 			" xiobuf 0x%p"
 			" caller %#p\n",
 			p, p->ref, p->readers, p->writer,
-			p->blkno, p->len,
+			p->blkno,
 			p->fore, p->back,
 			p->xiobuf,
 			getcallerpc(&p));
--- a/mafs.c
+++ b/mafs.c
@@ -193,7 +193,7 @@
 maxsize(void)
 {
 	int i;
-	uvlong max = Ndspanid, ind;
+	uvlong max = Ndblock, ind;
 
 	dprint("maxsize direct spans max %llud\n", max);
 	for (i = 0; i < Niblock; i++) {
@@ -209,22 +209,16 @@
 printsizes(void)
 {
 	int i;
-	u64 spans, max;
+	u64 n, max;
 
-	dprint("Namelen %d Ndspanid %d Niblock %d\n", Namelen, Ndspanid, Niblock);
-	dprint("Blocksize %d Nspanidperblock %d Nindperblock %d\n",
-			Blocksize, Nspanidperblock, Nindperblock);
-	dprint("Maxspanlen %llud Maxspansize %llud\n",
-			Maxspanlen, Maxspansize);
+	dprint("Namelen %d Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
+	dprint("Blocksize %d Nindperblock %d\n",
+			Blocksize, Nindperblock);
 
-	spans = nperindunit(Tind0);
-	dprint("A %s unit points to %lld data spans (%llud bytes)\n",
-			 tagnames[Tind0], spans, spans*Maxspansize);
-	dprint("	block points to %lld data spans\n", nperiblock(Tind0));
-	for (i = Tind1; i < Maxtind; i++) {
-		spans = nperindunit(i);
+	for (i = Tind0; i < Maxtind; i++) {
+		n = nperindunit(i);
 		dprint("A %s unit points to %lld data spans (%llud bytes)\n",
-			 tagnames[i], spans, spans*Maxspansize);
+			 tagnames[i], n, n*Blocksize);
 		dprint("	block points to %lld data spans\n", nperiblock(i));
 	}
 	dprint("sizeof(Dentry1) %d Namelen %d\n",
@@ -231,6 +225,6 @@
 			sizeof(Dentry1), Namelen);
 	max = maxsize();
 	dprint("maximum possible spans %llud\n", max);
-	dprint("	(%llud*Maxspansize = %llud bytes = %llud TiB)\n",
-			max, max*Maxspansize, (max*Maxspansize)/(MiB*MiB));
+	dprint("	(%llud*Rawblocksize = %llud bytes = %llud TiB)\n",
+			max, max*Rawblocksize, (max*Rawblocksize)/(MiB*MiB));
 }
--- a/sub.c
+++ b/sub.c
@@ -36,7 +36,7 @@
 	Iobuf *sb;
 	Superb *s;
 
-	sb = getbufchk(Bsuper, 1, Bwritable, Tdata, Qpsuper);
+	sb = getbufchk(Bsuper, Bwritable, Tdata, Qpsuper);
 	if(sb == nil){
 		panic("newqpath: sb == nil\n");
 	}
@@ -95,21 +95,21 @@
 
 /* making the assumption that all allocations are not readonly */
 Iobuf *
-allocblocks(u16 len, int tag, u64 qpath)
+allocblock(int tag, u64 qpath)
 {
 	u64 blkno;
 	Iobuf *buf;
 
-	blkno = balloc(&frees, len);
+	blkno = balloc(&frees);
 	if(blkno == 0)
 		return nil;	/* the caller should trigger an Efull message */
 
 	if(chatty9p > 1)
-		dprint("alloc %d at %llud\n", len, blkno);
+		dprint("alloc %llud\n", blkno);
 	/* cannot do getbufchk() unless we ream the whole disk at start */
-	buf = getbuf(blkno, len, Bwritable, Bfreshalloc);
+	buf = getbuf(blkno, Bwritable, Bfreshalloc);
 	/* clear the buf to avoid leaks on reuse */
-	memset(buf->io, 0, buf->len*Rawblocksize);
+	memset(buf->io, 0, Rawblocksize);
 	settag(buf, tag, qpath);
 	return buf;
 }
@@ -122,17 +122,17 @@
 		panic("freeblockbuf without Bwritable");
 
 	/* clear the buf to avoid leaks on reuse */
-	memset(buf->io, 0, buf->len*Rawblocksize);
+	memset(buf->io, 0, Rawblocksize);
 	if(buf->dirties)
 		buf->tofree = 1;
 	else
-		bfree(&frees, buf->blkno, buf->len);
+		bfree(&frees, buf->blkno, 1);
 	putbuffree(buf);
 }
 
 /* add the block to the extents used to manage free blocks */
 void
-freeblocks(u64 blkno, u16 len, u16 tag, u64 qpath)
+freeblock(u64 blkno, u16 tag, u64 qpath)
 {
 	Iobuf *buf;
 
@@ -141,7 +141,7 @@
 				 blkno, config.nblocks);
 		return;
 	}
-	buf = getbufchk(blkno, len, Bwritable, tag, qpath);
+	buf = getbufchk(blkno, Bwritable, tag, qpath);
 	if(buf == nil)
 		dprint("%s",errstring[Ephase]);
 	freeblockbuf(buf);
@@ -172,7 +172,7 @@
 	Iobuf *sb;
 	Superb *s;
 
-	sb = getbufchk(Bsuper, 1, Bwritable, Tdata, Qpsuper);
+	sb = getbufchk(Bsuper, Bwritable, Tdata, Qpsuper);
 	if(sb == nil){
 		panic("newqpath: sb == nil\n");
 	}
@@ -198,17 +198,13 @@
 		close(fd);
 }
 
-/*	"When we say that something was written to the disk, it should be written"
-	Bimm is obsolete as all writes are synchronous
- */
-
 void
-reamdata(u64 bno, u16 len, u64 qpath)
+reamdata(u64 bno, u64 qpath)
 {
 	Iobuf *b;
 
-	b = getbuf(bno, len, Bwritable, Bfreshalloc);
-	memset(b->io, 0, len*Rawblocksize);
+	b = getbuf(bno, Bwritable, Bfreshalloc);
+	memset(b->io, 0, Rawblocksize);
 	settag(b, Tdata, qpath);
 	putbuf(b);
 }
@@ -218,9 +214,8 @@
 {
 	Iobuf *b;
 	Dentry *d;
-	u16 len;
 
-	b = getbuf(dblkno, 1, Bwritable, Bfreshalloc);
+	b = getbuf(dblkno, Bwritable, Bfreshalloc);
 	memset(b->io, 0, Rawblocksize);
 	settag(b, Tdentry, qpath);
 	d = &b->io->d;
@@ -236,12 +231,8 @@
 	d->size = size;
 	d->pdblkno = pdblkno;
 	d->pqpath = pqpath;
-	if(contentblkno > 0){
-		len = (size+sizeof(Tag))/Rawblocksize;
-		if((size+sizeof(Tag))%Rawblocksize > 0)
-			len++;
-		d->dspans[0] = (Spanid){contentblkno,len};
-	}
+	if(contentblkno > 0)
+		d->dblocks[0] = contentblkno;
 	putbuf(b);
 }
 
@@ -264,7 +255,7 @@
 					"10006:glenda:glenda:\n"
 					"10007:manies::\n";
 
-	b = getbuf(Badm, 1, Bwritable, Bfreshalloc);
+	b = getbuf(Badm, Bwritable, Bfreshalloc);
 	memset(b->io, 0, Rawblocksize);
 	settag(b, Tdentry, Qpadm);
 	d = &b->io->d;
@@ -279,15 +270,15 @@
 	d->mtime = nsec();
 	d->pdblkno = Broot;
 	d->pqpath = Qproot;
-	d->dspans[0] = (Spanid){Bbkp, 1};
-	d->dspans[1] = (Spanid){Bdconfig, 1};
-	d->dspans[2] = (Spanid){Bdctl, 1};
-	d->dspans[3] = (Spanid){Bdsuper, 1};
-	d->dspans[4] = (Spanid){Bdusers, 1};
-	d->dspans[5] = (Spanid){Bdfrees, 1};
+	d->dblocks[0] = Bbkp;
+	d->dblocks[1] = Bdconfig;
+	d->dblocks[2] = Bdctl;
+	d->dblocks[3] = Bdsuper;
+	d->dblocks[4] = Bdusers;
+	d->dblocks[5] = Bdfrees;
 	putbuf(b);
 
-	b = getbuf(Bbkp, 1, Bwritable, Bfreshalloc);
+	b = getbuf(Bbkp, Bwritable, Bfreshalloc);
 	memset(b->io, 0, Rawblocksize);
 	settag(b, Tdentry, Qpbkp);
 	d = &b->io->d;
@@ -303,12 +294,12 @@
 	d->size = strlen(users)+1;
 	d->pdblkno = Badm;
 	d->pqpath = Qpadm;
-	d->dspans[0] = (Spanid){Bdconfig0, 1};
-	d->dspans[1] = (Spanid){Bdsuper0, 1};
-	d->dspans[2] = (Spanid){Bdroot0, 1};
-	d->dspans[3] = (Spanid){Bdconfig1, 1};
-	d->dspans[4] = (Spanid){Bdsuper1, 1};
-	d->dspans[5] = (Spanid){Bdroot1, 1};
+	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);
 
 	reamfile(Bdconfig, Qpconfig, "config", 0, Badm, Qpadm, Bconfig);
@@ -332,7 +323,7 @@
 	reamfile(Bdroot1, Qproot1, "root.1",
 			 Blocksize, Bbkp, Qpbkp, config.root.dest[1]);
 
-	b = getbuf(Busers, 1, Bwritable, Bfreshalloc);
+	b = getbuf(Busers, Bwritable, Bfreshalloc);
 	if(b == nil)
 		panic("cannot get Busers");
 	memset(b->io, 0, Rawblocksize);
@@ -347,7 +338,7 @@
 	Iobuf *b;
 	Dentry *d;
 
-	b = getbuf(Broot, 1, Bwritable, Bfreshalloc);
+	b = getbuf(Broot, Bwritable, Bfreshalloc);
 	if(b == nil)
 		panic("rootream b == nil");
 	memset(b->io, 0, Rawblocksize);
@@ -364,7 +355,7 @@
 	d->qid.path = Qproot;
 	d->qid.version = 0;
 	d->mtime = nsec();
-	d->dspans[0] = (Spanid){Badm, 1};
+	d->dblocks[0] = Badm;
 	putbuf(b);
 }
 
@@ -376,7 +367,7 @@
 	u64 i, nbused;
 
 	nbused = Nbused;
-	sbuf = getbuf(Bsuper, 1, Bwritable, Bfreshalloc);
+	sbuf = getbuf(Bsuper, Bwritable, Bfreshalloc);
 	if(sbuf == nil)
 		panic("superream: sbuf == nil");
 	memset(sbuf->io, 0, Rawblocksize);
@@ -396,9 +387,9 @@
 	config.root.dest[0] = nblocks-Broot;
 	config.root.dest[1] = nbused+((nblocks-nbused)/2)-Broot;
 	for(i=0; i<Nbkp; i++){
-		reamdata(config.config.dest[i], 1, Qpconfig0+3*i);
-		reamdata(config.super.dest[i], 1, Qpsuper0+3*i);
-		reamdata(config.root.dest[i], 1, Qproot0+3*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);
 	}
 	putbuf(sbuf);
 
@@ -410,7 +401,7 @@
 				config.super.dest[0], config.super.dest[1],
 				config.root.dest[0], config.root.dest[1]);
 
-	reamdata(Bconfig, 1, Qpconfig);
+	reamdata(Bconfig, Qpconfig);
 	reamdefaults();
 	rootream();
 
@@ -454,13 +445,13 @@
 
 	memset(buf, 0, Rawblocksize);
 	for(i = 0; i < Nbused; i++)
-		devwrite(i, buf, 1);
+		devwrite(i, buf);
 
 	superream(size, nblocks);
 
-	iob = getbuf(Bmagicb, 1, Bwritable, Bfreshalloc);
-	snprint((s8*)iob->io->buf+256, Rawblocksize-256, "%s%d\n%llud\n",
-			magic, Rawblocksize, Maxspansize);
+	iob = getbuf(Bmagicb, Bwritable, Bfreshalloc);
+	snprint((s8*)iob->io->buf+256, Rawblocksize-256, "%s%d\n\n",
+			magic, Rawblocksize);
 	settag(iob, Tmagic, Qpmagic);
 	putbuf(iob);
 
@@ -482,7 +473,7 @@
 	Dentry *d;
 	u64 ret;
 
-	b = getbufchk(dblkno, 1, Breadonly, Tdentry, qpath);
+	b = getbufchk(dblkno, Breadonly, Tdentry, qpath);
 	if(b == nil){
 		putbuf(b);
 		panic("%s",errstring[Ephase]);
@@ -489,7 +480,7 @@
 		return 0;
 	}
 	d = &b->io->d;
-	ret = d->dspans[0].blkno;
+	ret = d->dblocks[0];
 	putbuf(b);
 	return ret;
 }
@@ -497,7 +488,7 @@
 void
 init(int doream)
 {
-	u32 rbufsize, maxspansize;
+	u32 rbufsize;
 	u64 size;
 	Iobuf *sb, *b;
 	Superb *s;
@@ -515,7 +506,7 @@
 	}
 
 	/* check magic */
-	b = getbufchk(Bmagicb, 1, Breadonly, Tmagic, Qpmagic);
+	b = getbufchk(Bmagicb, Breadonly, Tmagic, Qpmagic);
 	if(b == nil){
 		panic("Invalid magic: %s",errstring[Ephase]);
 		return;
@@ -530,16 +521,10 @@
 				Rawblocksize, rbufsize);
 		panic("bad Rawblocksize != rbufsize");
 	}
-	maxspansize = strtoul(rptr+1, nil, 10);
-	if(maxspansize != Maxspansize){
-		print("init incorrect block size Maxspansize %llud maxspansize %ud\n",
-				Maxspansize, maxspansize);
-		panic("bad Maxspansize != maxspansize");
-	}
 	putbuf(b);
 
 	/* check super */
-	sb = getbufchk(Bsuper, 1, Breadonly, Tdata, Qpsuper);
+	sb = getbufchk(Bsuper, Breadonly, Tdata, Qpsuper);
 	if(sb == nil){
 		panic("Invalid super: %s",errstring[Ephase]);
 		return;
--- a/tag.c
+++ b/tag.c
@@ -34,7 +34,8 @@
 
 	v = 1;
 	for(i = 1; i <= n; i++)
-		v = v*base;
+		v = mulu64ov(v,base);
+//		v = v*base;
 	return v;
 }
 
@@ -47,7 +48,7 @@
 
 	if(tag == Tind0)
 		return 1;
-	return Nspanidperblock*power(Blocksize/sizeof(u64), tag-Tind1);
+	return Nindperblock*power(Blocksize/sizeof(u64), tag-Tind1);
 }
 
 /* Each u64 address in the indirect block links to n Tdata/Tdentry blocks */
@@ -63,10 +64,10 @@
 {
 	u64 maxfortag, tag, i;
 
-	if(reli < Ndspanid){
+	if(reli < Ndblock){
 		panic("should not be here");
 	}
-	reli -= Ndspanid;
+	reli -= Ndblock;
 
 	for(tag = Tind0, i = reli; tag <= Tmaxind; tag++){
 		maxfortag = nperiblock(tag);
@@ -87,9 +88,9 @@
 tagstartreli(u8 tag)
 {
 	if(tag == Tind0)
-		return Ndspanid;
+		return Ndblock;
 	else if(tag == Tind1)
-		return Ndspanid+Nspanidperblock;
+		return Ndblock+Nindperblock;
 	return nperiblock(tag-1)+tagstartreli(tag-1);
 }
 
@@ -99,7 +100,7 @@
 	if(tag >= Maxtind || tag < Tind0)
 		panic("maxn: invalid tag %d\n", tag);;
 	if(tag == Tind0)
-		return Ndspanid+Nspanidperblock;
+		return Ndblock+Nindperblock;
 	else
 		return nperiblock(tag) + tagstartreli(tag);
 }
--- a/tests/sizes.c
+++ b/tests/sizes.c
@@ -26,7 +26,7 @@
 maxsize1(void)
 {
 	int i;
-	uvlong max = Ndspanid, ind = 1;
+	uvlong max = Ndblock, ind = 1;
 
 	for (i = 0; i < Niblock; i++) {
 		ind = muluvlongov(ind, Nindperblock);	/* power of Nindperblock */
@@ -65,9 +65,13 @@
 
 	if(tag == Tind0)
 		return 1;
-	return Nspanidperblock*power(Blocksize/sizeof(u64), tag-Tind1);
+	return Nindperblock*power(Blocksize/sizeof(u64), tag-Tind1);
 }
 
+/*
+ * compute BUFSIZE*(Ndblock+INDPERBUF+INDPERBUF²+INDPERBUF³+INDPERBUF⁴ .. upto ^Niblock)
+ * while watching for overflow; in that case, return 0.
+ */
 /* extern double pow(double x, double y); *//* return x ^ y (exponentiation) */
 /* Each u64 address in the indirect block links to n Tdata/Tdentry blocks */
 u64
@@ -80,9 +84,9 @@
 maxsize(void)
 {
 	int i;
-	uvlong max = Ndspanid, ind;
+	uvlong max = Ndblock, ind;
 
-	print("maxsize direct spans max %llud\n", max);
+	print("maxsize direct blocks max %llud\n", max);
 	for (i = 0; i < Niblock; i++) {
 		ind = nperiblock(Tind0+i);
 		max += ind;
@@ -95,30 +99,23 @@
 main(int, void**)
 {
 	int i;
-	u64 spans, max;
+	u64 max, n;
 
-	print("Namelen %d Ndspanid %d Niblock %d\n", Namelen, Ndspanid, Niblock);
-	print("Blocksize %d Nspanidperblock %d Nindperblock %d\n",
-			Blocksize, Nspanidperblock, Nindperblock);
-	print("Maxspanlen %llud Maxspansize %llud\n",
-			Maxspanlen, Maxspansize);
+	print("Namelen %llud Ndblock %d Niblock %d\n", Namelen, Ndblock, Niblock);
+	print("Blocksize %llud Nindperblock %llud\n",
+			Blocksize, Nindperblock);
 
-	spans = nperindunit(Tind0);
-	print("A %s unit points to %lld data spans (%llud bytes)\n",
-			 tagnames[Tind0], spans, spans*Maxspansize);
-	print("	block points to %lld data spans\n", nperiblock(Tind0));
-	for (i = Tind1; i < Maxtind; i++) {
-		spans = nperindunit(i);
-		print("A %s unit points to %lld data spans (%llud bytes)\n",
-			 tagnames[i], spans, spans*Maxspansize);
-		print("	block points to %lld data spans\n", nperiblock(i));
+	for (i = Tind0; i < Maxtind; i++) {
+		n = nperindunit(i);
+		print("A %s unit points to %lld blocks (%llud bytes)\n",
+			 tagnames[i], n, n*Blocksize);
+		print("	block points to %llud blocks\n", nperiblock(i));
 	}
-	print("sizeof(Dentry1) %d Namelen %d\n",
+	print("sizeof(Dentry1) %d Namelen %llud\n",
 			sizeof(Dentry1), Namelen);
 	max = maxsize();
-	print("maximum possible spans %llud\n", max);
-	print("	(%llud*Maxspansize = %llud bytes)\n", max, max*Maxspansize);
-	print("	(%llud*Maxspansize = %llud bytes = %llud GiB)\n",
-			max, max*Maxspansize, (max*Maxspansize)/(GiB));
+	print("maximum possible blocks %llud\n", max);
+	print("	(%llud*Rawblocksize = %llud bytes = %llud GiB)\n",
+			max, max*Rawblocksize, (max*Rawblocksize)/(GiB));
 	exits(0);
 }
--- a/used.c
+++ b/used.c
@@ -79,7 +79,7 @@
 	u8 buf[Rawblocksize];
 	Tag *t;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	return checkvalid(blkno, t, tag, qpath);
 }
@@ -91,21 +91,18 @@
 	Tag *t, *ct;
 	u64 cblkno, *bufa;
 	int i;
-	Spanid *s;
-	u16 len;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	if(checkvalid(blkno, t, tag, qpath)){
 		if(t->type == Tind0){
-			s = (Spanid*)(buf+sizeof(Tag));
-			for(i = 0; i<Nspanidperblock; i++){
-				cblkno = s[i].blkno;
-				len = s[i].len;
+			bufa = (u64*)(buf+sizeof(Tag));
+			for(i = 0; i<Nindperblock; i++){
+				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				cbuf = malloc(len*Rawblocksize);
-				devread(cblkno, cbuf, len);
+				cbuf = malloc(Rawblocksize);
+				devread(cblkno, cbuf);
 				ct = (Tag*)cbuf;
 				if(ct->type == Tdentry && ct->type == bottomtag)
 					walkdentry(cblkno);
@@ -120,7 +117,7 @@
 				cblkno = bufa[i];
 				if(cblkno == 0)
 					return;
-				devread(cblkno, cbuf, 1);
+				devread(cblkno, cbuf);
 				/* check tag */
 				walkindir(cblkno, tag-1,  bottomtag, qpath);
 			}
@@ -141,7 +138,7 @@
 	u8 isdir;
 	u16 len;
 
-	devread(blkno, buf, 1);
+	devread(blkno, buf);
 	t = (Tag*)buf;
 	d = (Dentry*)(buf+sizeof(Tag));
 	isdir = (d->mode & DMDIR) > 0;
@@ -159,13 +156,12 @@
 		as they are considered to be free blocks */
 	if(blkno == Bdfrees)
 		return;
-	for(i = 0; i<Ndspanid; i++){
-		cblkno = d->dspans[i].blkno;
-		len = d->dspans[i].len;
+	for(i = 0; i<Ndblock; i++){
+		cblkno = d->dblocks[i];
 		if(cblkno == 0)
 			return;
-		cbuf = malloc(len*Rawblocksize);
-		devread(cblkno, cbuf, len);
+		cbuf = malloc(Rawblocksize);
+		devread(cblkno, cbuf);
 		ct = (Tag*)cbuf;
 		if(isdir)
 			walkdentry(cblkno);
@@ -178,7 +174,7 @@
 		cblkno = d->iblocks[i];
 		if(cblkno == 0)
 			return;
-		devread(cblkno, cbuf, 1);
+		devread(cblkno, cbuf);
 		ct = (Tag*)cbuf;
 		if(ct->type == Tind0+i){
 			walkindir(cblkno, Tind0+i, isdir ? Tdentry : Tdata, d->qid.path);
--- a/user.c
+++ b/user.c
@@ -288,14 +288,14 @@
 	char rem[Blocksize*2];
 	Dentry *du;
 
-	ubuf = getbufchk(Bdusers, 1, Breadonly, Tdentry, Qpusers);
+	ubuf = getbufchk(Bdusers, Breadonly, Tdentry, Qpusers);
 	du = &ubuf->io->d;
-	/* for(i = 0; i < Ndspanid; i++){ */
-		if(du->dspans[0].blkno == 0){
+	/* for(i = 0; i < Ndblock; i++){ */
+		if(du->dblocks[0] == 0){
 			putbuf(ubuf);
 			return;
 		}
-		ucbuf = getbufchk(du->dspans[0].blkno, 1, Breadonly, Tdata, Qpusers);
+		ucbuf = getbufchk(du->dblocks[0], Breadonly, Tdata, Qpusers);
 		/* fill(rem, ucbuf->iobuf); */
 		strncpy(rem, (char*)ucbuf->io->buf, Blocksize);
 		parseusers(rem);
--- a/writer.c
+++ b/writer.c
@@ -162,7 +162,7 @@
 	if(chatty9p > 4)
 		dprint("dowrite p->blkno %llud locked\n", p->blkno);
 	p->io.dirty = 1;
-	if((n = devwrite(p->blkno, &p->payload, p->len)) != p->len*Rawblocksize){
+	if((n = devwrite(p->blkno, &p->payload)) != Rawblocksize){
 		dprint("%s\n", errstring[Esystem]);
 		panic("error writing block %llud: %llud bytes: %r\n",
 				p->blkno, n);
@@ -176,7 +176,7 @@
 	p->iobuf->dirties--;
 	if(p->iobuf->tofree && p->iobuf->dirties == 0){
 		p->iobuf->tofree = 0;
-		bfree(&frees, p->iobuf->blkno, p->iobuf->len);
+		bfree(&frees, p->iobuf->blkno, 1);
 	}
 	wunlock(p->iobuf);
 	free(p);