shithub: riscv

Download patch

ref: 1ee5cd7425b2bcaaef4d83092c3a9453fb33588f
parent: e51845797bf3253096b15b7a86a8c900c751bb37
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed Oct 17 11:48:30 EDT 2012

kernel: mnt cache rework

avoid double entries in the cache for copen() and properly handle
locking so we wont just give up if we cant lock the Mntcache entry,
but drop the cache lock, qlock the Mntcache entry, and then recheck
the cache.

general cleanup (cdev -> ccache, use eqchantdqid())

--- a/sys/lib/acid/kernel
+++ b/sys/lib/acid/kernel
@@ -74,6 +74,20 @@
 	}
 }
 
+defn findchan(dev,type,path) {
+	local c;
+
+	c = (Chan)chanalloc.list;
+	while c != 0 do {
+		if c.ref != 0 then {
+			if c.dev == dev && c.type == type && c.qid.path == path then
+				return c;
+		}
+		c=(Chan)c.link;
+	}
+	return 0;
+}
+
 defn nchans() {
 	local c, n;
 	
@@ -159,6 +173,27 @@
 	}
 }
 
+NHASH=128;
+defn mntcache() {
+	local i, m, c;
+
+	i=0; loop 1,NHASH do {
+		m = cache.hash[i];
+		while m != 0 do {
+			complex Mntcache m;
+			print(m\X, " dev ", m.dev\D, " type ", m.type, " qid (", 
+				m.qid.path, " ", m.qid.vers\D, ")\n");
+			c = findchan(m.dev, m.type, m.qid.path);
+			if c != 0 then {
+				print("	");
+				chan(c);
+			}
+			m = m.hash;
+		}
+		i = i+1;
+	}
+}
+
 // manipulate processes
 defn proctab(x) {
 	return procalloc.arena+sizeofProc*x;
@@ -379,5 +414,6 @@
 	needacid("proc");
 	needacid("chan");
 	needacid("segment");
+	needacid("cache");
 }
 }
--- a/sys/src/9/port/cache.c
+++ b/sys/src/9/port/cache.c
@@ -208,39 +208,42 @@
 	}
 }
 
+/* called with cache locked */
+static Mntcache*
+clookup(Chan *c, int skipvers)
+{
+	Mntcache *m;
+
+	for(m = cache.hash[c->qid.path%NHASH]; m; m = m->hash)
+		if(eqchantdqid(c, m->type, m->dev, m->qid, skipvers) && c->qid.type == m->qid.type)
+			return m;
+
+	return 0;
+}
+
 void
 copen(Chan *c)
 {
-	int h;
 	Mntcache *m, *f, **l;
 
 	/* directories aren't cacheable and append-only files confuse us */
-	if(c->qid.type&(QTDIR|QTAPPEND))
+	if(c->qid.type&(QTDIR|QTAPPEND)){
+		c->mcp = 0;
 		return;
-	h = c->qid.path%NHASH;
+	}
+
 	lock(&cache);
-	for(m = cache.hash[h]; m; m = m->hash) {
-		if(m->qid.path == c->qid.path)
-		if(m->qid.type == c->qid.type)
-		if(m->dev == c->dev && m->type == c->type) {
-			/* File was updated, invalidate cache */
-			if(m->qid.vers != c->qid.vers){
-				if(!canqlock(m))
-					goto Busy;
-				m->qid.vers = c->qid.vers;
-				goto Update;
-			}
-			ctail(m);
-			c->mcp = m;
-			unlock(&cache);
-			return;
-		}
+	m = clookup(c, 1);
+	if(m == 0)
+		m = cache.head;
+	else if(m->qid.vers == c->qid.vers) {
+		ctail(m);
+		unlock(&cache);
+		c->mcp = m;
+		return;
 	}
+	ctail(m);
 
-	/* LRU the cache headers */
-	m = cache.head;
-	if(!canqlock(m))
-		goto Busy;
 	l = &cache.hash[m->qid.path%NHASH];
 	for(f = *l; f; f = f->hash) {
 		if(f == m) {
@@ -250,39 +253,53 @@
 		l = &f->hash;
 	}
 
+	if(!canqlock(m)){
+		unlock(&cache);
+		qlock(m);
+		lock(&cache);
+		f = clookup(c, 0);
+		if(f != 0) {
+			/*
+			 * someone got there first while cache lock
+			 * was released and added a updated Mntcache
+			 * for us. update LRU and use it.
+			 */
+			ctail(f);
+			unlock(&cache);
+			qunlock(m);
+			c->mcp = f;
+			return;
+		}
+	}
+
 	m->qid = c->qid;
 	m->dev = c->dev;
 	m->type = c->type;
 
-	l = &cache.hash[h];
+	l = &cache.hash[c->qid.path%NHASH];
 	m->hash = *l;
 	*l = m;
-Update:
-	ctail(m);
-	c->mcp = m;
 	unlock(&cache);
 	cnodata(m);
 	qunlock(m);
-	return;
-Busy:
-	unlock(&cache);
-	c->mcp = 0;
+	c->mcp = m;
 }
 
-static int
-cdev(Mntcache *m, Chan *c)
+/* return locked Mntcache if still valid else reset mcp */
+static Mntcache*
+ccache(Chan *c)
 {
-	if(m->qid.path != c->qid.path)
-		return 0;
-	if(m->qid.type != c->qid.type)
-		return 0;
-	if(m->dev != c->dev)
-		return 0;
-	if(m->type != c->type)
-		return 0;
-	if(m->qid.vers != c->qid.vers)
-		return 0;
-	return 1;
+	Mntcache *m;
+
+	m = c->mcp;
+	if(m) {
+		qlock(m);
+		if(eqchantdqid(c, m->type, m->dev, m->qid, 0) && c->qid.type == m->qid.type)
+			return m;
+		c->mcp = 0;
+		qunlock(m);
+	}
+	return 0;
 }
 
 int
@@ -298,17 +315,10 @@
 	if(off+len > maxcache)
 		return 0;
 
-	m = c->mcp;
+	m = ccache(c);
 	if(m == 0)
 		return 0;
 
-	qlock(m);
-	if(cdev(m, c) == 0) {
-		qunlock(m);
-		c->mcp = 0;
-		return 0;
-	}
-
 	offset = off;
 	t = &m->list;
 	for(e = *t; e; e = e->next) {
@@ -470,15 +480,9 @@
 	if(off > maxcache || len == 0)
 		return;
 
-	m = c->mcp;
+	m = ccache(c);
 	if(m == 0)
 		return;
-	qlock(m);
-	if(cdev(m, c) == 0) {
-		qunlock(m);
-		c->mcp = 0;
-		return;
-	}
 
 	/*
 	 * Find the insertion point
@@ -564,16 +568,9 @@
 	if(off > maxcache || len == 0)
 		return;
 
-	m = c->mcp;
+	m = ccache(c);
 	if(m == 0)
 		return;
-
-	qlock(m);
-	if(cdev(m, c) == 0) {
-		qunlock(m);
-		c->mcp = 0;
-		return;
-	}
 
 	offset = off;
 	m->qid.vers++;
--