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())
This commit is contained in:
cinap_lenrek 2012-10-17 15:48:30 +02:00
parent e51845797b
commit 1ee5cd7425
2 changed files with 101 additions and 68 deletions

View file

@ -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");
}
}

View file

@ -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;
}
}
/* LRU the cache headers */
m = cache.head;
if(!canqlock(m))
goto Busy;
lock(&cache);
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);
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++;