summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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++;