mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Correctly update link and ref counts in rmdir.
Inotify sends events when a watch target is reaches a link count of 0 (see include/linux/fsnotify.h:fsnotify_inoderemove). Currently, we do not account for both dir/ and dir/.. in unlink, causing syscalls/linux/inotify.cc:WatchTargetDeletionGeneratesEvent to fail because the expected inotify events are not generated. Furthermore, we should DecRef() once the inode reaches zero links; otherwise, we will leak a reference. PiperOrigin-RevId: 313502091
This commit is contained in:
@@ -603,8 +603,10 @@ func (fs *filesystem) RmdirAt(ctx context.Context, rp *vfs.ResolvingPath) error
|
||||
return err
|
||||
}
|
||||
parentDir.removeChildLocked(child)
|
||||
parentDir.inode.decLinksLocked() // from child's ".."
|
||||
// Remove links for child, child/., and child/..
|
||||
child.inode.decLinksLocked()
|
||||
child.inode.decLinksLocked()
|
||||
parentDir.inode.decLinksLocked()
|
||||
vfsObj.CommitDeleteDentry(&child.vfsd)
|
||||
parentDir.inode.touchCMtime()
|
||||
return nil
|
||||
|
||||
@@ -209,11 +209,9 @@ type inode struct {
|
||||
// refs is a reference count. refs is accessed using atomic memory
|
||||
// operations.
|
||||
//
|
||||
// A reference is held on all inodes that are reachable in the filesystem
|
||||
// tree. For non-directories (which may have multiple hard links), this
|
||||
// means that a reference is dropped when nlink reaches 0. For directories,
|
||||
// nlink never reaches 0 due to the "." entry; instead,
|
||||
// filesystem.RmdirAt() drops the reference.
|
||||
// A reference is held on all inodes as long as they are reachable in the
|
||||
// filesystem tree, i.e. nlink is nonzero. This reference is dropped when
|
||||
// nlink reaches 0.
|
||||
refs int64
|
||||
|
||||
// xattrs implements extended attributes.
|
||||
@@ -276,14 +274,17 @@ func (i *inode) incLinksLocked() {
|
||||
atomic.AddUint32(&i.nlink, 1)
|
||||
}
|
||||
|
||||
// decLinksLocked decrements i's link count.
|
||||
// decLinksLocked decrements i's link count. If the link count reaches 0, we
|
||||
// remove a reference on i as well.
|
||||
//
|
||||
// Preconditions: filesystem.mu must be locked for writing. i.nlink != 0.
|
||||
func (i *inode) decLinksLocked() {
|
||||
if i.nlink == 0 {
|
||||
panic("tmpfs.inode.decLinksLocked() called with no existing links")
|
||||
}
|
||||
atomic.AddUint32(&i.nlink, ^uint32(0))
|
||||
if atomic.AddUint32(&i.nlink, ^uint32(0)) == 0 {
|
||||
i.decRef()
|
||||
}
|
||||
}
|
||||
|
||||
func (i *inode) incRef() {
|
||||
|
||||
Reference in New Issue
Block a user