Enable checkpoint/restore for /dev/shm

When Podman is running a container in private IPC mode (default), it
creates a bind mount for /dev/shm that is then attached to a tmpfs
folder on the host file system. However, checkpointing a container has
the side-effect of stopping that container and unmount the tmpfs used
for /dev/shm. As a result, after checkpoint all files stored in the
container's /dev/shm would be lost and the container might fail to
restore from checkpoint.

To address this problem, this patch creates a tar file with the
content of /dev/shm that is included in the container checkpoint and
used to restore the container.

Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit is contained in:
Radostin Stoyanov 2021-12-20 19:28:24 +00:00
parent 2d7dbda415
commit f3d485d4d7
No known key found for this signature in database
GPG key ID: 21C246FD7C1157A7

View file

@ -990,6 +990,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
includeFiles := []string{
"artifacts",
metadata.DevShmCheckpointTar,
metadata.ConfigDumpFile,
metadata.SpecDumpFile,
metadata.NetworkStatusFile,
@ -1143,6 +1144,29 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO
return nil, 0, err
}
// Keep the content of /dev/shm directory
if c.config.ShmDir != "" && c.state.BindMounts["/dev/shm"] == c.config.ShmDir {
shmDirTarFileFullPath := filepath.Join(c.bundlePath(), metadata.DevShmCheckpointTar)
shmDirTarFile, err := os.Create(shmDirTarFileFullPath)
if err != nil {
return nil, 0, err
}
defer shmDirTarFile.Close()
input, err := archive.TarWithOptions(c.config.ShmDir, &archive.TarOptions{
Compression: archive.Uncompressed,
IncludeSourceDir: true,
})
if err != nil {
return nil, 0, err
}
if _, err = io.Copy(shmDirTarFile, input); err != nil {
return nil, 0, err
}
}
// Save network.status. This is needed to restore the container with
// the same IP. Currently limited to one IP address in a container
// with one interface.
@ -1486,6 +1510,24 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti
}
}
// Restore /dev/shm content
if c.config.ShmDir != "" && c.state.BindMounts["/dev/shm"] == c.config.ShmDir {
shmDirTarFileFullPath := filepath.Join(c.bundlePath(), metadata.DevShmCheckpointTar)
if _, err := os.Stat(shmDirTarFileFullPath); err != nil {
logrus.Debug("Container checkpoint doesn't contain dev/shm: ", err.Error())
} else {
shmDirTarFile, err := os.Open(shmDirTarFileFullPath)
if err != nil {
return nil, 0, err
}
defer shmDirTarFile.Close()
if err := archive.UntarUncompressed(shmDirTarFile, c.config.ShmDir, nil); err != nil {
return nil, 0, err
}
}
}
// Cleanup for a working restore.
if err := c.removeConmonFiles(); err != nil {
return nil, 0, err