mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Update tmpfs to restore its MemoryFile using stateify tools.
PiperOrigin-RevId: 615233954
This commit is contained in:
@@ -23,11 +23,29 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
)
|
||||
|
||||
// afterLoad is called by stateify.
|
||||
func (fs *filesystem) afterLoad(goContext.Context) {
|
||||
if !fs.privateMF {
|
||||
fs.mf = fs.mfp.MemoryFile()
|
||||
// saveMf is called by stateify.
|
||||
func (fs *filesystem) saveMf() string {
|
||||
if !fs.mf.IsSavable() {
|
||||
panic(fmt.Sprintf("Can't save tmpfs filesystem because its MemoryFile is not savable: %v", fs.mf))
|
||||
}
|
||||
return fs.mf.RestoreID()
|
||||
}
|
||||
|
||||
// loadMf is called by stateify.
|
||||
func (fs *filesystem) loadMf(ctx goContext.Context, restoreID string) {
|
||||
if restoreID == "" {
|
||||
fs.mf = pgalloc.MemoryFileFromContext(ctx)
|
||||
return
|
||||
}
|
||||
mfmap := pgalloc.MemoryFileMapFromContext(ctx)
|
||||
if mfmap == nil {
|
||||
panic("CtxMemoryFileMap was not provided")
|
||||
}
|
||||
mf, ok := mfmap[restoreID]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Memory file for %q not found in CtxMemoryFileMap", restoreID))
|
||||
}
|
||||
fs.mf = mf
|
||||
}
|
||||
|
||||
// saveParent is called by stateify.
|
||||
@@ -42,34 +60,23 @@ func (d *dentry) loadParent(_ goContext.Context, parent *dentry) {
|
||||
|
||||
// PrepareSave implements vfs.FilesystemImplSaveRestoreExtension.PrepareSave.
|
||||
func (fs *filesystem) PrepareSave(ctx context.Context) error {
|
||||
if !fs.privateMF {
|
||||
restoreID := fs.mf.RestoreID()
|
||||
if restoreID == "" {
|
||||
return nil
|
||||
}
|
||||
mfmap := pgalloc.MemoryFileMapFromContext(ctx)
|
||||
if mfmap == nil {
|
||||
return fmt.Errorf("CtxMemoryFileMap was not provided")
|
||||
}
|
||||
if _, ok := mfmap[fs.uniqueID.String()]; ok {
|
||||
return fmt.Errorf("memory file for %q already exists in CtxMemoryFileMap", fs.uniqueID)
|
||||
if _, ok := mfmap[restoreID]; ok {
|
||||
return fmt.Errorf("memory file for %q already exists in CtxMemoryFileMap", restoreID)
|
||||
}
|
||||
mfmap[fs.uniqueID.String()] = fs.mf
|
||||
mfmap[restoreID] = fs.mf
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompleteRestore implements
|
||||
// vfs.FilesystemImplSaveRestoreExtension.CompleteRestore.
|
||||
func (fs *filesystem) CompleteRestore(ctx context.Context, opts vfs.CompleteRestoreOptions) error {
|
||||
if !fs.privateMF {
|
||||
return nil
|
||||
}
|
||||
mfmap := pgalloc.MemoryFileMapFromContext(ctx)
|
||||
if mfmap == nil {
|
||||
return fmt.Errorf("CtxMemoryFileMap was not provided")
|
||||
}
|
||||
mf, ok := mfmap[fs.uniqueID.String()]
|
||||
if !ok {
|
||||
return fmt.Errorf("memory file for %q not found in CtxMemoryFileMap", fs.uniqueID)
|
||||
}
|
||||
fs.mf = mf
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,20 +63,8 @@ type filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
// mf is used to allocate memory that stores regular file contents. mf is
|
||||
// immutable, except it may to changed during restore.
|
||||
mf *pgalloc.MemoryFile `state:"nosave"`
|
||||
|
||||
// privateMF indicates whether mf is private to this tmpfs mount. If so,
|
||||
// tmpfs takes ownership of mf. privateMF is immutable.
|
||||
privateMF bool
|
||||
|
||||
// uniqueID is an opaque string used to reassociate the filesystem with its
|
||||
// private MemoryFile during checkpoint and restore.
|
||||
uniqueID vfs.RestoreID
|
||||
|
||||
// mfp is used to provide mf, when privateMF == false. This is required to
|
||||
// re-provide mf on restore. mfp is immutable.
|
||||
mfp pgalloc.MemoryFileProvider
|
||||
// immutable, except it is changed during restore.
|
||||
mf *pgalloc.MemoryFile `state:".(string)"`
|
||||
|
||||
// clock is a realtime clock used to set timestamps in file operations.
|
||||
clock time.Clock
|
||||
@@ -156,10 +144,6 @@ type FilesystemOpts struct {
|
||||
// AllowXattrPrefix is a set of xattr namespace prefixes that this
|
||||
// tmpfs mount will allow.
|
||||
AllowXattrPrefix []string
|
||||
|
||||
// If UniqueID is non-empty, it is an opaque string used to reassociate the
|
||||
// filesystem with its private MemoryFile during checkpoint and restore.
|
||||
UniqueID vfs.RestoreID
|
||||
}
|
||||
|
||||
// Default size limit mount option. It is immutable after initialization.
|
||||
@@ -186,13 +170,10 @@ func getDefaultSizeLimit(disable bool) uint64 {
|
||||
|
||||
// GetFilesystem implements vfs.FilesystemType.GetFilesystem.
|
||||
func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, _ string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
|
||||
mfp := pgalloc.MemoryFileProviderFromContext(ctx)
|
||||
if mfp == nil {
|
||||
panic("MemoryFileProviderFromContext returned nil")
|
||||
mf := pgalloc.MemoryFileFromContext(ctx)
|
||||
if mf == nil {
|
||||
panic("CtxMemoryFile returned nil")
|
||||
}
|
||||
mf := mfp.MemoryFile()
|
||||
privateMF := false
|
||||
var uniqueID vfs.RestoreID
|
||||
rootFileType := uint16(linux.S_IFDIR)
|
||||
disableDefaultSizeLimit := false
|
||||
newFSType := vfs.FilesystemType(&fstype)
|
||||
@@ -218,17 +199,11 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
||||
disableDefaultSizeLimit = tmpfsOpts.DisableDefaultSizeLimit
|
||||
if tmpfsOpts.MemoryFile != nil {
|
||||
mf = tmpfsOpts.MemoryFile
|
||||
privateMF = true
|
||||
}
|
||||
uniqueID = tmpfsOpts.UniqueID
|
||||
for _, xattr := range tmpfsOpts.AllowXattrPrefix {
|
||||
allowXattrPrefix[xattr] = struct{}{}
|
||||
}
|
||||
}
|
||||
if privateMF && len(uniqueID.Path) == 0 {
|
||||
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: privateMF requires uniqueID to be set")
|
||||
return nil, nil, linuxerr.EINVAL
|
||||
}
|
||||
|
||||
mopts := vfs.GenericParseMountOptions(opts.Data)
|
||||
rootMode := linux.FileMode(0777)
|
||||
@@ -311,9 +286,6 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
||||
}
|
||||
fs := filesystem{
|
||||
mf: mf,
|
||||
privateMF: privateMF,
|
||||
uniqueID: uniqueID,
|
||||
mfp: mfp,
|
||||
clock: clock,
|
||||
devMinor: devMinor,
|
||||
mopts: opts.Data,
|
||||
@@ -351,7 +323,9 @@ func (fs *filesystem) Release(ctx context.Context) {
|
||||
fs.root.releaseChildrenLocked(ctx)
|
||||
}
|
||||
fs.mu.Unlock()
|
||||
if fs.privateMF {
|
||||
if fs.mf.RestoreID() != "" {
|
||||
// If RestoreID is set, then this is a private MemoryFile which needs to be
|
||||
// destroyed since this tmpfs is the only user.
|
||||
fs.mf.Destroy()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user