kernel: make the mntcache robust against fileserver like fossil that do not change the qid.vers on wstat
introducing new ctrunc() function that invalidates any caches for the passed in chan, invoked when handling wstat with a specified file length or on file creation/truncation. test program to reproduce the problem: #include <u.h> #include <libc.h> #include <libsec.h> void main(int argc, char *argv[]) { int fd; Dir *d, nd; fd = create("xxx", ORDWR, 0666); write(fd, "1234", 4); d = dirstat("xxx"); assert(d->length == 4); nulldir(&nd); nd.length = 0; dirwstat("xxx", &nd); d = dirstat("xxx"); assert(d->length == 0); fd = open("xxx", OREAD); assert(read(fd, (void*)&d, 4) == 0); }
This commit is contained in:
parent
4aeefba681
commit
47f07b2669
3 changed files with 47 additions and 13 deletions
|
@ -187,7 +187,7 @@ ccache(Chan *c)
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
copen(Chan *c)
|
copen(Chan *c)
|
||||||
{
|
{
|
||||||
Mntcache *m, *f, **l;
|
Mntcache *m, *f, **l;
|
||||||
|
@ -195,19 +195,20 @@ copen(Chan *c)
|
||||||
/* directories aren't cacheable */
|
/* directories aren't cacheable */
|
||||||
if(c->qid.type&QTDIR){
|
if(c->qid.type&QTDIR){
|
||||||
c->mcp = nil;
|
c->mcp = nil;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock(&cache);
|
lock(&cache);
|
||||||
m = clookup(c, 1);
|
m = clookup(c, 0);
|
||||||
if(m == nil)
|
if(m != nil){
|
||||||
m = cache.head;
|
|
||||||
else if(m->qid.vers == c->qid.vers) {
|
|
||||||
ctail(m);
|
ctail(m);
|
||||||
unlock(&cache);
|
unlock(&cache);
|
||||||
c->mcp = m;
|
c->mcp = m;
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
m = clookup(c, 1);
|
||||||
|
if(m == nil)
|
||||||
|
m = cache.head;
|
||||||
ctail(m);
|
ctail(m);
|
||||||
|
|
||||||
l = &cache.hash[m->qid.path%NHASH];
|
l = &cache.hash[m->qid.path%NHASH];
|
||||||
|
@ -234,7 +235,7 @@ copen(Chan *c)
|
||||||
unlock(&cache);
|
unlock(&cache);
|
||||||
cacheunlock(m);
|
cacheunlock(m);
|
||||||
c->mcp = f;
|
c->mcp = f;
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,10 +252,9 @@ copen(Chan *c)
|
||||||
m->rah.vers = m->qid.vers;
|
m->rah.vers = m->qid.vers;
|
||||||
mntrahinit(&m->rah);
|
mntrahinit(&m->rah);
|
||||||
cnodata(m);
|
cnodata(m);
|
||||||
|
|
||||||
cacheunlock(m);
|
cacheunlock(m);
|
||||||
|
|
||||||
c->mcp = m;
|
c->mcp = m;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -482,6 +482,31 @@ cwrite(Chan* c, uchar *buf, int len, vlong off)
|
||||||
cachedata(m, buf, len, off);
|
cachedata(m, buf, len, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ctrunc(Chan *c)
|
||||||
|
{
|
||||||
|
Mntcache *m;
|
||||||
|
|
||||||
|
if(c->qid.type&QTDIR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if((c->flag&COPEN) == 0){
|
||||||
|
lock(&cache);
|
||||||
|
c->mcp = clookup(c, 0);
|
||||||
|
unlock(&cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
m = ccache(c);
|
||||||
|
if(m == nil)
|
||||||
|
return;
|
||||||
|
mntrahinit(&m->rah);
|
||||||
|
cnodata(m);
|
||||||
|
cacheunlock(m);
|
||||||
|
|
||||||
|
if((c->flag&COPEN) == 0)
|
||||||
|
c->mcp = nil;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cclunk(Chan *c)
|
cclunk(Chan *c)
|
||||||
{
|
{
|
||||||
|
|
|
@ -521,8 +521,11 @@ mntopencreate(int type, Chan *c, char *name, int omode, ulong perm)
|
||||||
poperror();
|
poperror();
|
||||||
mntfree(r);
|
mntfree(r);
|
||||||
|
|
||||||
if(c->flag & CCACHE)
|
if(c->flag & CCACHE){
|
||||||
copen(c);
|
if(copen(c))
|
||||||
|
if(type == Tcreate || (omode&OTRUNC) != 0)
|
||||||
|
ctrunc(c);
|
||||||
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -620,6 +623,11 @@ mntwstat(Chan *c, uchar *dp, int n)
|
||||||
mountrpc(m, r);
|
mountrpc(m, r);
|
||||||
poperror();
|
poperror();
|
||||||
mntfree(r);
|
mntfree(r);
|
||||||
|
|
||||||
|
if(c->flag & CCACHE)
|
||||||
|
if(GBIT64(&dp[STATFIXLEN-4*BIT16SZ-BIT64SZ]) != ~0ULL)
|
||||||
|
ctrunc(c);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,14 @@ void confinit(void);
|
||||||
int consactive(void);
|
int consactive(void);
|
||||||
void (*consdebug)(void);
|
void (*consdebug)(void);
|
||||||
void cpushutdown(void);
|
void cpushutdown(void);
|
||||||
void copen(Chan*);
|
int copen(Chan*);
|
||||||
void cclunk(Chan*);
|
void cclunk(Chan*);
|
||||||
Block* concatblock(Block*);
|
Block* concatblock(Block*);
|
||||||
Block* copyblock(Block*, int);
|
Block* copyblock(Block*, int);
|
||||||
void copypage(Page*, Page*);
|
void copypage(Page*, Page*);
|
||||||
void countpagerefs(ulong*, int);
|
void countpagerefs(ulong*, int);
|
||||||
int cread(Chan*, uchar*, int, vlong);
|
int cread(Chan*, uchar*, int, vlong);
|
||||||
|
void ctrunc(Chan*);
|
||||||
void cunmount(Chan*, Chan*);
|
void cunmount(Chan*, Chan*);
|
||||||
void cupdate(Chan*, uchar*, int, vlong);
|
void cupdate(Chan*, uchar*, int, vlong);
|
||||||
void cwrite(Chan*, uchar*, int, vlong);
|
void cwrite(Chan*, uchar*, int, vlong);
|
||||||
|
|
Loading…
Reference in a new issue