[vfs2] Don't leak disconnected mounts.

PiperOrigin-RevId: 336694658
This commit is contained in:
Dean Deng
2020-10-12 10:41:04 -07:00
committed by gVisor bot
parent db36d948fa
commit d861cd5f14
4 changed files with 32 additions and 3 deletions
+15
View File
@@ -1738,3 +1738,18 @@ func (k *Kernel) ShmMount() *vfs.Mount {
func (k *Kernel) SocketMount() *vfs.Mount {
return k.socketMount
}
// Release releases resources owned by k.
//
// Precondition: This should only be called after the kernel is fully
// initialized, e.g. after k.Start() has been called.
func (k *Kernel) Release() {
if VFS2Enabled {
ctx := k.SupervisorContext()
k.hostMount.DecRef(ctx)
k.pipeMount.DecRef(ctx)
k.shmMount.DecRef(ctx)
k.socketMount.DecRef(ctx)
k.vfs.Release(ctx)
}
}
+5 -2
View File
@@ -46,8 +46,9 @@ import (
// +stateify savable
type Mount struct {
// vfs, fs, root are immutable. References are held on fs and root.
// Note that for a disconnected mount, root may be nil.
//
// Invariant: root belongs to fs.
// Invariant: if not nil, root belongs to fs.
vfs *VirtualFilesystem
fs *Filesystem
root *Dentry
@@ -498,7 +499,9 @@ func (mnt *Mount) DecRef(ctx context.Context) {
mnt.vfs.mounts.seq.EndWrite()
mnt.vfs.mountMu.Unlock()
}
mnt.root.DecRef(ctx)
if mnt.root != nil {
mnt.root.DecRef(ctx)
}
mnt.fs.DecRef(ctx)
if vd.Ok() {
vd.DecRef(ctx)
+7
View File
@@ -122,6 +122,13 @@ type VirtualFilesystem struct {
filesystems map[*Filesystem]struct{}
}
// Release drops references on filesystem objects held by vfs.
//
// Precondition: This must be called after VFS.Init() has succeeded.
func (vfs *VirtualFilesystem) Release(ctx context.Context) {
vfs.anonMount.DecRef(ctx)
}
// Init initializes a new VirtualFilesystem with no mounts or FilesystemTypes.
func (vfs *VirtualFilesystem) Init(ctx context.Context) error {
if vfs.mountpoints != nil {
+5 -1
View File
@@ -472,9 +472,13 @@ func (l *Loader) Destroy() {
}
l.watchdog.Stop()
// Release all kernel resources. This is only safe after we can no longer
// save/restore.
l.k.Release()
// In the success case, stdioFDs and goferFDs will only contain
// released/closed FDs that ownership has been passed over to host FDs and
// gofer sessions. Close them here in case on failure.
// gofer sessions. Close them here in case of failure.
for _, fd := range l.root.stdioFDs {
_ = fd.Close()
}