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

convert all namespace uses to c++

usertests still pass ugly hack in file.h for kernlet.c
上级 229d25d4
...@@ -56,7 +56,6 @@ OBJS = \ ...@@ -56,7 +56,6 @@ OBJS = \
memide.o \ memide.o \
mp.o \ mp.o \
net.o \ net.o \
ns.o \
pci.o \ pci.o \
picirq.o \ picirq.o \
pipe.o \ pipe.o \
......
...@@ -9,7 +9,11 @@ extern "C" { ...@@ -9,7 +9,11 @@ extern "C" {
#include "spinlock.h" #include "spinlock.h"
#include "fs.h" #include "fs.h"
#include "condvar.h" #include "condvar.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "amd64.h" #include "amd64.h"
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
......
...@@ -13,6 +13,20 @@ class pair { ...@@ -13,6 +13,20 @@ class pair {
} }
}; };
template<int N>
class strbuf {
public:
char _buf[N];
strbuf(const char *s) {
strncpy(_buf, s, N);
}
bool operator==(const strbuf<N> &other) {
return !strncmp(_buf, other._buf, N);
}
};
template<class A, class B> template<class A, class B>
pair<A, B> pair<A, B>
mkpair(const A &a, const B &b) mkpair(const A &a, const B &b)
......
...@@ -9,7 +9,11 @@ extern "C" { ...@@ -9,7 +9,11 @@ extern "C" {
#include "amd64.h" #include "amd64.h"
#include "stat.h" #include "stat.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "elf.h" #include "elf.h"
#include "cpu.h" #include "cpu.h"
#include "vm.h" #include "vm.h"
......
...@@ -4,7 +4,11 @@ extern "C" { ...@@ -4,7 +4,11 @@ extern "C" {
#include "condvar.h" #include "condvar.h"
#include "kernel.h" #include "kernel.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "stat.h" #include "stat.h"
#include "net.h" #include "net.h"
} }
......
#ifdef __cplusplus
#include "cpputil.hh"
#include "ns.hh"
u64 namehash(const strbuf<DIRSIZ>&);
#endif
struct file { struct file {
enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type; enum { FD_NONE, FD_PIPE, FD_INODE, FD_SOCKET } type;
int ref; // reference count int ref; // reference count
...@@ -23,7 +30,11 @@ struct inode { ...@@ -23,7 +30,11 @@ struct inode {
struct condvar cv; struct condvar cv;
struct spinlock lock; struct spinlock lock;
char lockname[16]; char lockname[16];
struct ns *dir; #ifdef __cplusplus
xns<strbuf<DIRSIZ>, u32, namehash> *dir;
#else
void *dir;
#endif
short type; // copy of disk inode short type; // copy of disk inode
short major; short major;
......
...@@ -21,13 +21,14 @@ extern "C" { ...@@ -21,13 +21,14 @@ extern "C" {
#include "proc.h" #include "proc.h"
#include "buf.h" #include "buf.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "cpu.h" #include "cpu.h"
} }
#include "cpputil.hh"
#include "ns.hh"
#define min(a, b) ((a) < (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b))
static void itrunc(struct inode*); static void itrunc(struct inode*);
...@@ -225,9 +226,9 @@ ifree(void *arg) ...@@ -225,9 +226,9 @@ ifree(void *arg)
struct inode *ip = (inode*) arg; struct inode *ip = (inode*) arg;
if (ip->dir) { if (ip->dir) {
ns_remove(ip->dir, KD("."), 0); ip->dir->remove(strbuf<DIRSIZ>("."));
ns_remove(ip->dir, KD(".."), 0); ip->dir->remove(strbuf<DIRSIZ>(".."));
nsfree(ip->dir); gc_delayed(ip->dir, del_rcu_freed);
ip->dir = 0; ip->dir = 0;
} }
...@@ -589,6 +590,12 @@ namecmp(const char *s, const char *t) ...@@ -589,6 +590,12 @@ namecmp(const char *s, const char *t)
return strncmp(s, t, DIRSIZ); return strncmp(s, t, DIRSIZ);
} }
u64
namehash(const strbuf<DIRSIZ> &n)
{
return n._buf[0]; /* XXX */
}
void void
dir_init(struct inode *dp) dir_init(struct inode *dp)
{ {
...@@ -597,7 +604,7 @@ dir_init(struct inode *dp) ...@@ -597,7 +604,7 @@ dir_init(struct inode *dp)
if (dp->type != T_DIR) if (dp->type != T_DIR)
panic("dir_init not DIR"); panic("dir_init not DIR");
struct ns *dir = nsalloc(0); auto dir = new xns<strbuf<DIRSIZ>, u32, namehash>(false);
for (u32 off = 0; off < dp->size; off += BSIZE) { for (u32 off = 0; off < dp->size; off += BSIZE) {
struct buf *bp = bread(dp->dev, bmap(dp, off / BSIZE), 0); struct buf *bp = bread(dp->dev, bmap(dp, off / BSIZE), 0);
for (struct dirent *de = (struct dirent *) bp->data; for (struct dirent *de = (struct dirent *) bp->data;
...@@ -606,37 +613,16 @@ dir_init(struct inode *dp) ...@@ -606,37 +613,16 @@ dir_init(struct inode *dp)
if (de->inum == 0) if (de->inum == 0)
continue; continue;
ns_insert(dir, KD(de->name), (void*) (u64) de->inum); dir->insert(strbuf<DIRSIZ>(de->name), de->inum);
} }
brelse(bp, 0); brelse(bp, 0);
} }
if (!__sync_bool_compare_and_swap(&dp->dir, 0, dir)) { if (!__sync_bool_compare_and_swap(&dp->dir, 0, dir)) {
// free all the dirents // XXX free all the dirents
nsfree(dir); delete dir;
} }
} }
struct flush_state {
struct inode *dp;
u32 off;
};
static void *
dir_flush_cb(void *key, void *val, void *arg)
{
struct flush_state *fs = (flush_state*) arg;
char *name = (char*) key;
u32 inum = (u64) val;
struct dirent de;
strncpy(de.name, name, DIRSIZ);
de.inum = inum;
if(writei(fs->dp, (char*)&de, fs->off, sizeof(de)) != sizeof(de))
panic("dir_flush_cb");
fs->off += sizeof(de);
return 0;
}
void void
dir_flush(struct inode *dp) dir_flush(struct inode *dp)
{ {
...@@ -645,10 +631,16 @@ dir_flush(struct inode *dp) ...@@ -645,10 +631,16 @@ dir_flush(struct inode *dp)
if (!dp->dir) if (!dp->dir)
return; return;
struct flush_state fs; u32 off = 0;
fs.dp = dp; dp->dir->enumerate([dp, &off](const strbuf<DIRSIZ> &name, const u32 &inum) {
fs.off = 0; struct dirent de;
ns_enumerate(dp->dir, dir_flush_cb, &fs); strncpy(de.name, name._buf, DIRSIZ);
de.inum = inum;
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
panic("dir_flush_cb");
off += sizeof(de);
return false;
});
} }
// Look for a directory entry in a directory. // Look for a directory entry in a directory.
...@@ -657,8 +649,7 @@ dirlookup(struct inode *dp, char *name) ...@@ -657,8 +649,7 @@ dirlookup(struct inode *dp, char *name)
{ {
dir_init(dp); dir_init(dp);
void *vinum = ns_lookup(dp->dir, KD(name)); u32 inum = dp->dir->lookup(strbuf<DIRSIZ>(name));
u32 inum = (u64) vinum;
//cprintf("dirlookup: %x (%d): %s -> %d\n", dp, dp->inum, name, inum); //cprintf("dirlookup: %x (%d): %s -> %d\n", dp, dp->inum, name, inum);
if (inum == 0) if (inum == 0)
...@@ -674,7 +665,7 @@ dirlink(struct inode *dp, const char *name, u32 inum) ...@@ -674,7 +665,7 @@ dirlink(struct inode *dp, const char *name, u32 inum)
dir_init(dp); dir_init(dp);
//cprintf("dirlink: %x (%d): %s -> %d\n", dp, dp->inum, name, inum); //cprintf("dirlink: %x (%d): %s -> %d\n", dp, dp->inum, name, inum);
return ns_insert(dp->dir, KD(name), (void*)(u64)inum); return dp->dir->insert(strbuf<DIRSIZ>(name), inum);
} }
// Paths // Paths
......
...@@ -184,50 +184,6 @@ void netrx(void *va, u16 len); ...@@ -184,50 +184,6 @@ void netrx(void *va, u16 len);
int nettx(void *va, u16 len); int nettx(void *va, u16 len);
void nethwaddr(u8 *hwaddr); void nethwaddr(u8 *hwaddr);
// ns.c
enum {
nskey_int = 1,
nskey_ii,
nskey_str,
nskey_dirname,
nskey_iis
};
struct nskey {
int type;
union {
u64 i;
struct {
u64 a;
u64 b;
} ii;
char *s;
const char *dirname;
struct {
u64 a;
u64 b;
char *s;
} iis;
} u;
};
#define KI(v) (struct nskey){type: nskey_int, u: { i: v }}
#define KII(x,y) (struct nskey){type: nskey_ii, u: {ii: {a:x, b:y}}}
#define KS(v) (struct nskey){.type=nskey_str,.u.s=v}
#define KD(v) (struct nskey){type: nskey_dirname, u: { dirname: v }}
#define KIIS(x,y,z) (struct nskey){.type=nskey_iis,.u.iis.a=x, \
.u.iis.b=y, \
.u.iis.s=z}
struct ns* nsalloc(int allowdup);
void nsfree(struct ns*);
u64 ns_allockey(struct ns*);
int ns_insert(struct ns*, struct nskey key, void*);
void* ns_lookup(struct ns*, struct nskey key);
void* ns_remove(struct ns *ns, struct nskey key, void *val); // removed val
void* ns_enumerate(struct ns *ns, void *(*f)(void *, void *, void *), void *arg);
void* ns_enumerate_key(struct ns *ns, struct nskey key, void *(*f)(void *, void *), void *arg);
// picirq.c // picirq.c
void picenable(int); void picenable(int);
void piceoi(void); void piceoi(void);
......
//
// file-system name cache
//
// to do:
// eviction
// maybe generation #s don't need to be in on-disk inode
// if namecache only referred to cached inodes
//
#include "types.h"
#include "defs.h"
#include "stat.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
#include "queue.h"
#include "proc.h"
#include "buf.h"
#include "fs.h"
#include "file.h"
struct spinlock nc_lock;
struct ns *ncns;
// map the tuple <dev,dinum,name> to cinum;
struct nce {
uint cinum; // child inumber
uint gen; // child ip->gen
};
void
nc_init()
{
ncns = nsalloc(0);
initlock(&nc_lock, "namecache");
}
struct inode *
nc_lookup(struct inode *dir, char *name)
{
rcu_begin_read();
struct nce *e = ns_lookup(ncns, KIIS(dir->dev, dir->inum, name));
if (!e)
return 0;
struct inode *ip = iget(dir->dev, e->cinum);
// this is a bit ugly
// maybe there should be a real inode cache and
// the namecache should contain direct refs.
int ok = (ip->gen == e->gen);
rcu_end_read();
if(ok){
return ip;
} else {
iput(ip);
return 0;
}
}
// dir is locked, but ip is not.
void
nc_insert(struct inode *dir, char *name, struct inode *ip)
{
// though ip is not locked, it's still OK to
// look at ip->gen.
rcu_begin_read();
struct nce *e = ns_lookup(ncns, KIIS(dir->dev, dir->inum, name));
if(e){
if(e->cinum != ip->inum || e->gen != ip->gen){
// someone forgot to call nc_invalidate()
panic("nc_insert change");
}
rcu_end_read();
return;
}
rcu_end_read();
e = kmalloc(sizeof(*e));
e->cinum = ip->inum;
e->gen = ip->gen;
ns_insert(ncns, KIIS(dir->dev, dir->inum, name), e);
}
void
nc_invalidate(struct inode *dir, char *name)
{
ns_remove(ncns, KIIS(dir->dev, dir->inum, name), 0);
}
...@@ -23,7 +23,11 @@ extern "C" { ...@@ -23,7 +23,11 @@ extern "C" {
#endif #endif
#include "proc.h" #include "proc.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "net.h" #include "net.h"
err_t if_init(struct netif *netif); err_t if_init(struct netif *netif);
......
extern "C" {
#include "types.h"
#include "kernel.h"
#include "spinlock.h"
#include "fs.h"
#include <stddef.h>
}
// name spaces
// XXX maybe use open hash table, no chain, better cache locality
#if SPINLOCK_DEBUG
#define NHASH 10
#else
#define NHASH 100
#endif
struct elem {
void *val;
int next_lock;
struct elem * volatile next;
union {
u64 ikey;
struct {
u64 a;
u64 b;
} iikey;
char skey[0];
char dnkey[DIRSIZ];
struct {
u64 a;
u64 b;
char s[0];
} iiskey;
};
};
struct bucket {
struct elem * volatile chain;
} __attribute__((aligned (CACHELINE)));
struct ns {
int allowdup;
u64 nextkey;
struct bucket table[NHASH];
};
// XXX should be using our missing scalable allocator module
struct ns*
nsalloc(int allowdup)
{
struct ns *ns = 0;
ns = (struct ns*) kmalloc(sizeof(struct ns));
if (ns == 0)
panic("nsalloc");
memset(ns, 0, sizeof(struct ns));
ns->nextkey = 1;
ns->allowdup = allowdup;
return ns;
}
static void *
any(void *x, void *y, void *arg)
{
return (void*) 1;
}
void
nsfree(struct ns *ns)
{
if (ns_enumerate(ns, &any, 0))
panic("nsfree: not empty");
gc_delayed(ns, kmfree);
}
static struct elem *
elemalloc(struct nskey *k)
{
struct elem *e = 0;
int sz;
switch (k->type) {
case nskey_int:
sz = offsetof(struct elem, ikey) + sizeof(e->ikey);
break;
case nskey_ii:
sz = offsetof(struct elem, iikey) + sizeof(e->iikey);
break;
case nskey_str:
sz = offsetof(struct elem, skey) + strlen(k->u.s) + 1;
break;
case nskey_dirname:
sz = offsetof(struct elem, dnkey) + sizeof(e->dnkey);
break;
case nskey_iis:
sz = offsetof(struct elem, iiskey.s) + strlen(k->u.iis.s) + 1;
break;
default:
panic("key type");
}
e = (elem*) kmalloc(sz);
if (e == 0)
return 0;
memset(e, 0, sz);
return e;
}
static u64
h(struct nskey *k)
{
switch (k->type) {
case nskey_int:
return k->u.i % NHASH;
case nskey_ii:
return (k->u.ii.a ^ k->u.ii.b) % NHASH;
case nskey_str:
return k->u.s[0] % NHASH; // XXX
case nskey_dirname:
return k->u.dirname[0] % NHASH; // XXX
case nskey_iis:
return (k->u.iis.a ^ k->u.iis.b ^ k->u.iis.s[0]) % NHASH;
default:
panic("key type");
}
}
static void
setkey(struct elem *e, struct nskey *k)
{
switch (k->type) {
case nskey_int:
e->ikey = k->u.i;
break;
case nskey_ii:
e->iikey.a = k->u.ii.a;
e->iikey.b = k->u.ii.b;
break;
case nskey_str:
strncpy(e->skey, k->u.s, strlen(k->u.s) + 1);
break;
case nskey_dirname:
strncpy(e->dnkey, k->u.dirname, DIRSIZ);
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;
default:
panic("key type");
}
}
static int
cmpkey(struct elem *e, struct nskey *k)
{
switch (k->type) {
case nskey_int:
return e->ikey == k->u.i;
case nskey_ii:
return e->iikey.a == k->u.ii.a && e->iikey.b == k->u.ii.b;
case nskey_str:
return !strcmp(e->skey, k->u.s);
case nskey_dirname:
return !namecmp(e->dnkey, k->u.dirname);
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:
panic("key type");
}
}
// XXX need something more scalable; partition the name space?
u64
ns_allockey(struct ns *ns)
{
u64 n = __sync_fetch_and_add(&ns->nextkey, 1);
return n;
}
int
ns_insert(struct ns *ns, struct nskey key, void *val)
{
struct elem *e = elemalloc(&key);
if (e) {
setkey(e, &key);
e->val = val;
u64 i = h(&key);
gc_begin_epoch();
retry:
(void) 0;
struct elem *root = ns->table[i].chain;
if (!ns->allowdup) {
for (struct elem *x = root; x; x = x->next) {
if (cmpkey(x, &key)) {
gc_end_epoch();
gc_delayed(e, kmfree);
return -1;
}
}
}
e->next = root;
if (!__sync_bool_compare_and_swap(&ns->table[i].chain, root, e))
goto retry;
gc_end_epoch();
return 0;
}
return -1;
}
void*
ns_lookup(struct ns *ns, struct nskey key)
{
u64 i = h(&key);
gc_begin_epoch();
struct elem *e = ns->table[i].chain;
while (e != NULL) {
if (cmpkey(e, &key)) {
gc_end_epoch();
return e->val;
}
e = e->next;
}
gc_end_epoch();
return 0;
}
void*
ns_remove(struct ns *ns, struct nskey key, void *v)
{
u64 i = h(&key);
gc_begin_epoch();
retry:
(void) 0;
int fakelock = 0;
int *pelock = &fakelock;
struct elem * volatile * pe = &ns->table[i].chain;
for (;;) {
struct elem *e = *pe;
if (!e)
break;
if (cmpkey(e, &key) && (e->val == v || v == 0)) {
// XXX annotate as locks for mtrace
if (!__sync_bool_compare_and_swap(&e->next_lock, 0, 1))
goto retry;
if (!__sync_bool_compare_and_swap(pelock, 0, 1)) {
e->next_lock = 0;
goto retry;
}
if (!__sync_bool_compare_and_swap(pe, e, e->next)) {
*pelock = 0;
e->next_lock = 0;
goto retry;
}
*pelock = 0;
void *v = e->val;
gc_end_epoch();
gc_delayed(e, kmfree);
return v;
}
pe = &e->next;
pelock = &e->next_lock;
}
gc_end_epoch();
return 0;
}
void *
ns_enumerate(struct ns *ns, void *(*f)(void *, void *, void *), void *arg)
{
gc_begin_epoch();
for (int i = 0; i < NHASH; i++) {
struct elem *e = ns->table[i].chain;
while (e != NULL) {
void *r = (*f)(&e->ikey, e->val, arg);
if (r) {
gc_end_epoch();
return r;
}
e = e->next;
}
}
gc_end_epoch();
return 0;
}
void *
ns_enumerate_key(struct ns *ns, struct nskey key, void *(*f)(void *, void *), void *arg)
{
u64 i = h(&key);
gc_begin_epoch();
struct elem *e = ns->table[i].chain;
while (e) {
if (cmpkey(e, &key)) {
void *r = (*f)(e->val, arg);
if (r) {
gc_end_epoch();
return r;
}
}
e = e->next;
}
gc_end_epoch();
return 0;
}
...@@ -35,7 +35,7 @@ struct xbucket { ...@@ -35,7 +35,7 @@ struct xbucket {
} __attribute__((aligned (CACHELINE))); } __attribute__((aligned (CACHELINE)));
template<class K, class V, u64 (*HF)(const K&)> template<class K, class V, u64 (*HF)(const K&)>
class xns { class xns : public rcu_freed {
private: private:
bool allowdup; bool allowdup;
u64 nextkey; u64 nextkey;
......
...@@ -7,7 +7,11 @@ extern "C" { ...@@ -7,7 +7,11 @@ extern "C" {
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "cpu.h" #include "cpu.h"
} }
......
...@@ -4,7 +4,11 @@ extern "C" { ...@@ -4,7 +4,11 @@ extern "C" {
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "prof.h" #include "prof.h"
#include "bits.h" #include "bits.h"
#include "amd64.h" #include "amd64.h"
......
...@@ -3,8 +3,12 @@ extern "C" { ...@@ -3,8 +3,12 @@ extern "C" {
#include "spinlock.h" #include "spinlock.h"
#include "condvar.h" #include "condvar.h"
#include "fs.h" #include "fs.h"
#include "file.h"
#include "kernel.h" #include "kernel.h"
}
#include "file.h"
extern "C" {
#include "bits.h" #include "bits.h"
#include "amd64.h" #include "amd64.h"
#include "cpu.h" #include "cpu.h"
......
...@@ -10,9 +10,10 @@ extern "C" { ...@@ -10,9 +10,10 @@ extern "C" {
#include "mtrace.h" #include "mtrace.h"
#include "condvar.h" #include "condvar.h"
#include "fs.h" #include "fs.h"
#include "file.h"
} }
#include "file.h"
#if LOCKSTAT #if LOCKSTAT
static int lockstat_enable; static int lockstat_enable;
......
...@@ -8,7 +8,11 @@ extern "C" { ...@@ -8,7 +8,11 @@ extern "C" {
#include "queue.h" #include "queue.h"
#include "proc.h" #include "proc.h"
#include "fs.h" #include "fs.h"
}
#include "file.h" #include "file.h"
extern "C" {
#include "fcntl.h" #include "fcntl.h"
#include "cpu.h" #include "cpu.h"
#include "net.h" #include "net.h"
...@@ -174,22 +178,20 @@ bad: ...@@ -174,22 +178,20 @@ bad:
} }
// Is the directory dp empty except for "." and ".." ? // Is the directory dp empty except for "." and ".." ?
static void*
check_empty(void *k, void *v, void *arg)
{
char *name = (char*) k;
if (strcmp(name, ".") && strcmp(name, ".."))
return (void*)1;
return 0;
}
static int static int
isdirempty(struct inode *dp) isdirempty(struct inode *dp)
{ {
dir_init(dp); dir_init(dp);
if (ns_enumerate(dp->dir, check_empty, 0)) int empty = 1;
return 0; dp->dir->enumerate([&empty](const strbuf<DIRSIZ> &name, u64 ino) {
return 1; if (!strcmp(name._buf, "."))
return false;
if (!strcmp(name._buf, ".."))
return false;
empty = 0;
return true;
});
return empty;
} }
long long
...@@ -227,7 +229,7 @@ sys_unlink(void) ...@@ -227,7 +229,7 @@ sys_unlink(void)
} }
dir_init(dp); dir_init(dp);
if (ns_remove(dp->dir, KD(name), (void*)(u64)ip->inum) == 0) { if (dp->dir->remove(strbuf<DIRSIZ>(name), &ip->inum) == 0) {
iunlockput(ip); iunlockput(ip);
goto retry; goto retry;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论