Reference each inode with a non-zero nlink

上级 9f840849
...@@ -39,13 +39,16 @@ protected: ...@@ -39,13 +39,16 @@ protected:
}; };
// in-core file system types // in-core file system types
struct inode : public rcu_freed struct inode : public rcu_freed
{ {
static inode* alloc(u32 dev, u32 inum); static inode* alloc(u32 dev, u32 inum);
virtual void do_gc() { delete this; } virtual void do_gc() { delete this; }
void init(); void init();
void link();
void unlink();
short nlink();
inode& operator=(const inode&) = delete; inode& operator=(const inode&) = delete;
inode(const inode& x) = delete; inode(const inode& x) = delete;
...@@ -63,7 +66,6 @@ struct inode : public rcu_freed ...@@ -63,7 +66,6 @@ struct inode : public rcu_freed
short type; // copy of disk inode short type; // copy of disk inode
short major; short major;
short minor; short minor;
short nlink;
u32 size; u32 size;
u32 addrs[NDIRECT+1]; u32 addrs[NDIRECT+1];
...@@ -71,6 +73,8 @@ private: ...@@ -71,6 +73,8 @@ private:
inode(); inode();
~inode(); ~inode();
NEW_DELETE_OPS(inode) NEW_DELETE_OPS(inode)
short nlink_;
}; };
#define I_BUSYR 0x1 #define I_BUSYR 0x1
......
...@@ -193,7 +193,7 @@ ialloc(u32 dev, short type) ...@@ -193,7 +193,7 @@ ialloc(u32 dev, short type)
if(ip->type == 0){ if(ip->type == 0){
ip->type = type; ip->type = type;
ip->gen += 1; ip->gen += 1;
if(ip->nlink || ip->size || ip->addrs[0]) if(ip->nlink() || ip->size || ip->addrs[0])
panic("ialloc not zeroed"); panic("ialloc not zeroed");
iupdate(ip); iupdate(ip);
return ip; return ip;
...@@ -218,7 +218,7 @@ iupdate(struct inode *ip) ...@@ -218,7 +218,7 @@ iupdate(struct inode *ip)
dip->type = ip->type; dip->type = ip->type;
dip->major = ip->major; dip->major = ip->major;
dip->minor = ip->minor; dip->minor = ip->minor;
dip->nlink = ip->nlink; dip->nlink = ip->nlink();
dip->size = ip->size; dip->size = ip->size;
dip->gen = ip->gen; dip->gen = ip->gen;
memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); memmove(dip->addrs, ip->addrs, sizeof(ip->addrs));
...@@ -317,7 +317,7 @@ inode::init(void) ...@@ -317,7 +317,7 @@ inode::init(void)
type = dip->type; type = dip->type;
major = dip->major; major = dip->major;
minor = dip->minor; minor = dip->minor;
nlink = dip->nlink; nlink_ = dip->nlink;
size = dip->size; size = dip->size;
gen = dip->gen; gen = dip->gen;
memmove(addrs, dip->addrs, sizeof(addrs)); memmove(addrs, dip->addrs, sizeof(addrs));
...@@ -325,6 +325,32 @@ inode::init(void) ...@@ -325,6 +325,32 @@ inode::init(void)
flags |= I_VALID; flags |= I_VALID;
} }
void
inode::link(void)
{
// Must hold ilock if inode is accessible by multiple threads
if (++nlink_ == 1) {
// A non-zero nlink_ holds a reference to the inode
idup(this);
}
}
void
inode::unlink(void)
{
// Must hold ilock if inode is accessible by multiple threads
if (--nlink_ == 0) {
if (--ref == 0)
panic("inode::unlink last ref");
}
}
short
inode::nlink(void)
{
// Must hold ilock if inode is accessible by multiple threads
return nlink_;
}
// Increment reference count for ip. // Increment reference count for ip.
// Returns ip to enable ip = idup(ip1) idiom. // Returns ip to enable ip = idup(ip1) idiom.
...@@ -375,10 +401,10 @@ void ...@@ -375,10 +401,10 @@ void
iput(struct inode *ip) iput(struct inode *ip)
{ {
if(--ip->ref == 0) { if(--ip->ref == 0) {
if (ip->nlink)
return;
acquire(&ip->lock); acquire(&ip->lock);
if (ip->ref == 0 && ip->nlink == 0) { if (ip->nlink())
panic("iput: nlink %u\n", ip->nlink());
if (ip->ref == 0) {
// inode is no longer used: truncate and free inode. // inode is no longer used: truncate and free inode.
if(ip->flags & (I_BUSYR | I_BUSYW)) { if(ip->flags & (I_BUSYR | I_BUSYW)) {
// race with iget // race with iget
...@@ -547,7 +573,7 @@ stati(struct inode *ip, struct stat *st) ...@@ -547,7 +573,7 @@ stati(struct inode *ip, struct stat *st)
st->dev = ip->dev; st->dev = ip->dev;
st->ino = ip->inum; st->ino = ip->inum;
st->type = ip->type; st->type = ip->type;
st->nlink = ip->nlink; st->nlink = ip->nlink();
st->size = ip->size; st->size = ip->size;
} }
......
...@@ -225,7 +225,7 @@ sampstat(struct inode *ip, struct stat *st) ...@@ -225,7 +225,7 @@ sampstat(struct inode *ip, struct stat *st)
st->dev = ip->dev; st->dev = ip->dev;
st->ino = ip->inum; st->ino = ip->inum;
st->type = ip->type; st->type = ip->type;
st->nlink = ip->nlink; st->nlink = ip->nlink();
st->size = sz; st->size = sz;
} }
......
...@@ -124,7 +124,7 @@ sys_link(const char *old, const char *newn) ...@@ -124,7 +124,7 @@ sys_link(const char *old, const char *newn)
iunlockput(ip); iunlockput(ip);
return -1; return -1;
} }
ip->nlink++; ip->link();
iupdate(ip); iupdate(ip);
iunlock(ip); iunlock(ip);
...@@ -139,7 +139,7 @@ sys_link(const char *old, const char *newn) ...@@ -139,7 +139,7 @@ sys_link(const char *old, const char *newn)
bad: bad:
ilock(ip, 1); ilock(ip, 1);
ip->nlink--; ip->unlink();
iupdate(ip); iupdate(ip);
iunlockput(ip); iunlockput(ip);
return -1; return -1;
...@@ -189,7 +189,7 @@ sys_unlink(const char *path) ...@@ -189,7 +189,7 @@ sys_unlink(const char *path)
} }
ilock(ip, 1); ilock(ip, 1);
if(ip->nlink < 1) if(ip->nlink() < 1)
panic("unlink: nlink < 1"); panic("unlink: nlink < 1");
if(ip->type == T_DIR && !isdirempty(ip)){ if(ip->type == T_DIR && !isdirempty(ip)){
iunlockput(ip); iunlockput(ip);
...@@ -205,7 +205,7 @@ sys_unlink(const char *path) ...@@ -205,7 +205,7 @@ sys_unlink(const char *path)
if(ip->type == T_DIR){ if(ip->type == T_DIR){
ilock(dp, 1); ilock(dp, 1);
dp->nlink--; dp->unlink();
iupdate(dp); iupdate(dp);
iunlock(dp); iunlock(dp);
} }
...@@ -213,7 +213,7 @@ sys_unlink(const char *path) ...@@ -213,7 +213,7 @@ sys_unlink(const char *path)
//nc_invalidate(dp, name); //nc_invalidate(dp, name);
iput(dp); iput(dp);
ip->nlink--; ip->unlink();
iupdate(ip); iupdate(ip);
iunlockput(ip); iunlockput(ip);
return 0; return 0;
...@@ -248,13 +248,13 @@ create(inode *cwd, const char *path, short type, short major, short minor) ...@@ -248,13 +248,13 @@ create(inode *cwd, const char *path, short type, short major, short minor)
ip->major = major; ip->major = major;
ip->minor = minor; ip->minor = minor;
ip->nlink = 1; ip->link();
iupdate(ip); iupdate(ip);
mtwriteavar("inode:%x.%x", ip->dev, ip->inum); mtwriteavar("inode:%x.%x", ip->dev, ip->inum);
if(type == T_DIR){ // Create . and .. entries. if(type == T_DIR){ // Create . and .. entries.
dp->nlink++; // for ".." dp->link(); // for ".."
iupdate(dp); iupdate(dp);
// No ip->nlink++ for ".": avoid cyclic ref count. // No ip->nlink++ for ".": avoid cyclic ref count.
if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
...@@ -263,7 +263,7 @@ create(inode *cwd, const char *path, short type, short major, short minor) ...@@ -263,7 +263,7 @@ create(inode *cwd, const char *path, short type, short major, short minor)
if(dirlink(dp, name, ip->inum) < 0) { if(dirlink(dp, name, ip->inum) < 0) {
// create race // create race
ip->nlink--; ip->unlink();
iunlockput(ip); iunlockput(ip);
iput(dp); iput(dp);
goto retry; goto retry;
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论