[vfs] kernfs: Do not panic if destroyed dentry is cached.

If a kernfs user does not cache dentries, then cacheLocked will destroy the
dentry. The current DecRef implementation will be racy in this case as the
following can happen:
- Goroutine 1 calls DecRef and decreases ref count from 1 to 0.
- Goroutine 2 acquires d.fs.mu for reading and calls IncRef and increasing the
  ref count from 0 to 1.
- Goroutine 2 releases d.fs.mu and calls DecRef again decreasing ref count from
  1 to 0.
- Goroutine 1 now acquires d.fs.mu and calls cacheLocked which destroys the
  dentry.
- Goroutine 2 now acquires d.fs.mu and calls cacheLocked to find that the dentry
  is already destroyed!

Earlier we would panic in this case, we could instead just return instead of
adding complexity to handle this race. This is similar to what the gofer client
does.

We do not want to lock d.fs.mu in the case that the filesystem caches dentries
(common case as procfs and sysfs do this) to prevent congestion due to lock
contention.

PiperOrigin-RevId: 343229496
This commit is contained in:
Ayush Ranjan 2020-11-18 23:08:04 -08:00 committed by gVisor bot
parent e5650d1240
commit 74bc6e56cc
1 changed files with 1 additions and 1 deletions

View File

@ -286,7 +286,7 @@ func (d *Dentry) cacheLocked(ctx context.Context) {
refs := atomic.LoadInt64(&d.refs)
if refs == -1 {
// Dentry has already been destroyed.
panic(fmt.Sprintf("cacheLocked called on a dentry which has already been destroyed: %v", d))
return
}
if refs > 0 {
if d.cached {