fix: metanode mistakenly delete empty dir inode

If a directory is empty, the nlink of the dir inode is 2. And metanode
may mistakenly delete the inode upon receiving an iunlink request.

For example, if we are renaming a directory, the client will send ilink
and iunlink requests to the dir inode during the Rename process, and
this inode will be wrongly deleted after iunlink.

Signed-off-by: Shuoran Liu <shuoranliu@gmail.com>
This commit is contained in:
Shuoran Liu 2019-08-21 17:41:11 +08:00 committed by awzhgw
parent 6f05a78e23
commit 5477452974
2 changed files with 14 additions and 14 deletions

View File

@ -382,14 +382,11 @@ func (i *Inode) IncNLink() {
// DecNLink decreases the nLink value by one.
func (i *Inode) DecNLink() {
i.Lock()
if proto.IsDir(i.Type) {
if i.NLink > 2 {
i.NLink--
}
} else {
if i.NLink > 0 {
i.NLink--
}
if proto.IsDir(i.Type) && i.NLink == 2 {
i.NLink--
}
if i.NLink > 0 {
i.NLink--
}
i.Unlock()
}
@ -410,7 +407,7 @@ func (i *Inode) IsTempFile() bool {
func (i *Inode) IsEmptyDir() bool {
i.RLock()
ok := i.NLink == 2
ok := (proto.IsDir(i.Type) && i.NLink <= 2)
i.RUnlock()
return ok
}

View File

@ -122,7 +122,13 @@ func (mp *metaPartition) fsmUnlinkInode(ino *Inode) (resp *InodeResponse) {
inode.DoWriteFunc(func() {
inode.ModifyTime = ino.ModifyTime
})
if inode.IsEmptyDir() {
mp.inodeTree.Delete(inode)
}
inode.DecNLink()
if !proto.IsDir(inode.Type) {
if inode.IsTempFile() {
mp.freeList.Push(inode)
@ -130,9 +136,6 @@ func (mp *metaPartition) fsmUnlinkInode(ino *Inode) (resp *InodeResponse) {
return
}
if inode.IsEmptyDir() {
mp.inodeTree.Delete(inode)
}
return
}
@ -184,7 +187,7 @@ func (mp *metaPartition) fsmAppendExtents(ino *Inode) (status uint8) {
})
items = ino2.AppendExtents(items, ino.ModifyTime)
for _, item := range items {
log.LogInfof("fsmAppendExtents inode(%v) ext(%v)",ino2.Inode,item.(*proto.ExtentKey))
log.LogInfof("fsmAppendExtents inode(%v) ext(%v)", ino2.Inode, item.(*proto.ExtentKey))
mp.extDelCh <- item
}
return
@ -217,7 +220,7 @@ func (mp *metaPartition) fsmExtentsTruncate(ino *Inode) (resp *InodeResponse) {
i.ExtentsTruncate(delExtents, ino.Size, ino.ModifyTime)
// now we should delete the extent
for _, ext := range delExtents {
log.LogInfof("fsmExtentsTruncate inode(%v) ext(%v)",i.Inode,ext.(*proto.ExtentKey))
log.LogInfof("fsmExtentsTruncate inode(%v) ext(%v)", i.Inode, ext.(*proto.ExtentKey))
mp.extDelCh <- ext
}
return