summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-10-17 15:48:30 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-10-17 15:48:30 +0200
commit1ee5cd7425b2bcaaef4d83092c3a9453fb33588f (patch)
tree8c84a7c32976a28299a730d53ee386bf667568d6
parente51845797bf3253096b15b7a86a8c900c751bb37 (diff)
downloadplan9front-1ee5cd7425b2bcaaef4d83092c3a9453fb33588f.tar.xz
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())
-rw-r--r--sys/lib/acid/kernel36
-rw-r--r--sys/src/9/port/cache.c131
2 files changed, 100 insertions, 67 deletions
diff --git a/sys/lib/acid/kernel b/sys/lib/acid/kernel
index 68c484b5d..7d082ec12 100644
--- a/sys/lib/acid/kernel
+++ b/sys/lib/acid/kernel
@@ -74,6 +74,20 @@ defn chans() {
}
}
+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 @@ defn badchans() {
}
}
+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 @@ if (map()[2]) != {} then { // map has more than two elements -> active proc
needacid("proc");
needacid("chan");
needacid("segment");
+ needacid("cache");
}
}
diff --git a/sys/src/9/port/cache.c b/sys/src/9/port/cache.c
index 3bef6d4e9..e748c7301 100644
--- a/sys/src/9/port/cache.c
+++ b/sys/src/9/port/cache.c
@@ -208,39 +208,42 @@ ctail(Mntcache *m)
}
}
+/* 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 @@ copen(Chan *c)
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 @@ cread(Chan *c, uchar *buf, int len, vlong off)
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 @@ cupdate(Chan *c, uchar *buf, int len, vlong off)
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,17 +568,10 @@ cwrite(Chan* c, uchar *buf, int len, vlong off)
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++;
c->qid.vers++;