mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Move filesystem creation from GetFilesystem to RegistryImpl.
Move root dentry and filesystem creation from GetFilesystem to NewRegistryImpl, create IPCNamespace.InitPosixQueues to create a new mqueue filesystem for each ipc namespace, and update GetFilesystem to retreive fs and root dentry from IPCNamespace and return them. Updates #136
This commit is contained in:
@@ -31,6 +31,7 @@ go_library(
|
||||
"//pkg/refsvfs2",
|
||||
"//pkg/sentry/fsimpl/kernfs",
|
||||
"//pkg/sentry/kernel/auth",
|
||||
"//pkg/sentry/kernel/ipc",
|
||||
"//pkg/sentry/kernel/mq",
|
||||
"//pkg/sentry/vfs",
|
||||
"//pkg/sync",
|
||||
|
||||
@@ -24,6 +24,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/ipc"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/mq"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
)
|
||||
|
||||
@@ -47,28 +49,32 @@ func (FilesystemType) Release(ctx context.Context) {}
|
||||
|
||||
// GetFilesystem implements vfs.FilesystemType.GetFilesystem.
|
||||
func (ft FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
|
||||
devMinor, err := vfsObj.GetAnonBlockDevMinor()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
// mqfs is initialized only once per ipc namespace. Each ipc namespace has
|
||||
// a POSIX message registry with a root dentry, filesystem, and a
|
||||
// disconnected mount. We want the fs to be consistent for all processes in
|
||||
// the same ipc namespace, so instead of creating a new fs and root dentry,
|
||||
// we retreive them using IPCNamespace.PosixQueues and use them.
|
||||
|
||||
i := ipcNamespaceFromContext(ctx)
|
||||
if i == nil {
|
||||
return nil, nil, fmt.Errorf("mqfs.FilesystemType.GetFilesystem: ipc namespace doesn't exist")
|
||||
}
|
||||
defer i.DecRef(ctx)
|
||||
|
||||
registry := i.PosixQueues()
|
||||
if registry == nil {
|
||||
return nil, nil, fmt.Errorf("mqfs.FilesystemType.GetFilesystem: ipc namespace doesn't have a POSIX registry")
|
||||
}
|
||||
impl := registry.Impl().(*RegistryImpl)
|
||||
|
||||
maxCachedDentries, err := maxCachedDentries(ctx, vfs.GenericParseMountOptions(opts.Data))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
impl.fs.MaxCachedDentries = maxCachedDentries
|
||||
|
||||
fs := &filesystem{
|
||||
devMinor: devMinor,
|
||||
Filesystem: kernfs.Filesystem{
|
||||
MaxCachedDentries: maxCachedDentries,
|
||||
},
|
||||
}
|
||||
fs.VFSFilesystem().Init(vfsObj, &ft, fs)
|
||||
|
||||
var dentry kernfs.Dentry
|
||||
dentry.InitRoot(&fs.Filesystem, fs.newRootInode(ctx, creds))
|
||||
|
||||
return fs.VFSFilesystem(), dentry.VFSDentry(), nil
|
||||
impl.root.IncRef()
|
||||
return impl.fs.VFSFilesystem(), impl.root.VFSDentry(), nil
|
||||
}
|
||||
|
||||
// maxCachedDentries checks mopts for dentry_cache_limit. If a value is
|
||||
@@ -93,15 +99,40 @@ func maxCachedDentries(ctx context.Context, mopts map[string]string) (_ uint64,
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
devMinor uint32
|
||||
|
||||
// root is the filesystem's root dentry. Since we take a reference on it in
|
||||
// GetFilesystem, we should release it when the fs is released.
|
||||
root *kernfs.Dentry
|
||||
}
|
||||
|
||||
// Release implements vfs.FilesystemImpl.Release.
|
||||
func (fs *filesystem) Release(ctx context.Context) {
|
||||
fs.Filesystem.VFSFilesystem().VirtualFilesystem().PutAnonBlockDevMinor(fs.devMinor)
|
||||
fs.Filesystem.Release(ctx)
|
||||
fs.root.DecRef(ctx)
|
||||
}
|
||||
|
||||
// MountOptions implements vfs.FilesystemImpl.MountOptions.
|
||||
func (fs *filesystem) MountOptions() string {
|
||||
return fmt.Sprintf("dentry_cache_limit=%d", fs.MaxCachedDentries)
|
||||
}
|
||||
|
||||
// ipcNamespace defines functions we need from kernel.IPCNamespace. We redefine
|
||||
// ipcNamespace along with ipcNamespaceFromContext to avoid circular dependency
|
||||
// with package sentry/kernel.
|
||||
type ipcNamespace interface {
|
||||
// PosixQueues returns a POSIX message queue registry.
|
||||
PosixQueues() *mq.Registry
|
||||
|
||||
// DecRef decrements ipcNamespace's number of references.
|
||||
DecRef(ctx context.Context)
|
||||
}
|
||||
|
||||
// ipcNamespaceFromContext returns the IPC namespace in which ctx is executing.
|
||||
// Copied from package sentry/kernel.
|
||||
func ipcNamespaceFromContext(ctx context.Context) ipcNamespace {
|
||||
if v := ctx.Value(ipc.CtxIPCNamespace); v != nil {
|
||||
return v.(ipcNamespace)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -50,12 +50,32 @@ type RegistryImpl struct {
|
||||
|
||||
// NewRegistryImpl returns a new, initialized RegistryImpl, and takes a
|
||||
// reference on root.
|
||||
func NewRegistryImpl(root *kernfs.Dentry, fs *filesystem) *RegistryImpl {
|
||||
root.IncRef()
|
||||
return &RegistryImpl{
|
||||
root: root,
|
||||
fs: fs,
|
||||
func NewRegistryImpl(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) (*RegistryImpl, error) {
|
||||
devMinor, err := vfsObj.GetAnonBlockDevMinor()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dentry kernfs.Dentry
|
||||
fs := &filesystem{
|
||||
devMinor: devMinor,
|
||||
root: &dentry,
|
||||
}
|
||||
fs.VFSFilesystem().Init(vfsObj, &FilesystemType{}, fs)
|
||||
|
||||
dentry.InitRoot(&fs.Filesystem, fs.newRootInode(ctx, creds))
|
||||
dentry.IncRef()
|
||||
|
||||
mount, err := vfsObj.NewDisconnectedMount(fs.VFSFilesystem(), dentry.VFSDentry(), &vfs.MountOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &RegistryImpl{
|
||||
root: &dentry,
|
||||
fs: fs,
|
||||
mount: mount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Lookup implements mq.RegistryImpl.Lookup.
|
||||
@@ -83,11 +103,11 @@ func (r *RegistryImpl) New(ctx context.Context, name string, q *mq.Queue, perm l
|
||||
}
|
||||
|
||||
fd := &queueFD{queue: q}
|
||||
err = fd.Init(r.mount, r.root, qInode.data, &qInode.locks, 0 /* flags */)
|
||||
err = fd.Init(r.mount, r.root, q, qInode.Locks(), 0 /* flags */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fd.VFSFileDescription(), nil
|
||||
return &fd.vfsfd, nil
|
||||
}
|
||||
|
||||
// Unlink implements mq.RegistryImpl.Unlink.
|
||||
|
||||
@@ -249,6 +249,7 @@ go_library(
|
||||
"//pkg/sentry/fs/timerfd",
|
||||
"//pkg/sentry/fsbridge",
|
||||
"//pkg/sentry/fsimpl/kernfs",
|
||||
"//pkg/sentry/fsimpl/mqfs",
|
||||
"//pkg/sentry/fsimpl/pipefs",
|
||||
"//pkg/sentry/fsimpl/sockfs",
|
||||
"//pkg/sentry/fsimpl/timerfd",
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
package kernel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsimpl/mqfs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/mq"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/msgqueue"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/semaphore"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/shm"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
)
|
||||
|
||||
// IPCNamespace represents an IPC namespace.
|
||||
@@ -72,12 +76,19 @@ func (i *IPCNamespace) ShmRegistry() *shm.Registry {
|
||||
return i.shms
|
||||
}
|
||||
|
||||
// SetPosixQueues sets value of posixQueues if the value is currently nil,
|
||||
// otherwise returns without doing anything.
|
||||
func (i *IPCNamespace) SetPosixQueues(r *mq.Registry) {
|
||||
if i.posixQueues == nil {
|
||||
i.posixQueues = r
|
||||
// InitPosixQueues creates a new POSIX queue registry, and returns an error if
|
||||
// the registry was previously initialized.
|
||||
func (i *IPCNamespace) InitPosixQueues(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) error {
|
||||
if i.posixQueues != nil {
|
||||
return fmt.Errorf("IPCNamespace.InitPosixQueues: already initialized")
|
||||
}
|
||||
|
||||
impl, err := mqfs.NewRegistryImpl(ctx, vfsObj, creds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.posixQueues = mq.NewRegistry(impl)
|
||||
return nil
|
||||
}
|
||||
|
||||
// PosixQueues returns the posix message queue registry for this namespace.
|
||||
|
||||
@@ -79,6 +79,11 @@ func (r *Registry) Destroy(ctx context.Context) {
|
||||
r.impl.Destroy(ctx)
|
||||
}
|
||||
|
||||
// Impl returns RegistryImpl inside r.
|
||||
func (r *Registry) Impl() RegistryImpl {
|
||||
return r.impl
|
||||
}
|
||||
|
||||
// Queue represents a POSIX message queue.
|
||||
//
|
||||
// +stateify savable
|
||||
|
||||
Reference in New Issue
Block a user