ct: give criu informations about cgroup mounts
Actually cgroup mounts are bind-mounts, so they should be handled by the same way. Reported-by: Ross Boucher <rboucher@gmail.com> Signed-off-by: Andrey Vagin <avagin@openvz.org>
This commit is contained in:
parent
1eeb86fbf2
commit
af4a5e708a
|
@ -293,6 +293,19 @@ func (c *linuxContainer) checkCriuVersion() error {
|
||||||
|
|
||||||
const descriptors_filename = "descriptors.json"
|
const descriptors_filename = "descriptors.json"
|
||||||
|
|
||||||
|
func (c *linuxContainer) addCriuDumpMount(req *criurpc.CriuReq, m *configs.Mount) {
|
||||||
|
mountDest := m.Destination
|
||||||
|
if strings.HasPrefix(mountDest, c.config.Rootfs) {
|
||||||
|
mountDest = mountDest[len(c.config.Rootfs):]
|
||||||
|
}
|
||||||
|
|
||||||
|
extMnt := &criurpc.ExtMountMap{
|
||||||
|
Key: proto.String(mountDest),
|
||||||
|
Val: proto.String(mountDest),
|
||||||
|
}
|
||||||
|
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
||||||
c.m.Lock()
|
c.m.Lock()
|
||||||
defer c.m.Unlock()
|
defer c.m.Unlock()
|
||||||
|
@ -356,22 +369,25 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
t := criurpc.CriuReqType_DUMP
|
t := criurpc.CriuReqType_DUMP
|
||||||
req := criurpc.CriuReq{
|
req := &criurpc.CriuReq{
|
||||||
Type: &t,
|
Type: &t,
|
||||||
Opts: &rpcOpts,
|
Opts: &rpcOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range c.config.Mounts {
|
for _, m := range c.config.Mounts {
|
||||||
if m.Device == "bind" {
|
switch m.Device {
|
||||||
mountDest := m.Destination
|
case "bind":
|
||||||
if strings.HasPrefix(mountDest, c.config.Rootfs) {
|
c.addCriuDumpMount(req, m)
|
||||||
mountDest = mountDest[len(c.config.Rootfs):]
|
break
|
||||||
|
case "cgroup":
|
||||||
|
binds, err := getCgroupMounts(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
for _, b := range binds {
|
||||||
extMnt := new(criurpc.ExtMountMap)
|
c.addCriuDumpMount(req, b)
|
||||||
extMnt.Key = proto.String(mountDest)
|
}
|
||||||
extMnt.Val = proto.String(mountDest)
|
break
|
||||||
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,13 +403,26 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.criuSwrk(nil, &req, criuOpts)
|
err = c.criuSwrk(nil, req, criuOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *linuxContainer) addCriuRestoreMount(req *criurpc.CriuReq, m *configs.Mount) {
|
||||||
|
mountDest := m.Destination
|
||||||
|
if strings.HasPrefix(mountDest, c.config.Rootfs) {
|
||||||
|
mountDest = mountDest[len(c.config.Rootfs):]
|
||||||
|
}
|
||||||
|
|
||||||
|
extMnt := &criurpc.ExtMountMap{
|
||||||
|
Key: proto.String(mountDest),
|
||||||
|
Val: proto.String(m.Source),
|
||||||
|
}
|
||||||
|
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
||||||
c.m.Lock()
|
c.m.Lock()
|
||||||
defer c.m.Unlock()
|
defer c.m.Unlock()
|
||||||
|
@ -449,7 +478,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
||||||
defer syscall.Unmount(root, syscall.MNT_DETACH)
|
defer syscall.Unmount(root, syscall.MNT_DETACH)
|
||||||
|
|
||||||
t := criurpc.CriuReqType_RESTORE
|
t := criurpc.CriuReqType_RESTORE
|
||||||
req := criurpc.CriuReq{
|
req := &criurpc.CriuReq{
|
||||||
Type: &t,
|
Type: &t,
|
||||||
Opts: &criurpc.CriuOpts{
|
Opts: &criurpc.CriuOpts{
|
||||||
ImagesDirFd: proto.Int32(int32(imageDir.Fd())),
|
ImagesDirFd: proto.Int32(int32(imageDir.Fd())),
|
||||||
|
@ -468,16 +497,19 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, m := range c.config.Mounts {
|
for _, m := range c.config.Mounts {
|
||||||
if m.Device == "bind" {
|
switch m.Device {
|
||||||
mountDest := m.Destination
|
case "bind":
|
||||||
if strings.HasPrefix(mountDest, c.config.Rootfs) {
|
c.addCriuRestoreMount(req, m)
|
||||||
mountDest = mountDest[len(c.config.Rootfs):]
|
break
|
||||||
|
case "cgroup":
|
||||||
|
binds, err := getCgroupMounts(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
for _, b := range binds {
|
||||||
extMnt := new(criurpc.ExtMountMap)
|
c.addCriuRestoreMount(req, b)
|
||||||
extMnt.Key = proto.String(mountDest)
|
}
|
||||||
extMnt.Val = proto.String(m.Source)
|
break
|
||||||
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, iface := range c.config.Networks {
|
for _, iface := range c.config.Networks {
|
||||||
|
@ -515,7 +547,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.criuSwrk(process, &req, criuOpts)
|
err = c.criuSwrk(process, req, criuOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,27 +170,10 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "cgroup":
|
case "cgroup":
|
||||||
mounts, err := cgroups.GetCgroupMounts()
|
binds, err := getCgroupMounts(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var binds []*configs.Mount
|
|
||||||
for _, mm := range mounts {
|
|
||||||
dir, err := mm.GetThisCgroupDir()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
relDir, err := filepath.Rel(mm.Root, dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
binds = append(binds, &configs.Mount{
|
|
||||||
Device: "bind",
|
|
||||||
Source: filepath.Join(mm.Mountpoint, relDir),
|
|
||||||
Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
|
|
||||||
Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
tmpfs := &configs.Mount{
|
tmpfs := &configs.Mount{
|
||||||
Source: "tmpfs",
|
Source: "tmpfs",
|
||||||
Device: "tmpfs",
|
Device: "tmpfs",
|
||||||
|
@ -211,6 +194,34 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
|
||||||
|
mounts, err := cgroups.GetCgroupMounts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var binds []*configs.Mount
|
||||||
|
|
||||||
|
for _, mm := range mounts {
|
||||||
|
dir, err := mm.GetThisCgroupDir()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
relDir, err := filepath.Rel(mm.Root, dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
binds = append(binds, &configs.Mount{
|
||||||
|
Device: "bind",
|
||||||
|
Source: filepath.Join(mm.Mountpoint, relDir),
|
||||||
|
Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
|
||||||
|
Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return binds, nil
|
||||||
|
}
|
||||||
|
|
||||||
// checkMountDestination checks to ensure that the mount destination is not over the
|
// checkMountDestination checks to ensure that the mount destination is not over the
|
||||||
// top of /proc or /sys.
|
// top of /proc or /sys.
|
||||||
// dest is required to be an abs path and have any symlinks resolved before calling this function.
|
// dest is required to be an abs path and have any symlinks resolved before calling this function.
|
||||||
|
|
Loading…
Reference in New Issue