code: plan9front

Download patch

ref: 2e85e328864c215c2efa228f129ce3fa6aa1db1f
parent: f5688dd6c9bfb6cee00f2c5e5f190d7a2ffaa6c6
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jul 14 18:23:16 EDT 2015

9660srv: keep data and metadata separate in the cache with a tag

data on the disk is layed out sequentially and directory information
is at the end of the disk. we want to keep data and metadata separated
so that reading large sequential files will not evict the directory
information from the cache causing long seeks.

for that, we tag the clusters (an 8th for metadata, and the rest
for data) and getbuf() will only evict clusters of the same tag.

--- a/sys/src/cmd/9660srv/9660srv.c
+++ b/sys/src/cmd/9660srv/9660srv.c
@@ -69,7 +69,7 @@
 	dp = nil;
 	haveplan9 = 0;
 	for(i=VOLDESC;i<VOLDESC+100; i++){	/* +100 for sanity */
-		p = getbuf(cd->d, i);
+		p = getbuf(cd->d, i, 1);
 		v = (Voldesc*)(p->iobuf);
 		if(memcmp(v->byte, "\01CD001\01", 7) == 0){		/* iso */
 			if(dirp)
@@ -372,7 +372,7 @@
 	while(count > 0){
 		if(n > count)
 			n = count;
-		p = getbuf(f->xf->d, addr);
+		p = getbuf(f->xf->d, addr, 0);
 		memmove(&buf[rcnt], &p->iobuf[o], n);
 		putbuf(p);
 		count -= n;
@@ -499,7 +499,7 @@
 			ip->offset += Sectorsize-boff;
 			continue;
 		}
-		p = getbuf(f->xf->d, addr/Sectorsize);
+		p = getbuf(f->xf->d, addr/Sectorsize, 1);
 		len = p->iobuf[boff];
 		if(len >= 34)
 			break;
@@ -754,7 +754,7 @@
 	off = l32(p+12);
 	len = l32(p+20);
 	chat("getcontin %d...", bn);
-	b = getbuf(dev, bn);
+	b = getbuf(dev, bn, 1);
 	if(b == 0){
 		*s = 0;
 		return 0;
--- a/sys/src/cmd/9660srv/dat.h
+++ b/sys/src/cmd/9660srv/dat.h
@@ -31,6 +31,7 @@
 	int	nbuf;
 	Iobuf*	buf;
 	uchar*	iobuf;
+	ulong	tag;			/* cache tag for eviction: 0 = data, 1 = metadata */
 };
 
 struct Xdata
--- a/sys/src/cmd/9660srv/fns.h
+++ b/sys/src/cmd/9660srv/fns.h
@@ -1,7 +1,7 @@
 void	chat(char*, ...);
 void*	ealloc(long);
 void	error(char*);
-Iobuf*	getbuf(Xdata*, ulong);
+Iobuf*	getbuf(Xdata*, ulong, ulong);
 Xdata*	getxdata(char*);
 void	iobuf_init(void);
 void	nexterror(void);
--- a/sys/src/cmd/9660srv/iobuf.c
+++ b/sys/src/cmd/9660srv/iobuf.c
@@ -31,7 +31,7 @@
 static Ioclust*	iohead;
 static Ioclust*	iotail;
 
-static Ioclust*	getclust(Xdata*, long);
+static Ioclust*	getclust(Xdata*, long, ulong);
 static void	putclust(Ioclust*);
 static void	xread(Ioclust*);
 
@@ -53,6 +53,16 @@
 	for(i=0; i<nclust; i++){
 		c = (Ioclust*)mem;
 		mem += sizeof(Ioclust);
+
+		/*
+		 * on a iso filesystem, data is usually layed out sequentially
+		 * but directory information is at the end of the disk. to avoid
+		 * evicting directory information when reading large sequential
+		 * files, we keep them tagged in the cache. for now, we use
+		 * an 8th of the clusters for meta data.
+		 */
+		c->tag = i <= (nclust/8);
+
 		c->addr = -1;
 		c->prev = iotail;
 		if(iotail)
@@ -87,13 +97,13 @@
 }
 
 static Ioclust*
-getclust(Xdata *dev, long addr)
+getclust(Xdata *dev, long addr, ulong tag)
 {
 	Ioclust *c, *f;
 
 	f = nil;
 	for(c=iohead; c; c=c->next){
-		if(!c->busy)
+		if(!c->busy && c->tag == tag)
 			f = c;
 		if(c->addr == addr && c->dev == dev){
 			c->busy++;
@@ -141,13 +151,13 @@
 }
 
 Iobuf*
-getbuf(Xdata *dev, ulong addr)
+getbuf(Xdata *dev, ulong addr, ulong tag)
 {
 	int off;
 	Ioclust *c;
 
 	off = addr%BUFPERCLUST;
-	c = getclust(dev, addr - off);
+	c = getclust(dev, addr - off, tag);
 	if(c->nbuf < off){
 		c->busy--;
 		error("I/O read error");