Reference each inode with a non-zero nlink

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