[vfs2] Add FilesystemType.Release to avoid reference leaks.

Singleton filesystem like devpts and devtmpfs have a single filesystem shared
among all mounts, so they acquire a "self-reference" when initialized that
must be released when the entire virtual filesystem is released at sandbox
exit.

PiperOrigin-RevId: 336828852
This commit is contained in:
Dean Deng
2020-10-13 01:13:22 -07:00
committed by gVisor bot
parent fc7df53222
commit 577c82f22c
18 changed files with 96 additions and 23 deletions
+1
View File
@@ -35,6 +35,7 @@ go_library(
"//pkg/refs",
"//pkg/safemem",
"//pkg/sentry/arch",
"//pkg/sentry/fs",
"//pkg/sentry/fs/lock",
"//pkg/sentry/fsimpl/kernfs",
"//pkg/sentry/kernel",
+34 -10
View File
@@ -37,27 +37,51 @@ const Name = "devpts"
// FilesystemType implements vfs.FilesystemType.
//
// +stateify savable
type FilesystemType struct{}
type FilesystemType struct {
initOnce sync.Once `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
initErr error
// fs backs all mounts of this FilesystemType. root is fs' root. fs and root
// are immutable.
fs *vfs.Filesystem
root *vfs.Dentry
}
// Name implements vfs.FilesystemType.Name.
func (FilesystemType) Name() string {
func (*FilesystemType) Name() string {
return Name
}
var _ vfs.FilesystemType = (*FilesystemType)(nil)
// GetFilesystem implements vfs.FilesystemType.GetFilesystem.
func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
func (fstype *FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
// No data allowed.
if opts.Data != "" {
return nil, nil, syserror.EINVAL
}
fs, root, err := fstype.newFilesystem(vfsObj, creds)
if err != nil {
return nil, nil, err
fstype.initOnce.Do(func() {
fs, root, err := fstype.newFilesystem(vfsObj, creds)
if err != nil {
fstype.initErr = err
return
}
fstype.fs = fs.VFSFilesystem()
fstype.root = root.VFSDentry()
})
if fstype.initErr != nil {
return nil, nil, fstype.initErr
}
fstype.fs.IncRef()
fstype.root.IncRef()
return fstype.fs, fstype.root, nil
}
// Release implements vfs.FilesystemType.Release.
func (fstype *FilesystemType) Release(ctx context.Context) {
if fstype.fs != nil {
fstype.root.DecRef(ctx)
fstype.fs.DecRef(ctx)
}
return fs.Filesystem.VFSFilesystem(), root.VFSDentry(), nil
}
// +stateify savable
@@ -69,7 +93,7 @@ type filesystem struct {
// newFilesystem creates a new devpts filesystem with root directory and ptmx
// master inode. It returns the filesystem and root Dentry.
func (fstype FilesystemType) newFilesystem(vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) (*filesystem, *kernfs.Dentry, error) {
func (fstype *FilesystemType) newFilesystem(vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) (*filesystem, *kernfs.Dentry, error) {
devMinor, err := vfsObj.GetAnonBlockDevMinor()
if err != nil {
return nil, nil, err