mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[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:
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user