Skip to content
This repository has been archived by the owner on Feb 8, 2023. It is now read-only.

Commit

Permalink
Merge pull request #19 from alibaba/update_2019_0213
Browse files Browse the repository at this point in the history
Update runc 2019 0213
  • Loading branch information
fuweid authored Feb 13, 2019
2 parents 6a93df1 + e73c8b3 commit 4df7cda
Show file tree
Hide file tree
Showing 299 changed files with 88,186 additions and 14,189 deletions.
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ RUN cd /tmp \
&& rm -rf /tmp/bats

# install criu
# For CRIU 3.11 one patch is needed for the test 'checkpoint and restore with container specific CRIU config'
# This should be no longer necessary with CRIU 3.12
# See https://github.com/opencontainers/runc/pull/1933
ENV CRIU_VERSION v3.11
RUN mkdir -p /usr/src/criu \
&& curl -sSL https://github.com/checkpoint-restore/criu/archive/${CRIU_VERSION}.tar.gz | tar -v -C /usr/src/criu/ -xz --strip-components=1 \
&& cd /usr/src/criu \
&& curl https://github.com/checkpoint-restore/criu/commit/bb0b2f2635d71e549851b7c626a1464e42a3b5c7.patch | patch -p1 \
&& make install-criu \
&& rm -rf /usr/src/criu

Expand Down
50 changes: 50 additions & 0 deletions docs/checkpoint-restore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Checkpoint and Restore #

For a basic description about checkpointing and restoring containers with
`runc` please see [runc-checkpoint(8)](../man/runc-checkpoint.8.md) and
[runc-restore(8)](../man/runc-restore.8.md).

## Checkpoint/Restore Annotations ##

In addition to specifying options on the command-line like it is described
in the man-pages (see above), it is also possible to influence CRIU's
behaviour using CRIU configuration files. For details about CRIU's
configuration file support please see [CRIU's wiki](https://criu.org/Configuration_files).

In addition to CRIU's default configuration files `runc` tells CRIU to
also evaluate the file `/etc/criu/runc.conf`. Using the annotation
`org.criu.config` it is, however, possible to change this additional
CRIU configuration file.

If the annotation `org.criu.config` is set to an empty string `runc`
will not pass any additional configuration file to CRIU. With an empty
string it is therefore possible to disable the additional CRIU configuration
file. This can be used to make sure that no additional configuration file
changes CRIU's behaviour accidentally.

If the annotation `org.criu.config` is set to a non-empty string `runc` will
pass that string to CRIU to be evaluated as an additional configuration file.
If CRIU cannot open this additional configuration file, it will ignore this
file and continue.

### Annotation Example to disable additional CRIU configuration file ###

```
{
"ociVersion": "1.0.0",
"annotations": {
"org.criu.config": ""
},
"process": {
```

### Annotation Example to set a specific CRIU configuration file ###

```
{
"ociVersion": "1.0.0",
"annotations": {
"org.criu.config": "/etc/special-runc-criu-options"
},
"process": {
```
10 changes: 10 additions & 0 deletions libcontainer/cgroups/systemd/apply_systemd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package systemd
import (
"errors"
"fmt"
"io/ioutil"
"math"
"os"
"path/filepath"
Expand Down Expand Up @@ -590,6 +591,15 @@ func setKernelMemory(c *configs.Cgroup) error {
if err := os.MkdirAll(path, 0755); err != nil {
return err
}
// do not try to enable the kernel memory if we already have
// tasks in the cgroup.
content, err := ioutil.ReadFile(filepath.Join(path, "tasks"))
if err != nil {
return err
}
if len(content) > 0 {
return nil
}
return fs.EnableKernelMemoryAccounting(path)
}

Expand Down
40 changes: 35 additions & 5 deletions libcontainer/cgroups/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

units "github.com/docker/go-units"
"golang.org/x/sys/unix"
)

const (
Expand Down Expand Up @@ -463,11 +464,40 @@ func WriteCgroupProc(dir string, pid int) error {
return fmt.Errorf("no such directory for %s", CgroupProcesses)
}

// Don't attach any pid to the cgroup if -1 is specified as a pid
if pid != -1 {
if err := ioutil.WriteFile(filepath.Join(dir, CgroupProcesses), []byte(strconv.Itoa(pid)), 0700); err != nil {
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
// Dont attach any pid to the cgroup if -1 is specified as a pid
if pid == -1 {
return nil
}

cgroupProcessesFile, err := os.OpenFile(filepath.Join(dir, CgroupProcesses), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
if err != nil {
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
}
defer cgroupProcessesFile.Close()

for i := 0; i < 5; i++ {
_, err = cgroupProcessesFile.WriteString(strconv.Itoa(pid))
if err == nil {
return nil
}

// EINVAL might mean that the task being added to cgroup.procs is in state
// TASK_NEW. We should attempt to do so again.
if isEINVAL(err) {
time.Sleep(30 * time.Millisecond)
continue
}

return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
}
return err
}

func isEINVAL(err error) bool {
switch err := err.(type) {
case *os.PathError:
return err.Err == unix.EINVAL
default:
return false
}
return nil
}
30 changes: 30 additions & 0 deletions libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,32 @@ func waitForCriuLazyServer(r *os.File, status string) error {
return nil
}

func (c *linuxContainer) handleCriuConfigurationFile(rpcOpts *criurpc.CriuOpts) {
// CRIU will evaluate a configuration starting with release 3.11.
// Settings in the configuration file will overwrite RPC settings.
// Look for annotations. The annotation 'org.criu.config'
// specifies if CRIU should use a different, container specific
// configuration file.
_, annotations := utils.Annotations(c.config.Labels)
configFile, exists := annotations["org.criu.config"]
if exists {
// If the annotation 'org.criu.config' exists and is set
// to a non-empty string, tell CRIU to use that as a
// configuration file. If the file does not exist, CRIU
// will just ignore it.
if configFile != "" {
rpcOpts.ConfigFile = proto.String(configFile)
}
// If 'org.criu.config' exists and is set to an empty
// string, a runc specific CRIU configuration file will
// be not set at all.
} else {
// If the mentioned annotation has not been found, specify
// a default CRIU configuration file.
rpcOpts.ConfigFile = proto.String("/etc/criu/runc.conf")
}
}

func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
c.m.Lock()
defer c.m.Unlock()
Expand Down Expand Up @@ -940,6 +966,8 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error {
LazyPages: proto.Bool(criuOpts.LazyPages),
}

c.handleCriuConfigurationFile(&rpcOpts)

// If the container is running in a network namespace and has
// a path to the network namespace configured, we will dump
// that network namespace as an external namespace and we
Expand Down Expand Up @@ -1190,6 +1218,8 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
},
}

c.handleCriuConfigurationFile(req.Opts)

// Same as during checkpointing. If the container has a specific network namespace
// assigned to it, this now expects that the checkpoint will be restored in a
// already created network namespace.
Expand Down
Loading

0 comments on commit 4df7cda

Please sign in to comment.