diff --git a/runsc/boot/autosave.go b/runsc/boot/autosave.go index 0b787796a..c0a023daf 100644 --- a/runsc/boot/autosave.go +++ b/runsc/boot/autosave.go @@ -25,11 +25,11 @@ import ( "gvisor.dev/gvisor/pkg/sentry/state" "gvisor.dev/gvisor/pkg/sentry/strace" "gvisor.dev/gvisor/pkg/sync" + "gvisor.dev/gvisor/runsc/version" ) func getTargetForSaveResume(l *Loader) func(k *kernel.Kernel) { return func(k *kernel.Kernel) { - l.addVersionToCheckpoint() l.addContainerSpecsToCheckpoint() // Store the state file contents in a buffer for save-resume. // There is no need to verify the state file, we just need the @@ -39,6 +39,7 @@ func getTargetForSaveResume(l *Loader) func(k *kernel.Kernel) { Autosave: true, Resume: true, Destination: &buf, + Metadata: map[string]string{VersionKey: version.Version()}, } saveOpts.Save(k.SupervisorContext(), k, l.watchdog) } @@ -52,18 +53,17 @@ func getTargetForSaveRestore(l *Loader, files []*fd.FD) func(k *kernel.Kernel) { var once sync.Once return func(k *kernel.Kernel) { once.Do(func() { - l.addVersionToCheckpoint() l.addContainerSpecsToCheckpoint() saveOpts := state.SaveOpts{ Autosave: true, Resume: false, Destination: files[0], + Metadata: map[string]string{VersionKey: version.Version()}, } if len(files) == 3 { saveOpts.PagesMetadata = files[1] saveOpts.PagesFile = files[2] } - saveOpts.Save(k.SupervisorContext(), k, l.watchdog) }) } diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go index 217280b1e..790fb1ade 100644 --- a/runsc/boot/controller.go +++ b/runsc/boot/controller.go @@ -42,6 +42,7 @@ import ( "gvisor.dev/gvisor/runsc/boot/procfs" "gvisor.dev/gvisor/runsc/config" "gvisor.dev/gvisor/runsc/specutils" + "gvisor.dev/gvisor/runsc/version" ) const ( @@ -570,7 +571,7 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error { return fmt.Errorf("reading metadata from statefile: %w", err) } var count int - countStr, ok := metadata["container_count"] + countStr, ok := metadata[ContainerCountKey] if !ok { // TODO(gvisor.dev/issue/1956): Add container count with syscall save // trigger. For now, assume that only a single container exists if metadata @@ -594,6 +595,11 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error { return fmt.Errorf("rewinding state file: %w", err) } + checkpointVersion := metadata[VersionKey] + currentVersion := version.Version() + if checkpointVersion != currentVersion { + return fmt.Errorf("runsc version does not match across checkpoint restore, checkpoint: %v current: %v", checkpointVersion, currentVersion) + } return cm.restorer.restoreContainerInfo(cm.l, &cm.l.root) } diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go index 32398a179..3c6e942ca 100644 --- a/runsc/boot/loader.go +++ b/runsc/boot/loader.go @@ -84,7 +84,6 @@ import ( "gvisor.dev/gvisor/runsc/profile" "gvisor.dev/gvisor/runsc/specutils" "gvisor.dev/gvisor/runsc/specutils/seccomp" - "gvisor.dev/gvisor/runsc/version" // Top-level inet providers. "gvisor.dev/gvisor/pkg/sentry/socket/hostinet" @@ -379,10 +378,6 @@ const ( // containerSpecsKey is the key used to add and pop the container specs to the // kernel during save/restore. containerSpecsKey = "container_specs" - - // versionKey is the key used to add and pop runsc version to the kernel - // during save/restore. - versionKey = "runsc_version" ) func getRootCredentials(spec *specs.Spec, conf *config.Config, userNs *auth.UserNamespace) *auth.Credentials { @@ -2048,13 +2043,3 @@ func popContainerSpecsFromCheckpoint(k *kernel.Kernel) (map[string]*specs.Spec, } return oldSpecs, nil } - -// addVersionToCheckpoint adds the runsc version to the kernel. -func (l *Loader) addVersionToCheckpoint() { - l.k.AddStateToCheckpoint(versionKey, version.Version()) -} - -// popVersionFromCheckpoint pops the runsc version from the kernel. -func popVersionFromCheckpoint(k *kernel.Kernel) string { - return (k.PopCheckpointState(versionKey)).(string) -} diff --git a/runsc/boot/restore.go b/runsc/boot/restore.go index 2d5ca0617..544244939 100644 --- a/runsc/boot/restore.go +++ b/runsc/boot/restore.go @@ -57,6 +57,11 @@ const ( // CheckpointPagesFileName is the file within the given image-path's // directory containing the container's MemoryFile pages. CheckpointPagesFileName = "pages.img" + // VersionKey is the key used to save runsc version in the save metadata and compare + // it across checkpoint restore. + VersionKey = "runsc_version" + // ContainerCountKey is the key used to save number of containers in the save metadata. + ContainerCountKey = "container_count" ) // restorer manages a restore session for a sandbox. It stores information about @@ -239,12 +244,6 @@ func (r *restorer) restore(l *Loader) error { return fmt.Errorf("failed to load kernel: %w", err) } - checkpointVersion := popVersionFromCheckpoint(l.k) - currentVersion := version.Version() - if checkpointVersion != currentVersion { - return fmt.Errorf("runsc version does not match across checkpoint restore, checkpoint: %v current: %v", checkpointVersion, currentVersion) - } - oldSpecs, err := popContainerSpecsFromCheckpoint(l.k) if err != nil { return fmt.Errorf("failed to pop container specs from checkpoint: %w", err) @@ -357,10 +356,10 @@ func (l *Loader) save(o *control.SaveOpts) (err error) { if o.Metadata == nil { o.Metadata = make(map[string]string) } - o.Metadata["container_count"] = strconv.Itoa(l.containerCount()) + o.Metadata[ContainerCountKey] = strconv.Itoa(l.containerCount()) // Save runsc version. - l.addVersionToCheckpoint() + o.Metadata[VersionKey] = version.Version() // Save container specs. l.addContainerSpecsToCheckpoint()