create doesn't touch parent director references

上级 11771df4
...@@ -89,6 +89,7 @@ struct inode* dirlookup(struct inode*, char*); ...@@ -89,6 +89,7 @@ struct inode* dirlookup(struct inode*, char*);
struct inode* ialloc(u32, short); struct inode* ialloc(u32, short);
struct inode* namei(inode *cwd, const char*); struct inode* namei(inode *cwd, const char*);
void iput(struct inode*); void iput(struct inode*);
void iput(inode* ip, bool haveref);
struct inode* iget(u32 dev, u32 inum); struct inode* iget(u32 dev, u32 inum);
void ilock(struct inode*, int writer); void ilock(struct inode*, int writer);
void iunlockput(struct inode*); void iunlockput(struct inode*);
......
...@@ -476,6 +476,13 @@ iunlock(struct inode *ip) ...@@ -476,6 +476,13 @@ iunlock(struct inode *ip)
release(&ip->lock); release(&ip->lock);
} }
void
iput(inode* ip, bool haveref)
{
if (haveref)
iput(ip);
}
// Caller holds reference to unlocked ip. Drop reference. // Caller holds reference to unlocked ip. Drop reference.
void void
iput(struct inode *ip) iput(struct inode *ip)
......
...@@ -224,53 +224,65 @@ create(inode *cwd, const char *path, short type, short major, short minor) ...@@ -224,53 +224,65 @@ create(inode *cwd, const char *path, short type, short major, short minor)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
char name[DIRSIZ]; char name[DIRSIZ];
bool haveref = false;
mt_ascope ascope("%s(%d.%d,%s,%d,%d,%d)", mt_ascope ascope("%s(%d.%d,%s,%d,%d,%d)",
__func__, cwd->dev, cwd->inum, __func__, cwd->dev, cwd->inum,
path, type, major, minor); path, type, major, minor);
retry: retry:
if((dp = nameiparent(cwd, path, name)) == 0) {
return 0; scoped_gc_epoch e;
if(dp->type != T_DIR) if((dp = __nameiparent(cwd, path, name, &haveref)) == 0)
panic("create"); return 0;
if((ip = dirlookup(dp, name)) != 0){ if(dp->type != T_DIR)
iput(dp); panic("create");
ilock(ip, 1);
if(type == T_FILE && ip->type == T_FILE) if((ip = dirlookup(dp, name)) != 0){
return ip; iput(dp, haveref);
iunlockput(ip); ilock(ip, 1);
return nullptr; if(type == T_FILE && ip->type == T_FILE)
} return ip;
iunlockput(ip);
if((ip = ialloc(dp->dev, type)) == nullptr) return nullptr;
return nullptr; }
ip->major = major; if((ip = ialloc(dp->dev, type)) == nullptr)
ip->minor = minor; return nullptr;
ip->link();
iupdate(ip); ip->major = major;
ip->minor = minor;
mtwriteavar("inode:%x.%x", ip->dev, ip->inum); ip->link();
iupdate(ip);
if(type == T_DIR){ // Create . and .. entries.
dp->link(); // for ".." mtwriteavar("inode:%x.%x", ip->dev, ip->inum);
iupdate(dp);
// No ip->nlink++ for ".": avoid cyclic ref count. if(type == T_DIR){ // Create . and .. entries.
if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) dp->link(); // for ".."
panic("create dots"); iupdate(dp);
} // No ip->nlink++ for ".": avoid cyclic ref count.
if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
panic("create dots");
}
if(dirlink(dp, name, ip->inum) < 0) {
// create race
ip->unlink();
iunlockput(ip);
iput(dp, haveref);
goto retry;
}
if(dirlink(dp, name, ip->inum) < 0) { if (!dp->valid()) {
// create race // XXX(sbw) we need to undo everything we just did
ip->unlink(); // (at least all the modifications to dp) and retry.
iunlockput(ip); panic("create: race");
iput(dp); }
goto retry;
} }
//nc_insert(dp, name, ip); //nc_insert(dp, name, ip);
iput(dp); iput(dp, haveref);
return ip; return ip;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论