Hold a reference while calling p9.pathNode.removeWithName() callback.

This prevents a racing clunk() call from destroying the file while the callback
is running, leading to potential data races.

PiperOrigin-RevId: 426180506
This commit is contained in:
Nicolas Lacasse
2022-02-03 10:29:42 -08:00
committed by gVisor bot
parent 95d883a92e
commit 34f41dfcbf
2 changed files with 24 additions and 1 deletions
+10 -1
View File
@@ -216,8 +216,17 @@ func (p *pathNode) removeWithName(name string, fn func(ref *fidRef)) *pathNode {
for ref := range m {
delete(m, ref)
delete(p.childRefNames, ref)
if fn != nil {
if fn == nil {
// No callback provided.
continue
}
// Attempt to hold a reference while calling fn() to
// prevent concurrent destruction of the child, which
// can lead to data races. If the child has already
// been destroyed, then we can skip the callback.
if ref.TryIncRef() {
fn(ref)
ref.DecRef()
}
}
}
+14
View File
@@ -205,6 +205,20 @@ func (f *fidRef) DecRef() {
}
}
// TryIncRef returns true if a new reference is taken on the fid, and false if
// the fid has been destroyed.
func (f *fidRef) TryIncRef() bool {
for {
r := atomic.LoadInt64(&f.refs)
if r <= 0 {
return false
}
if atomic.CompareAndSwapInt64(&f.refs, r, r+1) {
return true
}
}
}
// isDeleted returns true if this fidRef has been deleted.
//
// Precondition: this must be called via safelyRead, safelyWrite or