Skip to content

Commit 0a475cb

Browse files
ayushr2gvisor-bot
authored andcommitted
runsc: Move checkpoint options to sandbox.CheckpointOpts.
This change gets rid of `statefile.Options`, which was housing a lot of non-statefile related options. Compression is the only statefile related option today. This way we can have all checkpoint-related options in one place. PiperOrigin-RevId: 785682760
1 parent d284a99 commit 0a475cb

File tree

9 files changed

+48
-67
lines changed

9 files changed

+48
-67
lines changed

pkg/state/statefile/statefile.go

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -107,33 +107,9 @@ func (c CompressionLevel) String() string {
107107
return string(c)
108108
}
109109

110-
// Options is statefile options.
111-
type Options struct {
112-
// Compression is an image compression type/level.
113-
Compression CompressionLevel
114-
115-
// Resume indicates if the sandbox process should continue running
116-
// after checkpointing.
117-
Resume bool
118-
119-
// SaveRestoreExecArgv is the argv of the save/restore binary split by spaces.
120-
// The first element is the path to the binary.
121-
SaveRestoreExecArgv string
122-
123-
// SaveRestoreExecTimeout is the timeout for waiting for the save/restore
124-
// binary.
125-
SaveRestoreExecTimeout time.Duration
126-
127-
// SaveRestoreExecContainerID is the ID of the container that the
128-
// save/restore binary executes in.
129-
SaveRestoreExecContainerID string
130-
}
131-
132-
// WriteToMetadata save options to the metadata storage. Method returns the
133-
// reference to the original metadata map to allow to be used in the chain calls.
134-
func (o Options) WriteToMetadata(metadata map[string]string) map[string]string {
135-
metadata[CompressionKey] = string(o.Compression)
136-
return metadata
110+
// ToMetadata returns the compression level as a metadata map.
111+
func (c CompressionLevel) ToMetadata() map[string]string {
112+
return map[string]string{CompressionKey: string(c)}
137113
}
138114

139115
// CompressionLevelFromString parses a string into the CompressionLevel.

pkg/state/statefile/statefile_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ func benchmark(b *testing.B, size int, write bool, compressible bool) {
212212
var stateBuf bytes.Buffer
213213
writeState := func() {
214214
stateBuf.Reset()
215-
w, err := NewWriter(&stateBuf, key, Options{Compression: CompressionLevelFlateBestSpeed}.WriteToMetadata(map[string]string{}))
215+
w, err := NewWriter(&stateBuf, key, CompressionLevelFlateBestSpeed.ToMetadata())
216216
if err != nil {
217217
b.Fatalf("error creating writer: %v", err)
218218
}

runsc/cmd/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ go_library(
116116
"//runsc/metricserver/containermetrics",
117117
"//runsc/mitigate",
118118
"//runsc/profile",
119+
"//runsc/sandbox",
119120
"//runsc/specutils",
120121
"//runsc/starttime",
121122
"@com_github_google_subcommands//:go_default_library",

runsc/cmd/checkpoint.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ import (
2222

2323
"github.com/google/subcommands"
2424
"gvisor.dev/gvisor/pkg/sentry/control"
25-
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
2625
"gvisor.dev/gvisor/pkg/state/statefile"
2726
"gvisor.dev/gvisor/runsc/cmd/util"
2827
"gvisor.dev/gvisor/runsc/config"
2928
"gvisor.dev/gvisor/runsc/container"
3029
"gvisor.dev/gvisor/runsc/flag"
30+
"gvisor.dev/gvisor/runsc/sandbox"
3131
)
3232

3333
// Checkpoint implements subcommands.Command for the "checkpoint" command.
@@ -100,22 +100,17 @@ func (c *Checkpoint) Execute(_ context.Context, f *flag.FlagSet, args ...any) su
100100
util.Fatalf("making directories at path provided: %v", err)
101101
}
102102

103-
sOpts := statefile.Options{
103+
opts := sandbox.CheckpointOpts{
104104
Compression: c.compression.Level(),
105+
Resume: c.leaveRunning,
106+
Direct: c.direct,
107+
ExcludeCommittedZeroPages: c.excludeCommittedZeroPages,
105108
SaveRestoreExecArgv: c.saveRestoreExecArgv,
106109
SaveRestoreExecTimeout: c.saveRestoreExecTimeout,
107110
SaveRestoreExecContainerID: id,
108111
}
109-
mfOpts := pgalloc.SaveOpts{
110-
ExcludeCommittedZeroPages: c.excludeCommittedZeroPages,
111-
}
112-
113-
if c.leaveRunning {
114-
// Do not destroy the sandbox after saving.
115-
sOpts.Resume = true
116-
}
117112

118-
if err := cont.Checkpoint(c.imagePath, c.direct, sOpts, mfOpts); err != nil {
113+
if err := cont.Checkpoint(c.imagePath, opts); err != nil {
119114
util.Fatalf("checkpoint failed: %v", err)
120115
}
121116

runsc/container/BUILD

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ go_library(
2727
"//pkg/sentry/fsimpl/tmpfs",
2828
"//pkg/sentry/pgalloc",
2929
"//pkg/sighandling",
30-
"//pkg/state/statefile",
3130
"//pkg/sync",
3231
"//pkg/unet",
3332
"//pkg/urpc",
@@ -84,7 +83,6 @@ go_test(
8483
"//pkg/sentry/kernel",
8584
"//pkg/sentry/kernel/auth",
8685
"//pkg/sentry/limits",
87-
"//pkg/sentry/pgalloc",
8886
"//pkg/sentry/platform",
8987
"//pkg/sentry/seccheck",
9088
"//pkg/sentry/seccheck/points:points_go_proto",
@@ -97,6 +95,7 @@ go_test(
9795
"//runsc/cgroup",
9896
"//runsc/config",
9997
"//runsc/flag",
98+
"//runsc/sandbox",
10099
"//runsc/specutils",
101100
"//test/metricclient",
102101
"@com_github_cenkalti_backoff//:go_default_library",

runsc/container/container.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import (
4040
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
4141
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
4242
"gvisor.dev/gvisor/pkg/sighandling"
43-
"gvisor.dev/gvisor/pkg/state/statefile"
4443
"gvisor.dev/gvisor/pkg/unet"
4544
"gvisor.dev/gvisor/pkg/urpc"
4645
"gvisor.dev/gvisor/runsc/boot"
@@ -702,12 +701,12 @@ func (c *Container) ForwardSignals(pid int32, fgProcess bool) func() {
702701

703702
// Checkpoint sends the checkpoint call to the container.
704703
// The statefile will be written to f, the file at the specified image-path.
705-
func (c *Container) Checkpoint(imagePath string, direct bool, sfOpts statefile.Options, mfOpts pgalloc.SaveOpts) error {
704+
func (c *Container) Checkpoint(imagePath string, opts sandbox.CheckpointOpts) error {
706705
log.Debugf("Checkpoint container, cid: %s", c.ID)
707706
if err := c.requireStatus("checkpoint", Created, Running, Paused); err != nil {
708707
return err
709708
}
710-
return c.Sandbox.Checkpoint(c.ID, imagePath, direct, sfOpts, mfOpts)
709+
return c.Sandbox.Checkpoint(c.ID, imagePath, opts)
711710
}
712711

713712
// Pause suspends the container and its kernel.

runsc/container/container_test.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import (
4242
"gvisor.dev/gvisor/pkg/sentry/fsimpl/erofs"
4343
"gvisor.dev/gvisor/pkg/sentry/kernel"
4444
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
45-
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
4645
"gvisor.dev/gvisor/pkg/sentry/platform"
4746
"gvisor.dev/gvisor/pkg/state/statefile"
4847
"gvisor.dev/gvisor/pkg/sync"
@@ -51,6 +50,7 @@ import (
5150
"gvisor.dev/gvisor/runsc/cgroup"
5251
"gvisor.dev/gvisor/runsc/config"
5352
"gvisor.dev/gvisor/runsc/flag"
53+
"gvisor.dev/gvisor/runsc/sandbox"
5454
"gvisor.dev/gvisor/runsc/specutils"
5555
)
5656

@@ -1063,7 +1063,7 @@ func testCheckpointRestore(t *testing.T, conf *config.Config, compression statef
10631063
}
10641064

10651065
// Checkpoint running container; save state into new file.
1066-
if err := cont.Checkpoint(dir, false /* direct */, statefile.Options{Compression: compression}, pgalloc.SaveOpts{}); err != nil {
1066+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Compression: compression}); err != nil {
10671067
t.Fatalf("error checkpointing container to empty file: %v", err)
10681068
}
10691069

@@ -1267,7 +1267,7 @@ func TestCheckpointRestoreExecKilled(t *testing.T) {
12671267
}
12681268

12691269
// Checkpoint running container.
1270-
if err := cont.Checkpoint(dir, false /* direct */, statefile.Options{Compression: statefile.CompressionLevelFlateBestSpeed}, pgalloc.SaveOpts{}); err != nil {
1270+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Compression: statefile.CompressionLevelFlateBestSpeed}); err != nil {
12711271
t.Fatalf("error checkpointing container: %v", err)
12721272
}
12731273
cont.Destroy()
@@ -1346,7 +1346,7 @@ func TestCheckpointRestoreCreateMountPoint(t *testing.T) {
13461346
}
13471347

13481348
// Checkpoint running container; save state into new file.
1349-
if err := cont.Checkpoint(dir, false, statefile.Options{Compression: statefile.CompressionLevelDefault}, pgalloc.SaveOpts{}); err != nil {
1349+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Compression: statefile.CompressionLevelDefault}); err != nil {
13501350
t.Fatalf("error checkpointing container to file: %v", err)
13511351
}
13521352

@@ -1445,7 +1445,7 @@ func TestUnixDomainSockets(t *testing.T) {
14451445
}
14461446

14471447
// Checkpoint running container; save state into new file.
1448-
if err := cont.Checkpoint(dir, false /* direct */, statefile.Options{Compression: statefile.CompressionLevelDefault}, pgalloc.SaveOpts{}); err != nil {
1448+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Compression: statefile.CompressionLevelDefault}); err != nil {
14491449
t.Fatalf("error checkpointing container to empty file: %v", err)
14501450
}
14511451

@@ -2829,7 +2829,7 @@ func TestUsageFD(t *testing.T) {
28292829
}
28302830

28312831
// Checkpoint running container.
2832-
if err := cont.Checkpoint(dir, false /* direct */, statefile.Options{Compression: statefile.CompressionLevelDefault}, pgalloc.SaveOpts{}); err != nil {
2832+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Compression: statefile.CompressionLevelDefault}); err != nil {
28332833
t.Fatalf("error checkpointing container: %v", err)
28342834
}
28352835
cont.Destroy()
@@ -3954,7 +3954,7 @@ func TestSpecValidation(t *testing.T) {
39543954
t.Fatalf("error chmoding file: %q, %v", dir, err)
39553955
}
39563956
// Checkpoint running container; save state into new file.
3957-
if err := cont.Checkpoint(dir, false /* direct */, statefile.Options{Compression: statefile.CompressionLevelFlateBestSpeed}, pgalloc.SaveOpts{}); err != nil {
3957+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Compression: statefile.CompressionLevelFlateBestSpeed}); err != nil {
39583958
t.Fatalf("error checkpointing container to empty file: %v", err)
39593959
}
39603960

@@ -4148,11 +4148,8 @@ func TestCheckpointResume(t *testing.T) {
41484148
t.Fatalf("Failed to wait for output file: %v", err)
41494149
}
41504150

4151-
sfOpts := statefile.Options{
4152-
Resume: true,
4153-
}
41544151
// Checkpoint running container; save state into new file.
4155-
if err := cont.Checkpoint(dir, false /* direct */, sfOpts, pgalloc.SaveOpts{}); err != nil {
4152+
if err := cont.Checkpoint(dir, sandbox.CheckpointOpts{Resume: true}); err != nil {
41564153
t.Fatalf("error checkpointing container to empty file: %v", err)
41574154
}
41584155

runsc/container/multi_container_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ import (
3232
"gvisor.dev/gvisor/pkg/cleanup"
3333
"gvisor.dev/gvisor/pkg/sentry/control"
3434
"gvisor.dev/gvisor/pkg/sentry/kernel"
35-
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
3635
"gvisor.dev/gvisor/pkg/state/statefile"
3736
"gvisor.dev/gvisor/pkg/sync"
3837
"gvisor.dev/gvisor/pkg/test/testutil"
3938
"gvisor.dev/gvisor/runsc/boot"
4039
"gvisor.dev/gvisor/runsc/config"
40+
"gvisor.dev/gvisor/runsc/sandbox"
4141
"gvisor.dev/gvisor/runsc/specutils"
4242
)
4343

@@ -2782,7 +2782,7 @@ func testMultiContainerCheckpointRestore(t *testing.T, conf *config.Config, comp
27822782
}()
27832783

27842784
// Checkpoint root container; save state into new file.
2785-
if err := conts[0].Checkpoint(dir, false /* direct */, statefile.Options{Compression: compression}, pgalloc.SaveOpts{}); err != nil {
2785+
if err := conts[0].Checkpoint(dir, sandbox.CheckpointOpts{Compression: compression}); err != nil {
27862786
t.Fatalf("error checkpointing container to empty file: %v", err)
27872787
}
27882788

runsc/sandbox/sandbox.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ import (
4343
"gvisor.dev/gvisor/pkg/coverage"
4444
"gvisor.dev/gvisor/pkg/fd"
4545
"gvisor.dev/gvisor/pkg/log"
46-
metricpb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
4746
"gvisor.dev/gvisor/pkg/prometheus"
4847
"gvisor.dev/gvisor/pkg/sentry/control"
4948
"gvisor.dev/gvisor/pkg/sentry/devices/nvproxy"
@@ -65,6 +64,8 @@ import (
6564
"gvisor.dev/gvisor/runsc/profile"
6665
"gvisor.dev/gvisor/runsc/specutils"
6766
"gvisor.dev/gvisor/runsc/starttime"
67+
68+
metricpb "gvisor.dev/gvisor/pkg/metric/metric_go_proto"
6869
)
6970

7071
const (
@@ -1448,12 +1449,25 @@ func (s *Sandbox) SignalProcess(cid string, pid int32, sig unix.Signal, fgProces
14481449
return nil
14491450
}
14501451

1452+
// CheckpointOpts contains the options for checkpointing a sandbox.
1453+
type CheckpointOpts struct {
1454+
Compression statefile.CompressionLevel
1455+
Resume bool
1456+
Direct bool
1457+
ExcludeCommittedZeroPages bool
1458+
1459+
// Save/restore exec options.
1460+
SaveRestoreExecArgv string
1461+
SaveRestoreExecTimeout time.Duration
1462+
SaveRestoreExecContainerID string
1463+
}
1464+
14511465
// Checkpoint sends the checkpoint call for a container in the sandbox.
14521466
// The statefile will be written to f.
1453-
func (s *Sandbox) Checkpoint(cid string, imagePath string, direct bool, sfOpts statefile.Options, mfOpts pgalloc.SaveOpts) error {
1454-
log.Debugf("Checkpoint sandbox %q, statefile options %+v, MemoryFile options %+v", s.ID, sfOpts, mfOpts)
1467+
func (s *Sandbox) Checkpoint(cid string, imagePath string, opts CheckpointOpts) error {
1468+
log.Debugf("Checkpoint sandbox %q, imagePath %q, opts %+v", s.ID, imagePath, opts)
14551469

1456-
files, err := createSaveFiles(imagePath, direct, sfOpts.Compression)
1470+
files, err := createSaveFiles(imagePath, opts.Direct, opts.Compression)
14571471
if err != nil {
14581472
return err
14591473
}
@@ -1464,16 +1478,16 @@ func (s *Sandbox) Checkpoint(cid string, imagePath string, direct bool, sfOpts s
14641478
}()
14651479

14661480
opt := control.SaveOpts{
1467-
Metadata: sfOpts.WriteToMetadata(map[string]string{}),
1468-
MemoryFileSaveOpts: mfOpts,
1481+
Metadata: opts.Compression.ToMetadata(),
1482+
MemoryFileSaveOpts: pgalloc.SaveOpts{ExcludeCommittedZeroPages: opts.ExcludeCommittedZeroPages},
14691483
FilePayload: urpc.FilePayload{
14701484
Files: files,
14711485
},
14721486
HavePagesFile: len(files) > 1,
1473-
Resume: sfOpts.Resume,
1474-
SaveRestoreExecArgv: sfOpts.SaveRestoreExecArgv,
1475-
SaveRestoreExecTimeout: sfOpts.SaveRestoreExecTimeout,
1476-
SaveRestoreExecContainerID: sfOpts.SaveRestoreExecContainerID,
1487+
Resume: opts.Resume,
1488+
SaveRestoreExecArgv: opts.SaveRestoreExecArgv,
1489+
SaveRestoreExecTimeout: opts.SaveRestoreExecTimeout,
1490+
SaveRestoreExecContainerID: opts.SaveRestoreExecContainerID,
14771491
}
14781492

14791493
if err := s.call(boot.ContMgrCheckpoint, &opt, nil); err != nil {

0 commit comments

Comments
 (0)