mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Use O_DIRECT to read pages.img.
Suggested-by: Jamie Liu <jamieliu@google.com> PiperOrigin-RevId: 627496836
This commit is contained in:
@@ -39,6 +39,13 @@ type Restore struct {
|
|||||||
|
|
||||||
// detach indicates that runsc has to start a process and exit without waiting it.
|
// detach indicates that runsc has to start a process and exit without waiting it.
|
||||||
detach bool
|
detach bool
|
||||||
|
|
||||||
|
// direct indicates whether O_DIRECT should be used for reading the
|
||||||
|
// checkpoint pages file. It is faster if the checkpoint files are not
|
||||||
|
// already in the page cache (for example if its coming from an untouched
|
||||||
|
// network block device). Usually the restore is done only once, so the cost
|
||||||
|
// of adding the checkpoint files to the page cache can be redundant.
|
||||||
|
direct bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name implements subcommands.Command.Name.
|
// Name implements subcommands.Command.Name.
|
||||||
@@ -62,6 +69,7 @@ func (r *Restore) SetFlags(f *flag.FlagSet) {
|
|||||||
r.Create.SetFlags(f)
|
r.Create.SetFlags(f)
|
||||||
f.StringVar(&r.imagePath, "image-path", "", "directory path to saved container image")
|
f.StringVar(&r.imagePath, "image-path", "", "directory path to saved container image")
|
||||||
f.BoolVar(&r.detach, "detach", false, "detach from the container's process")
|
f.BoolVar(&r.detach, "detach", false, "detach from the container's process")
|
||||||
|
f.BoolVar(&r.direct, "direct", false, "use O_DIRECT for reading checkpoint pages file")
|
||||||
|
|
||||||
// Unimplemented flags necessary for compatibility with docker.
|
// Unimplemented flags necessary for compatibility with docker.
|
||||||
|
|
||||||
@@ -138,7 +146,7 @@ func (r *Restore) Execute(_ context.Context, f *flag.FlagSet, args ...any) subco
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Restore: %v", r.imagePath)
|
log.Debugf("Restore: %v", r.imagePath)
|
||||||
if err := c.Restore(conf, r.imagePath); err != nil {
|
if err := c.Restore(conf, r.imagePath, r.direct); err != nil {
|
||||||
return util.Errorf("starting container: %v", err)
|
return util.Errorf("starting container: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ func (c *Container) Start(conf *config.Config) error {
|
|||||||
|
|
||||||
// Restore takes a container and replaces its kernel and file system
|
// Restore takes a container and replaces its kernel and file system
|
||||||
// to restore a container from its state file.
|
// to restore a container from its state file.
|
||||||
func (c *Container) Restore(conf *config.Config, imagePath string) error {
|
func (c *Container) Restore(conf *config.Config, imagePath string, direct bool) error {
|
||||||
log.Debugf("Restore container, cid: %s", c.ID)
|
log.Debugf("Restore container, cid: %s", c.ID)
|
||||||
if err := c.Saver.lock(BlockAcquire); err != nil {
|
if err := c.Saver.lock(BlockAcquire); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -542,7 +542,7 @@ func (c *Container) Restore(conf *config.Config, imagePath string) error {
|
|||||||
log.Warningf("StartContainer hook skipped because running inside container namespace is not supported")
|
log.Warningf("StartContainer hook skipped because running inside container namespace is not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Sandbox.Restore(conf, c.ID, imagePath); err != nil {
|
if err := c.Sandbox.Restore(conf, c.ID, imagePath, direct); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.changeStatus(Running)
|
c.changeStatus(Running)
|
||||||
|
|||||||
@@ -1101,7 +1101,7 @@ func testCheckpointRestore(t *testing.T, conf *config.Config, compression statef
|
|||||||
}
|
}
|
||||||
defer cont2.Destroy()
|
defer cont2.Destroy()
|
||||||
|
|
||||||
if err := cont2.Restore(conf, dir); err != nil {
|
if err := cont2.Restore(conf, dir, false /* direct */); err != nil {
|
||||||
t.Fatalf("error restoring container: %v", err)
|
t.Fatalf("error restoring container: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1144,7 +1144,7 @@ func testCheckpointRestore(t *testing.T, conf *config.Config, compression statef
|
|||||||
}
|
}
|
||||||
defer cont3.Destroy()
|
defer cont3.Destroy()
|
||||||
|
|
||||||
if err := cont3.Restore(conf, dir); err != nil {
|
if err := cont3.Restore(conf, dir, false /* direct */); err != nil {
|
||||||
t.Fatalf("error restoring container: %v", err)
|
t.Fatalf("error restoring container: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1263,7 +1263,7 @@ func TestCheckpointRestoreExecKilled(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer cont2.Destroy()
|
defer cont2.Destroy()
|
||||||
|
|
||||||
if err := cont2.Restore(conf, dir); err != nil {
|
if err := cont2.Restore(conf, dir, false /* direct */); err != nil {
|
||||||
t.Fatalf("error restoring container: %v", err)
|
t.Fatalf("error restoring container: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1377,7 +1377,7 @@ func TestUnixDomainSockets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer contRestore.Destroy()
|
defer contRestore.Destroy()
|
||||||
|
|
||||||
if err := contRestore.Restore(conf, dir); err != nil {
|
if err := contRestore.Restore(conf, dir, false /* direct */); err != nil {
|
||||||
t.Fatalf("error restoring container: %v", err)
|
t.Fatalf("error restoring container: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ func (s *Sandbox) StartSubcontainer(spec *specs.Spec, conf *config.Config, cid s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Restore sends the restore call for a container in the sandbox.
|
// Restore sends the restore call for a container in the sandbox.
|
||||||
func (s *Sandbox) Restore(conf *config.Config, cid string, imagePath string) error {
|
func (s *Sandbox) Restore(conf *config.Config, cid string, imagePath string, direct bool) error {
|
||||||
log.Debugf("Restore sandbox %q", s.ID)
|
log.Debugf("Restore sandbox %q", s.ID)
|
||||||
|
|
||||||
stateFileName := path.Join(imagePath, boot.CheckpointStateFileName)
|
stateFileName := path.Join(imagePath, boot.CheckpointStateFileName)
|
||||||
@@ -459,9 +459,14 @@ func (s *Sandbox) Restore(conf *config.Config, cid string, imagePath string) err
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the image file exists, we must pass it in.
|
// If the pages file exists, we must pass it in.
|
||||||
pagesFileName := path.Join(imagePath, boot.CheckpointPagesFileName)
|
pagesFileName := path.Join(imagePath, boot.CheckpointPagesFileName)
|
||||||
if pf, err := os.Open(pagesFileName); err == nil {
|
pagesReadFlags := os.O_RDONLY
|
||||||
|
if direct {
|
||||||
|
// The contents are page-aligned, so it can be opened with O_DIRECT.
|
||||||
|
pagesReadFlags |= syscall.O_DIRECT
|
||||||
|
}
|
||||||
|
if pf, err := os.OpenFile(pagesFileName, pagesReadFlags, 0); err == nil {
|
||||||
defer pf.Close()
|
defer pf.Close()
|
||||||
opt.HavePagesFile = true
|
opt.HavePagesFile = true
|
||||||
opt.FilePayload.Files = append(opt.FilePayload.Files, pf)
|
opt.FilePayload.Files = append(opt.FilePayload.Files, pf)
|
||||||
@@ -1289,9 +1294,10 @@ func (s *Sandbox) Checkpoint(cid string, imagePath string, options statefile.Opt
|
|||||||
|
|
||||||
// When there is no compression, MemoryFile contents are page-aligned.
|
// When there is no compression, MemoryFile contents are page-aligned.
|
||||||
// It is beneficial to store them separately so certain optimizations can be
|
// It is beneficial to store them separately so certain optimizations can be
|
||||||
// applied during restore.
|
// applied during restore. See Restore().
|
||||||
if options.Compression == statefile.CompressionLevelNone {
|
if options.Compression == statefile.CompressionLevelNone {
|
||||||
pagesFilePath := filepath.Join(imagePath, boot.CheckpointPagesFileName)
|
pagesFilePath := filepath.Join(imagePath, boot.CheckpointPagesFileName)
|
||||||
|
// TODO(b/327603247): Implement optional async O_DIRECT write.
|
||||||
pf, err := os.OpenFile(pagesFilePath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0644)
|
pf, err := os.OpenFile(pagesFilePath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating checkpoint pages file %q: %w", pagesFilePath, err)
|
return fmt.Errorf("creating checkpoint pages file %q: %w", pagesFilePath, err)
|
||||||
|
|||||||
Reference in New Issue
Block a user