shithub: riscv

Download patch

ref: 2bc9e8e5e3b3eab7063c718fc6711b0a1cd14dbe
parent: 18e515511f45c115acbed2dc40dd1895b2ea6890
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Nov 8 17:31:26 EST 2013

kernel: make image cache not hold onto the channel, remove nocache flag

the image cache should not hold onto the text file channel
when not neccesary. now, the image keeps track of the number
of page cache references in Image.pgref. if the number of
page cache references and Image.ref are equal, this means
all the references to this image are from the page cache.
so no segments are using this image. in that case, we can
close the channel, but keep the Image in the hash table.

when attachimage() finds our image, it will check if Image.c
is nil and reattach the channel to the image before it is
used.

the Image.nocache flag isnt needed anymore.

--- a/sys/lib/acid/kernel
+++ b/sys/lib/acid/kernel
@@ -29,9 +29,18 @@
 // print Image cache contents
 IHASHSIZE = 64;
 defn imagecacheline(h) {
+	local d, p, q;
+
 	while h != 0 do {
 		complex Image h;
-		print (h\X, " ", qid(h.qid), " type ", h.type\D, " ref ", h.ref, " next ", h.next\X, " ", path(h.c.path), "\n");
+
+		d=(Dev)(*(devtab+4*h.type));
+		p = "*closed*";
+		if h.c != 0 then
+			p = path(h.c.path);
+		q = h.qid;
+		print (h\X, " ref=", h.ref, " pgref=", h.pgref, "\t#", d.dc\r, h.dev\D, " (",
+			q.path, " ", q.vers\D, " ", q.type\X, ") ", p, "\n");
 		h = h.hash;
 	}
 }
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -228,9 +228,6 @@
 		return;
 	}
 
-	if(p->image && p->image->nocache)
-		uncachepage(p);
-
 	if(p->image && p->image != &swapimage)
 		pagechaintail(p);
 	else 
@@ -294,8 +291,8 @@
 		return;
 	}
 
-	/* No freelist cache with uncached image or when memory is very low */
-	if(p->image->nocache || palloc.freecount < swapalloc.highwater) {
+	/* No freelist cache when memory is very low */
+	if(palloc.freecount < swapalloc.highwater) {
 		unlock(&palloc);
 		uncachepage(p);
 		return;
@@ -360,8 +357,10 @@
 uncachepage(Page *p)			/* Always called with a locked page */
 {
 	Page **l, *f;
+	Image *i;
 
-	if(p->image == 0)
+	i = p->image;
+	if(i == 0)
 		return;
 
 	lock(&palloc.hashlock);
@@ -374,9 +373,13 @@
 		l = &f->hash;
 	}
 	unlock(&palloc.hashlock);
-	putimage(p->image);
 	p->image = 0;
 	p->daddr = 0;
+
+	lock(i);
+	i->pgref--;
+	unlock(i);
+	putimage(i);
 }
 
 void
@@ -392,7 +395,11 @@
 	if(p->image)
 		panic("cachepage");
 
-	incref(i);
+	lock(i);
+	i->ref++;
+	i->pgref++;
+	unlock(i);
+
 	lock(&palloc.hashlock);
 	p->image = i;
 	l = &pghash(p->daddr);
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -344,16 +344,15 @@
 struct Image
 {
 	Ref;
-	Chan	*c;			/* channel to text file */
+	long	pgref;			/* number of cached pages (pgref <= ref) */
+	Chan	*c;			/* channel to text file, nil when not used */
 	Qid 	qid;			/* Qid for page cache coherence */
-	Qid	mqid;
-	Chan	*mchan;
+	ulong	dev;			/* Device id of owning channel */
 	ushort	type;			/* Device type of owning channel */
 	Segment *s;			/* TEXT segment for image if running */
 	Image	*hash;			/* Qid hash chains */
 	Image	*next;			/* Free list */
 	char	notext;			/* no file associated */
-	char	nocache;		/* no freelist page caching */
 };
 
 struct Pte
--- a/sys/src/9/port/segment.c
+++ b/sys/src/9/port/segment.c
@@ -247,12 +247,8 @@
 	for(i = ihash(c->qid.path); i; i = i->hash) {
 		if(c->qid.path == i->qid.path) {
 			lock(i);
-			if(eqqid(c->qid, i->qid) &&
-			   eqqid(c->mqid, i->mqid) &&
-			   c->mchan == i->mchan &&
-			   c->type == i->type) {
+			if(eqchantdqid(c, i->type, i->dev, i->qid, 0) && c->qid.type == i->qid.type)
 				goto found;
-			}
 			unlock(i);
 		}
 	}
@@ -274,18 +270,20 @@
 	imagealloc.free = i->next;
 
 	lock(i);
-	incref(c);
-	i->nocache = (c->flag & CCACHE) == 0;
-	c->flag &= ~CCACHE;
-	i->c = c;
 	i->type = c->type;
+	i->dev = c->dev;
 	i->qid = c->qid;
-	i->mqid = c->mqid;
-	i->mchan = c->mchan;
+
 	l = &ihash(c->qid.path);
 	i->hash = *l;
 	*l = i;
+
 found:
+	if(i->c == nil){
+		i->c = c;
+		c->flag &= ~CCACHE;
+		incref(c);
+	}
 	unlock(&imagealloc);
 
 	if(i->s == 0) {
@@ -360,12 +358,21 @@
 	if(i->notext)
 		return;
 
+	c = nil;
 	lock(i);
-	if(--i->ref == 0) {
+	if(--i->ref == i->pgref){
+		/*
+		 * all remaining references to this image are from the
+		 * page cache now. close the channel as we can reattach
+		 * the chan on attachimage()
+		 */
+		c = i->c;
+		i->c = nil;
+	}
+	if(i->ref == 0){
 		l = &ihash(i->qid.path);
 		mkqid(&i->qid, ~0, ~0, QTFILE);
 		unlock(i);
-		c = i->c;
 
 		lock(&imagealloc);
 		for(f = *l; f; f = f->hash) {
@@ -375,15 +382,13 @@
 			}
 			l = &f->hash;
 		}
-
 		i->next = imagealloc.free;
 		imagealloc.free = i;
 		unlock(&imagealloc);
-
+	} else
+		unlock(i);
+	if(c)
 		ccloseq(c);	/* does not block */
-		return;
-	}
-	unlock(i);
 }
 
 long
--