Browse Source

Merge pull request #12180 from Mashimiao/add-cpuperiod-and-cpuquota-support

add cpu.cfs_period_us  support
Sebastiaan van Stijn 10 years ago
parent
commit
7699cee247

+ 2 - 0
api/client/build.go

@@ -55,6 +55,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
 	flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit")
 	flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit")
 	flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
 	flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
 	flCPUShares := cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
 	flCPUShares := cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
+	flCpuPeriod := cmd.Int64([]string{"-cpu-period"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
 	flCpuQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
 	flCpuQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
 	flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
 	flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
 	flCPUSetMems := cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
 	flCPUSetMems := cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
@@ -275,6 +276,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
 	v.Set("cpusetmems", *flCPUSetMems)
 	v.Set("cpusetmems", *flCPUSetMems)
 	v.Set("cpushares", strconv.FormatInt(*flCPUShares, 10))
 	v.Set("cpushares", strconv.FormatInt(*flCPUShares, 10))
 	v.Set("cpuquota", strconv.FormatInt(*flCpuQuota, 10))
 	v.Set("cpuquota", strconv.FormatInt(*flCpuQuota, 10))
+	v.Set("cpuperiod", strconv.FormatInt(*flCpuPeriod, 10))
 	v.Set("memory", strconv.FormatInt(memory, 10))
 	v.Set("memory", strconv.FormatInt(memory, 10))
 	v.Set("memswap", strconv.FormatInt(memorySwap, 10))
 	v.Set("memswap", strconv.FormatInt(memorySwap, 10))
 	v.Set("cgroupparent", *flCgroupParent)
 	v.Set("cgroupparent", *flCgroupParent)

+ 1 - 0
api/server/server.go

@@ -1294,6 +1294,7 @@ func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *ht
 	buildConfig.MemorySwap = int64ValueOrZero(r, "memswap")
 	buildConfig.MemorySwap = int64ValueOrZero(r, "memswap")
 	buildConfig.Memory = int64ValueOrZero(r, "memory")
 	buildConfig.Memory = int64ValueOrZero(r, "memory")
 	buildConfig.CpuShares = int64ValueOrZero(r, "cpushares")
 	buildConfig.CpuShares = int64ValueOrZero(r, "cpushares")
+	buildConfig.CpuPeriod = int64ValueOrZero(r, "cpuperiod")
 	buildConfig.CpuQuota = int64ValueOrZero(r, "cpuquota")
 	buildConfig.CpuQuota = int64ValueOrZero(r, "cpuquota")
 	buildConfig.CpuSetCpus = r.FormValue("cpusetcpus")
 	buildConfig.CpuSetCpus = r.FormValue("cpusetcpus")
 	buildConfig.CpuSetMems = r.FormValue("cpusetmems")
 	buildConfig.CpuSetMems = r.FormValue("cpusetmems")

+ 1 - 0
api/types/types.go

@@ -152,6 +152,7 @@ type Info struct {
 	DriverStatus       [][2]string
 	DriverStatus       [][2]string
 	MemoryLimit        bool
 	MemoryLimit        bool
 	SwapLimit          bool
 	SwapLimit          bool
+	CpuCfsPeriod       bool
 	CpuCfsQuota        bool
 	CpuCfsQuota        bool
 	IPv4Forwarding     bool
 	IPv4Forwarding     bool
 	Debug              bool
 	Debug              bool

+ 1 - 0
builder/evaluator.go

@@ -124,6 +124,7 @@ type Builder struct {
 	cpuSetCpus   string
 	cpuSetCpus   string
 	cpuSetMems   string
 	cpuSetMems   string
 	cpuShares    int64
 	cpuShares    int64
+	cpuPeriod    int64
 	cpuQuota     int64
 	cpuQuota     int64
 	cgroupParent string
 	cgroupParent string
 	memory       int64
 	memory       int64

+ 1 - 0
builder/internals.go

@@ -556,6 +556,7 @@ func (b *Builder) create() (*daemon.Container, error) {
 
 
 	hostConfig := &runconfig.HostConfig{
 	hostConfig := &runconfig.HostConfig{
 		CpuShares:    b.cpuShares,
 		CpuShares:    b.cpuShares,
+		CpuPeriod:    b.cpuPeriod,
 		CpuQuota:     b.cpuQuota,
 		CpuQuota:     b.cpuQuota,
 		CpusetCpus:   b.cpuSetCpus,
 		CpusetCpus:   b.cpuSetCpus,
 		CpusetMems:   b.cpuSetMems,
 		CpusetMems:   b.cpuSetMems,

+ 2 - 0
builder/job.go

@@ -49,6 +49,7 @@ type Config struct {
 	Memory         int64
 	Memory         int64
 	MemorySwap     int64
 	MemorySwap     int64
 	CpuShares      int64
 	CpuShares      int64
+	CpuPeriod      int64
 	CpuQuota       int64
 	CpuQuota       int64
 	CpuSetCpus     string
 	CpuSetCpus     string
 	CpuSetMems     string
 	CpuSetMems     string
@@ -164,6 +165,7 @@ func Build(d *daemon.Daemon, buildConfig *Config) error {
 		ConfigFile:      buildConfig.ConfigFile,
 		ConfigFile:      buildConfig.ConfigFile,
 		dockerfileName:  buildConfig.DockerfileName,
 		dockerfileName:  buildConfig.DockerfileName,
 		cpuShares:       buildConfig.CpuShares,
 		cpuShares:       buildConfig.CpuShares,
+		cpuPeriod:       buildConfig.CpuPeriod,
 		cpuQuota:        buildConfig.CpuQuota,
 		cpuQuota:        buildConfig.CpuQuota,
 		cpuSetCpus:      buildConfig.CpuSetCpus,
 		cpuSetCpus:      buildConfig.CpuSetCpus,
 		cpuSetMems:      buildConfig.CpuSetMems,
 		cpuSetMems:      buildConfig.CpuSetMems,

+ 1 - 0
contrib/completion/bash/docker

@@ -778,6 +778,7 @@ _docker_run() {
 		--cidfile
 		--cidfile
 		--cpuset
 		--cpuset
 		--cpu-shares -c
 		--cpu-shares -c
+		--cpu-period
 		--cpu-quota
 		--cpu-quota
 		--device
 		--device
 		--dns
 		--dns

+ 1 - 0
daemon/container.go

@@ -383,6 +383,7 @@ func populateCommand(c *Container, env []string) error {
 		CpuShares:      c.hostConfig.CpuShares,
 		CpuShares:      c.hostConfig.CpuShares,
 		CpusetCpus:     c.hostConfig.CpusetCpus,
 		CpusetCpus:     c.hostConfig.CpusetCpus,
 		CpusetMems:     c.hostConfig.CpusetMems,
 		CpusetMems:     c.hostConfig.CpusetMems,
+		CpuPeriod:      c.hostConfig.CpuPeriod,
 		CpuQuota:       c.hostConfig.CpuQuota,
 		CpuQuota:       c.hostConfig.CpuQuota,
 		BlkioWeight:    c.hostConfig.BlkioWeight,
 		BlkioWeight:    c.hostConfig.BlkioWeight,
 		Rlimits:        rlimits,
 		Rlimits:        rlimits,

+ 4 - 0
daemon/daemon.go

@@ -1170,6 +1170,10 @@ func (daemon *Daemon) verifyHostConfig(hostConfig *runconfig.HostConfig) ([]stri
 	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
 	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
 		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
 		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
 	}
 	}
+	if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod {
+		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
+		hostConfig.CpuPeriod = 0
+	}
 	if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota {
 	if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota {
 		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
 		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
 		hostConfig.CpuQuota = 0
 		hostConfig.CpuQuota = 0

+ 1 - 0
daemon/execdriver/driver.go

@@ -106,6 +106,7 @@ type Resources struct {
 	CpuShares      int64            `json:"cpu_shares"`
 	CpuShares      int64            `json:"cpu_shares"`
 	CpusetCpus     string           `json:"cpuset_cpus"`
 	CpusetCpus     string           `json:"cpuset_cpus"`
 	CpusetMems     string           `json:"cpuset_mems"`
 	CpusetMems     string           `json:"cpuset_mems"`
+	CpuPeriod      int64            `json:"cpu_period"`
 	CpuQuota       int64            `json:"cpu_quota"`
 	CpuQuota       int64            `json:"cpu_quota"`
 	BlkioWeight    int64            `json:"blkio_weight"`
 	BlkioWeight    int64            `json:"blkio_weight"`
 	Rlimits        []*ulimit.Rlimit `json:"rlimits"`
 	Rlimits        []*ulimit.Rlimit `json:"rlimits"`

+ 1 - 0
daemon/execdriver/driver_linux.go

@@ -53,6 +53,7 @@ func SetupCgroups(container *configs.Config, c *Command) error {
 		container.Cgroups.MemorySwap = c.Resources.MemorySwap
 		container.Cgroups.MemorySwap = c.Resources.MemorySwap
 		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
 		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
 		container.Cgroups.CpusetMems = c.Resources.CpusetMems
 		container.Cgroups.CpusetMems = c.Resources.CpusetMems
+		container.Cgroups.CpuPeriod = c.Resources.CpuPeriod
 		container.Cgroups.CpuQuota = c.Resources.CpuQuota
 		container.Cgroups.CpuQuota = c.Resources.CpuQuota
 		container.Cgroups.BlkioWeight = c.Resources.BlkioWeight
 		container.Cgroups.BlkioWeight = c.Resources.BlkioWeight
 		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
 		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable

+ 3 - 0
daemon/execdriver/lxc/lxc_template.go

@@ -109,6 +109,9 @@ lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
 {{if .Resources.CpuShares}}
 {{if .Resources.CpuShares}}
 lxc.cgroup.cpu.shares = {{.Resources.CpuShares}}
 lxc.cgroup.cpu.shares = {{.Resources.CpuShares}}
 {{end}}
 {{end}}
+{{if .Resources.CpuPeriod}}
+lxc.cgroup.cpu.cfs_period_us = {{.Resources.CpuPeriod}}
+{{end}}
 {{if .Resources.CpusetCpus}}
 {{if .Resources.CpusetCpus}}
 lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
 lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
 {{end}}
 {{end}}

+ 1 - 0
daemon/info.go

@@ -64,6 +64,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 		DriverStatus:       daemon.GraphDriver().Status(),
 		DriverStatus:       daemon.GraphDriver().Status(),
 		MemoryLimit:        daemon.SystemConfig().MemoryLimit,
 		MemoryLimit:        daemon.SystemConfig().MemoryLimit,
 		SwapLimit:          daemon.SystemConfig().SwapLimit,
 		SwapLimit:          daemon.SystemConfig().SwapLimit,
+		CpuCfsPeriod:       daemon.SystemConfig().CpuCfsPeriod,
 		CpuCfsQuota:        daemon.SystemConfig().CpuCfsQuota,
 		CpuCfsQuota:        daemon.SystemConfig().CpuCfsQuota,
 		IPv4Forwarding:     !daemon.SystemConfig().IPv4ForwardingDisabled,
 		IPv4Forwarding:     !daemon.SystemConfig().IPv4ForwardingDisabled,
 		Debug:              os.Getenv("DEBUG") != "",
 		Debug:              os.Getenv("DEBUG") != "",

+ 4 - 0
docs/man/docker-create.1.md

@@ -13,6 +13,7 @@ docker-create - Create a new container
 [**--cap-add**[=*[]*]]
 [**--cap-add**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cidfile**[=*CIDFILE*]]
 [**--cidfile**[=*CIDFILE*]]
+[**--cpu-period**[=*0*]]
 [**--cpuset-cpus**[=*CPUSET-CPUS*]]
 [**--cpuset-cpus**[=*CPUSET-CPUS*]]
 [**--cpuset-mems**[=*CPUSET-MEMS*]]
 [**--cpuset-mems**[=*CPUSET-MEMS*]]
 [**--cpu-quota**[=*0*]]
 [**--cpu-quota**[=*0*]]
@@ -78,6 +79,9 @@ IMAGE [COMMAND] [ARG...]
 **--cgroup-parent**=""
 **--cgroup-parent**=""
    Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.
    Path to cgroups under which the cgroup for the container will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.
 
 
+**--cpu-peroid**=0
+    Limit the CPU CFS (Completely Fair Scheduler) period
+
 **--cpuset-cpus**=""
 **--cpuset-cpus**=""
    CPUs in which to allow execution (0-3, 0,1)
    CPUs in which to allow execution (0-3, 0,1)
 
 

+ 6 - 0
docs/man/docker-run.1.md

@@ -13,6 +13,7 @@ docker-run - Run a command in a new container
 [**--cap-add**[=*[]*]]
 [**--cap-add**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cidfile**[=*CIDFILE*]]
 [**--cidfile**[=*CIDFILE*]]
+[**--cpu-period**[=*0*]]
 [**--cpuset-cpus**[=*CPUSET-CPUS*]]
 [**--cpuset-cpus**[=*CPUSET-CPUS*]]
 [**--cpuset-mems**[=*CPUSET-MEMS*]]
 [**--cpuset-mems**[=*CPUSET-MEMS*]]
 [**-d**|**--detach**[=*false*]]
 [**-d**|**--detach**[=*false*]]
@@ -138,6 +139,11 @@ division of CPU shares:
 **--cidfile**=""
 **--cidfile**=""
    Write the container ID to the file
    Write the container ID to the file
 
 
+**--cpu-period**=0
+   Limit the CPU CFS (Completely Fair Scheduler) period
+
+   Limit the container's CPU usage. This flag tell the kernel to restrict the container's CPU usage to the period you specify.
+
 **--cpuset-cpus**=""
 **--cpuset-cpus**=""
    CPUs in which to allow execution (0-3, 0,1)
    CPUs in which to allow execution (0-3, 0,1)
 
 

+ 3 - 0
docs/sources/reference/api/docker_remote_api_v1.19.md

@@ -147,6 +147,7 @@ Create a container
                "Memory": 0,
                "Memory": 0,
                "MemorySwap": 0,
                "MemorySwap": 0,
                "CpuShares": 512,
                "CpuShares": 512,
+               "CpuPeriod": 100000,
                "CpusetCpus": "0,1",
                "CpusetCpus": "0,1",
                "CpusetMems": "0,1",
                "CpusetMems": "0,1",
                "BlkioWeight": 300,
                "BlkioWeight": 300,
@@ -193,6 +194,7 @@ Json Parameters:
       always use this with `memory`, and make the value larger than `memory`.
       always use this with `memory`, and make the value larger than `memory`.
 -   **CpuShares** - An integer value containing the CPU Shares for container
 -   **CpuShares** - An integer value containing the CPU Shares for container
       (ie. the relative weight vs other containers).
       (ie. the relative weight vs other containers).
+-   **CpuPeriod** - The length of a CPU period (in microseconds).
 -   **Cpuset** - The same as CpusetCpus, but deprecated, please don't use.
 -   **Cpuset** - The same as CpusetCpus, but deprecated, please don't use.
 -   **CpusetCpus** - String value containing the cgroups CpusetCpus to use.
 -   **CpusetCpus** - String value containing the cgroups CpusetCpus to use.
 -   **CpusetMems** - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
 -   **CpusetMems** - Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
@@ -350,6 +352,7 @@ Return low-level information on the container `id`
 			"CpusetCpus": "",
 			"CpusetCpus": "",
 			"CpusetMems": "",
 			"CpusetMems": "",
 			"CpuShares": 0,
 			"CpuShares": 0,
+			"CpuPeriod": 100000,
 			"Devices": [],
 			"Devices": [],
 			"Dns": null,
 			"Dns": null,
 			"DnsSearch": null,
 			"DnsSearch": null,

+ 2 - 0
docs/sources/reference/commandline/cli.md

@@ -950,6 +950,7 @@ Creates a new container.
       --cidfile=""               Write the container ID to the file
       --cidfile=""               Write the container ID to the file
       --cpuset-cpus=""           CPUs in which to allow execution (0-3, 0,1)
       --cpuset-cpus=""           CPUs in which to allow execution (0-3, 0,1)
       --cpuset-mems=""           Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
       --cpuset-mems=""           Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
+      --cpu-period=0             Limit the CPU CFS (Completely Fair Scheduler) period
       --cpu-quota=0              Limit the CPU CFS (Completely Fair Scheduler) quota
       --cpu-quota=0              Limit the CPU CFS (Completely Fair Scheduler) quota
       --device=[]                Add a host device to the container
       --device=[]                Add a host device to the container
       --dns=[]                   Set custom DNS servers
       --dns=[]                   Set custom DNS servers
@@ -1907,6 +1908,7 @@ To remove an image using its digest:
       --cidfile=""               Write the container ID to the file
       --cidfile=""               Write the container ID to the file
       --cpuset-cpus=""           CPUs in which to allow execution (0-3, 0,1)
       --cpuset-cpus=""           CPUs in which to allow execution (0-3, 0,1)
       --cpuset-mems=""           Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
       --cpuset-mems=""           Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
+      --cpu-period=0             Limit the CPU CFS (Completely Fair Scheduler) period
       --cpu-quota=0              Limit the CPU CFS (Completely Fair Scheduler) quota
       --cpu-quota=0              Limit the CPU CFS (Completely Fair Scheduler) quota
       -d, --detach=false         Run container in background and print container ID
       -d, --detach=false         Run container in background and print container ID
       --device=[]                Add a host device to the container
       --device=[]                Add a host device to the container

+ 15 - 0
docs/sources/reference/run.md

@@ -483,6 +483,7 @@ container:
     -m, --memory="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
     -m, --memory="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g)
     -memory-swap="": Total memory limit (memory + swap, format: <number><optional unit>, where unit = b, k, m or g)
     -memory-swap="": Total memory limit (memory + swap, format: <number><optional unit>, where unit = b, k, m or g)
     -c, --cpu-shares=0: CPU shares (relative weight)
     -c, --cpu-shares=0: CPU shares (relative weight)
+    --cpu-period=0: Limit the CPU CFS (Completely Fair Scheduler) period
     --cpuset-cpus="": CPUs in which to allow execution (0-3, 0,1)
     --cpuset-cpus="": CPUs in which to allow execution (0-3, 0,1)
     --cpuset-mems="": Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
     --cpuset-mems="": Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.
     --cpu-quota=0: Limit the CPU CFS (Completely Fair Scheduler) quota
     --cpu-quota=0: Limit the CPU CFS (Completely Fair Scheduler) quota
@@ -620,6 +621,20 @@ division of CPU shares:
     101    {C1}		1	100% of CPU1
     101    {C1}		1	100% of CPU1
     102    {C1}		2	100% of CPU2
     102    {C1}		2	100% of CPU2
 
 
+### CPU period constraint
+
+The default CPU CFS (Completely Fair Scheduler) period is 100ms. We can use
+`--cpu-period` to set the period of CPUs to limit the container's CPU usage. 
+And usually `--cpu-period` should work with `--cpu-quota`.
+
+Examples:
+
+    $ docker run -ti --cpu-period=50000 --cpu-quota=25000 ubuntu:14.04 /bin/bash
+
+If there is 1 CPU, this means the container can get 50% CPU worth of run-time every 50ms.
+
+For more information, see the [CFS documentation on bandwidth limiting](https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt).
+
 ### Cpuset constraint
 ### Cpuset constraint
 
 
 We can set cpus in which to allow execution for containers.
 We can set cpus in which to allow execution for containers.

+ 22 - 0
integration-cli/docker_cli_run_test.go

@@ -1164,6 +1164,28 @@ func (s *DockerSuite) TestRunProcWritableInPrivilegedContainers(c *check.C) {
 	}
 	}
 }
 }
 
 
+func (s *DockerSuite) TestRunWithCpuPeriod(c *check.C) {
+	runCmd := exec.Command(dockerBinary, "run", "--cpu-period", "50000", "--name", "test", "busybox", "true")
+	out, _, _, err := runCommandWithStdoutStderr(runCmd)
+	if err != nil {
+		c.Fatalf("failed to run container: %v, output: %q", err, out)
+	}
+	out = strings.TrimSpace(out)
+	if strings.Contains(out, "Your kernel does not support CPU cfs period") {
+		c.Skip("Your kernel does not support CPU cfs period, skip this test")
+	}
+
+	cmd := exec.Command(dockerBinary, "inspect", "-f", "{{.HostConfig.CpuPeriod}}", "test")
+	out, _, err = runCommandWithOutput(cmd)
+	if err != nil {
+		c.Fatalf("failed to inspect container: %s, %v", out, err)
+	}
+	out = strings.TrimSpace(out)
+	if out != "50000" {
+		c.Errorf("setting the CPU CFS period failed")
+	}
+}
+
 func (s *DockerSuite) TestRunWithCpuset(c *check.C) {
 func (s *DockerSuite) TestRunWithCpuset(c *check.C) {
 	cmd := exec.Command(dockerBinary, "run", "--cpuset", "0", "busybox", "true")
 	cmd := exec.Command(dockerBinary, "run", "--cpuset", "0", "busybox", "true")
 	if code, err := runCommand(cmd); err != nil || code != 0 {
 	if code, err := runCommand(cmd); err != nil || code != 0 {

+ 10 - 2
pkg/sysinfo/sysinfo.go

@@ -15,6 +15,7 @@ import (
 type SysInfo struct {
 type SysInfo struct {
 	MemoryLimit            bool
 	MemoryLimit            bool
 	SwapLimit              bool
 	SwapLimit              bool
+	CpuCfsPeriod           bool
 	CpuCfsQuota            bool
 	CpuCfsQuota            bool
 	IPv4ForwardingDisabled bool
 	IPv4ForwardingDisabled bool
 	AppArmor               bool
 	AppArmor               bool
@@ -50,8 +51,15 @@ func New(quiet bool) *SysInfo {
 			logrus.Warnf("%v", err)
 			logrus.Warnf("%v", err)
 		}
 		}
 	} else {
 	} else {
-		_, err1 := ioutil.ReadFile(path.Join(cgroupCpuMountpoint, "cpu.cfs_quota_us"))
-		sysInfo.CpuCfsQuota = err1 == nil
+		_, err := ioutil.ReadFile(path.Join(cgroupCpuMountpoint, "cpu.cfs_period_us"))
+		logrus.Warnf("%s", cgroupCpuMountpoint)
+		sysInfo.CpuCfsPeriod = err == nil
+		if !sysInfo.CpuCfsPeriod && !quiet {
+			logrus.Warnf("WARING: Your kernel does not support cgroup cfs period")
+		}
+		_, err = ioutil.ReadFile(path.Join(cgroupCpuMountpoint, "cpu.cfs_quota_us"))
+		logrus.Warnf("%s", cgroupCpuMountpoint)
+		sysInfo.CpuCfsQuota = err == nil
 		if !sysInfo.CpuCfsQuota && !quiet {
 		if !sysInfo.CpuCfsQuota && !quiet {
 			logrus.Warn("Your kernel does not support cgroup cfs quotas")
 			logrus.Warn("Your kernel does not support cgroup cfs quotas")
 		}
 		}

+ 4 - 3
runconfig/hostconfig.go

@@ -166,9 +166,10 @@ type HostConfig struct {
 	Binds           []string
 	Binds           []string
 	ContainerIDFile string
 	ContainerIDFile string
 	LxcConf         *LxcConfig
 	LxcConf         *LxcConfig
-	Memory          int64  // Memory limit (in bytes)
-	MemorySwap      int64  // Total memory usage (memory + swap); set `-1` to disable swap
-	CpuShares       int64  // CPU shares (relative weight vs. other containers)
+	Memory          int64 // Memory limit (in bytes)
+	MemorySwap      int64 // Total memory usage (memory + swap); set `-1` to disable swap
+	CpuShares       int64 // CPU shares (relative weight vs. other containers)
+	CpuPeriod       int64
 	CpusetCpus      string // CpusetCpus 0-2, 0,1
 	CpusetCpus      string // CpusetCpus 0-2, 0,1
 	CpusetMems      string // CpusetMems 0-2, 0,1
 	CpusetMems      string // CpusetMems 0-2, 0,1
 	CpuQuota        int64
 	CpuQuota        int64

+ 2 - 0
runconfig/parse.go

@@ -64,6 +64,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		flUser            = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
 		flUser            = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
 		flWorkingDir      = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
 		flWorkingDir      = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
 		flCpuShares       = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
 		flCpuShares       = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
+		flCpuPeriod       = cmd.Int64([]string{"-cpu-period"}, 0, "Limit CPU CFS (Completely Fair Scheduler) period")
 		flCpusetCpus      = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
 		flCpusetCpus      = cmd.String([]string{"#-cpuset", "-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
 		flCpusetMems      = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
 		flCpusetMems      = cmd.String([]string{"-cpuset-mems"}, "", "MEMs in which to allow execution (0-3, 0,1)")
 		flCpuQuota        = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS quota")
 		flCpuQuota        = cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS quota")
@@ -319,6 +320,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		Memory:          flMemory,
 		Memory:          flMemory,
 		MemorySwap:      MemorySwap,
 		MemorySwap:      MemorySwap,
 		CpuShares:       *flCpuShares,
 		CpuShares:       *flCpuShares,
+		CpuPeriod:       *flCpuPeriod,
 		CpusetCpus:      *flCpusetCpus,
 		CpusetCpus:      *flCpusetCpus,
 		CpusetMems:      *flCpusetMems,
 		CpusetMems:      *flCpusetMems,
 		CpuQuota:        *flCpuQuota,
 		CpuQuota:        *flCpuQuota,