提交 22bc17ed 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

use namespace for dentry cache (namecache)

上级 2744a423
...@@ -103,7 +103,7 @@ enum { ...@@ -103,7 +103,7 @@ enum {
nskey_int = 1, nskey_int = 1,
nskey_ii, nskey_ii,
nskey_str, nskey_str,
nskey_iistr nskey_iis
}; };
struct nskey { struct nskey {
...@@ -115,12 +115,20 @@ struct nskey { ...@@ -115,12 +115,20 @@ struct nskey {
uint b; uint b;
} ii; } ii;
char *s; char *s;
struct {
uint a;
uint b;
char *s;
} iis;
} u; } u;
}; };
#define KI(v) (struct nskey){.type=nskey_int,.u.i=v} #define KI(v) (struct nskey){.type=nskey_int,.u.i=v}
#define KII(x,y) (struct nskey){.type=nskey_ii,.u.ii.a=x,.u.ii.b=y} #define KII(x,y) (struct nskey){.type=nskey_ii,.u.ii.a=x,.u.ii.b=y}
#define KS(v) (struct nskey){.type=nskey_str,.u.s=v} #define KS(v) (struct nskey){.type=nskey_str,.u.s=v}
#define KIIS(x,y,z) (struct nskey){.type=nskey_iis,.u.iis.a=x, \
.u.iis.b=y, \
.u.iis.s=z}
void nsinit(void); void nsinit(void);
struct ns* nsalloc(int allowdup); struct ns* nsalloc(int allowdup);
......
...@@ -2,12 +2,9 @@ ...@@ -2,12 +2,9 @@
// file-system name cache // file-system name cache
// //
// to do: // to do:
// use ns.c namespaces // eviction
// maybe generation #s don't need to be in on-disk inode // maybe generation #s don't need to be in on-disk inode
// if namecache only referred to cached inodes // if namecache only referred to cached inodes
// insert when file created, not just looked up
// eviction
// verify that it hits when it is supposed to
// //
#include "types.h" #include "types.h"
...@@ -24,66 +21,39 @@ ...@@ -24,66 +21,39 @@
#include "file.h" #include "file.h"
struct spinlock nc_lock; struct spinlock nc_lock;
struct ns *ncns;
// map the tuple <dev,dinum,name> to cinum; // map the tuple <dev,dinum,name> to cinum;
struct nce { struct nce {
int valid;
uint dev;
uint dinum; // directory inumber
char name[DIRSIZ];
uint cinum; // child inumber uint cinum; // child inumber
uint gen; // child ip->gen uint gen; // child ip->gen
}; };
#define NCE 128
struct nce nce[NCE];
void void
nc_init() nc_init()
{ {
ncns = nsalloc(0);
initlock(&nc_lock, "namecache"); initlock(&nc_lock, "namecache");
} }
// nc_lock must be held
struct nce *
nc_lookup1(struct inode *dir, char *name)
{
for(int i = 0; i < NCE; i++){
struct nce *e = &nce[i];
if(e->valid && e->dev == dir->dev && e->dinum == dir->inum &&
namecmp(name, e->name) == 0){
return e;
}
}
return 0;
}
struct inode * struct inode *
nc_lookup(struct inode *dir, char *name) nc_lookup(struct inode *dir, char *name)
{ {
uint inum = 0; rcu_begin_read();
uint gen = 0; struct nce *e = ns_lookup(ncns, KIIS(dir->dev, dir->inum, name));
if (!e)
acquire(&nc_lock); return 0;
struct nce *e = nc_lookup1(dir, name);
if(e){
inum = e->cinum;
gen = e->gen;
}
release(&nc_lock);
if(inum){ struct inode *ip = iget(dir->dev, e->cinum);
struct inode *ip = iget(dir->dev, inum); // this is a bit ugly
// this is a bit ugly // maybe there should be a real inode cache and
// maybe there should be a real inode cache and // the namecache should contain direct refs.
// the namecache should contain direct refs. int ok = (ip->gen == e->gen);
int ok = (ip->gen == gen); rcu_end_read();
if(ok){ if(ok){
return ip; return ip;
} else {
iput(ip);
return 0;
}
} else { } else {
iput(ip);
return 0; return 0;
} }
} }
...@@ -95,43 +65,26 @@ nc_insert(struct inode *dir, char *name, struct inode *ip) ...@@ -95,43 +65,26 @@ nc_insert(struct inode *dir, char *name, struct inode *ip)
// though ip is not locked, it's still OK to // though ip is not locked, it's still OK to
// look at ip->gen. // look at ip->gen.
acquire(&nc_lock); rcu_begin_read();
struct nce *e = ns_lookup(ncns, KIIS(dir->dev, dir->inum, name));
struct nce *e = nc_lookup1(dir, name);
if(e){ if(e){
if(e->cinum != ip->inum || e->gen != ip->gen){ if(e->cinum != ip->inum || e->gen != ip->gen){
// someone forgot to call nc_invalidate() // someone forgot to call nc_invalidate()
panic("nc_insert change"); panic("nc_insert change");
} }
release(&nc_lock); rcu_end_read();
return; return;
} }
rcu_end_read();
int i; e = kmalloc(sizeof(*e));
for(i = 0; i < NCE; i++){ e->cinum = ip->inum;
e = &nce[i]; e->gen = ip->gen;
if(e->valid == 0){ ns_insert(ncns, KIIS(dir->dev, dir->inum, name), e);
e->valid = 1;
e->dev = dir->dev;
e->dinum = dir->inum;
strncpy(e->name, name, DIRSIZ);
e->cinum = ip->inum;
e->gen = ip->gen;
break;
}
}
if(i >= NCE)
cprintf("namecache full\n");
release(&nc_lock);
} }
void void
nc_invalidate(struct inode *dir, char *name) nc_invalidate(struct inode *dir, char *name)
{ {
acquire(&nc_lock); ns_remove(ncns, KIIS(dir->dev, dir->inum, name), 0);
struct nce *e = nc_lookup1(dir, name);
if(e)
e->valid = 0;
release(&nc_lock);
} }
...@@ -24,6 +24,11 @@ struct elem { ...@@ -24,6 +24,11 @@ struct elem {
uint b; uint b;
} iikey; } iikey;
char skey[0]; char skey[0];
struct {
uint a;
uint b;
char s[0];
} iiskey;
}; };
}; };
...@@ -72,10 +77,13 @@ elemalloc(struct nskey *k) ...@@ -72,10 +77,13 @@ elemalloc(struct nskey *k)
case nskey_str: case nskey_str:
sz = offsetof(struct elem, skey) + strlen(k->u.s) + 1; sz = offsetof(struct elem, skey) + strlen(k->u.s) + 1;
break; break;
case nskey_iis:
sz = offsetof(struct elem, iiskey.s) + strlen(k->u.iis.s) + 1;
break;
default: default:
panic("key type"); panic("key type");
} }
e = kmalloc(sz); e = kmalloc(sz);
if (e == 0) if (e == 0)
return 0; return 0;
...@@ -93,6 +101,8 @@ h(struct nskey *k) ...@@ -93,6 +101,8 @@ h(struct nskey *k)
return (k->u.ii.a ^ k->u.ii.b) % NHASH; return (k->u.ii.a ^ k->u.ii.b) % NHASH;
case nskey_str: case nskey_str:
return k->u.s[0] % NHASH; // XXX return k->u.s[0] % NHASH; // XXX
case nskey_iis:
return (k->u.iis.a ^ k->u.iis.b ^ k->u.iis.s[0]) % NHASH;
default: default:
panic("key type"); panic("key type");
} }
...@@ -110,7 +120,12 @@ setkey(struct elem *e, struct nskey *k) ...@@ -110,7 +120,12 @@ setkey(struct elem *e, struct nskey *k)
e->iikey.b = k->u.ii.b; e->iikey.b = k->u.ii.b;
break; break;
case nskey_str: case nskey_str:
strncpy(e->skey, k->u.s, __INT_MAX__); strncpy(e->skey, k->u.s, strlen(k->u.s) + 1);
break;
case nskey_iis:
e->iiskey.a = k->u.iis.a;
e->iiskey.b = k->u.iis.b;
strncpy(e->iiskey.s, k->u.iis.s, strlen(k->u.iis.s) + 1);
break; break;
default: default:
panic("key type"); panic("key type");
...@@ -127,6 +142,10 @@ cmpkey(struct elem *e, struct nskey *k) ...@@ -127,6 +142,10 @@ cmpkey(struct elem *e, struct nskey *k)
return e->iikey.a == k->u.ii.a && e->iikey.b == k->u.ii.b; return e->iikey.a == k->u.ii.a && e->iikey.b == k->u.ii.b;
case nskey_str: case nskey_str:
return !strcmp(e->skey, k->u.s); return !strcmp(e->skey, k->u.s);
case nskey_iis:
return e->iiskey.a == k->u.iis.a &&
e->iiskey.b == k->u.iis.b &&
!strcmp(e->iiskey.s, k->u.iis.s);
default: default:
panic("key type"); panic("key type");
} }
......
...@@ -135,6 +135,8 @@ sys_link(void) ...@@ -135,6 +135,8 @@ sys_link(void)
iunlockput(dp); iunlockput(dp);
goto bad; goto bad;
} }
nc_insert(dp, name, ip);
iunlockput(dp); iunlockput(dp);
iput(ip); iput(ip);
return 0; return 0;
...@@ -258,6 +260,7 @@ create(char *path, short type, short major, short minor) ...@@ -258,6 +260,7 @@ create(char *path, short type, short major, short minor)
if(dirlink(dp, name, ip->inum) < 0) if(dirlink(dp, name, ip->inum) < 0)
panic("create: dirlink"); panic("create: dirlink");
nc_insert(dp, name, ip);
iunlockput(dp); iunlockput(dp);
return ip; return ip;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论