Browse Source

Add support for blkio.weight_device

Signed-off-by: Ma Shimiao <mashimiao.fnst@cn.fujitsu.com>
Ma Shimiao 10 năm trước cách đây
mục cha
commit
0fbfa1449d

+ 1 - 0
contrib/completion/bash/docker

@@ -1355,6 +1355,7 @@ _docker_run() {
 		--add-host
 		--add-host
 		--attach -a
 		--attach -a
 		--blkio-weight
 		--blkio-weight
+		--blkio-weight-device
 		--cap-add
 		--cap-add
 		--cap-drop
 		--cap-drop
 		--cgroup-parent
 		--cgroup-parent

+ 1 - 0
contrib/completion/zsh/_docker

@@ -418,6 +418,7 @@ __docker_subcommand() {
         "($help -a --attach)"{-a=,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
         "($help -a --attach)"{-a=,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
         "($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: "
         "($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: "
         "($help)--blkio-weight=[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
         "($help)--blkio-weight=[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
+        "($help)--blkio-weight-device=-[Block IO (relative device weight)]:device:Block IO weight: "
         "($help)*--cap-add=[Add Linux capabilities]:capability: "
         "($help)*--cap-add=[Add Linux capabilities]:capability: "
         "($help)*--cap-drop=[Drop Linux capabilities]:capability: "
         "($help)*--cap-drop=[Drop Linux capabilities]:capability: "
         "($help)--cidfile=[Write the container ID to the file]:CID file:_files"
         "($help)--cidfile=[Write the container ID to the file]:CID file:_files"

+ 15 - 9
daemon/container_unix.go

@@ -269,6 +269,11 @@ func (daemon *Daemon) populateCommand(c *Container, env []string) error {
 		}
 		}
 	}
 	}
 
 
+	weightDevices, err := getBlkioWeightDevices(c.hostConfig)
+	if err != nil {
+		return err
+	}
+
 	for _, limit := range ulimits {
 	for _, limit := range ulimits {
 		rl, err := limit.GetRlimit()
 		rl, err := limit.GetRlimit()
 		if err != nil {
 		if err != nil {
@@ -284,15 +289,16 @@ func (daemon *Daemon) populateCommand(c *Container, env []string) error {
 			CPUShares:         c.hostConfig.CPUShares,
 			CPUShares:         c.hostConfig.CPUShares,
 			BlkioWeight:       c.hostConfig.BlkioWeight,
 			BlkioWeight:       c.hostConfig.BlkioWeight,
 		},
 		},
-		MemorySwap:       c.hostConfig.MemorySwap,
-		KernelMemory:     c.hostConfig.KernelMemory,
-		CpusetCpus:       c.hostConfig.CpusetCpus,
-		CpusetMems:       c.hostConfig.CpusetMems,
-		CPUPeriod:        c.hostConfig.CPUPeriod,
-		CPUQuota:         c.hostConfig.CPUQuota,
-		Rlimits:          rlimits,
-		OomKillDisable:   c.hostConfig.OomKillDisable,
-		MemorySwappiness: -1,
+		MemorySwap:        c.hostConfig.MemorySwap,
+		KernelMemory:      c.hostConfig.KernelMemory,
+		CpusetCpus:        c.hostConfig.CpusetCpus,
+		CpusetMems:        c.hostConfig.CpusetMems,
+		CPUPeriod:         c.hostConfig.CPUPeriod,
+		CPUQuota:          c.hostConfig.CPUQuota,
+		Rlimits:           rlimits,
+		BlkioWeightDevice: weightDevices,
+		OomKillDisable:    c.hostConfig.OomKillDisable,
+		MemorySwappiness:  -1,
 	}
 	}
 
 
 	if c.hostConfig.MemorySwappiness != nil {
 	if c.hostConfig.MemorySwappiness != nil {

+ 1 - 0
daemon/daemon.go

@@ -1202,6 +1202,7 @@ func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.
 
 
 	container.Lock()
 	container.Lock()
 	defer container.Unlock()
 	defer container.Unlock()
+
 	// Register any links from the host config before starting the container
 	// Register any links from the host config before starting the container
 	if err := daemon.registerLinks(container, hostConfig); err != nil {
 	if err := daemon.registerLinks(container, hostConfig); err != nil {
 		return err
 		return err

+ 22 - 0
daemon/daemon_unix.go

@@ -15,6 +15,7 @@ import (
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/dockerversion"
 	derr "github.com/docker/docker/errors"
 	derr "github.com/docker/docker/errors"
+	pblkiodev "github.com/docker/docker/pkg/blkiodev"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers"
@@ -30,6 +31,7 @@ import (
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/types"
 	"github.com/docker/libnetwork/types"
+	blkiodev "github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/label"
 	"github.com/opencontainers/runc/libcontainer/label"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 )
 )
@@ -41,6 +43,21 @@ const (
 	platformSupported = true
 	platformSupported = true
 )
 )
 
 
+func getBlkioWeightDevices(config *runconfig.HostConfig) ([]*blkiodev.WeightDevice, error) {
+	var stat syscall.Stat_t
+	var BlkioWeightDevices []*blkiodev.WeightDevice
+
+	for _, weightDevice := range config.BlkioWeightDevice {
+		if err := syscall.Stat(weightDevice.Path, &stat); err != nil {
+			return nil, err
+		}
+		WeightDevice := blkiodev.NewWeightDevice(int64(stat.Rdev/256), int64(stat.Rdev%256), weightDevice.Weight, 0)
+		BlkioWeightDevices = append(BlkioWeightDevices, WeightDevice)
+	}
+
+	return BlkioWeightDevices, nil
+}
+
 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
 	var (
 	var (
 		labelOpts []string
 		labelOpts []string
@@ -220,6 +237,11 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
 	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
 	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
 		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
 		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
 	}
 	}
+	if len(hostConfig.BlkioWeightDevice) > 0 && !sysInfo.BlkioWeightDevice {
+		warnings = append(warnings, "Your kernel does not support Block I/O weight_device.")
+		logrus.Warnf("Your kernel does not support Block I/O weight_device. Weight-device discarded.")
+		hostConfig.BlkioWeightDevice = []*pblkiodev.WeightDevice{}
+	}
 	if hostConfig.OomKillDisable && !sysInfo.OomKillDisable {
 	if hostConfig.OomKillDisable && !sysInfo.OomKillDisable {
 		hostConfig.OomKillDisable = false
 		hostConfig.OomKillDisable = false
 		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
 		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")

+ 5 - 0
daemon/daemon_windows.go

@@ -12,6 +12,7 @@ import (
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork"
+	blkiodev "github.com/opencontainers/runc/libcontainer/configs"
 )
 )
 
 
 const (
 const (
@@ -21,6 +22,10 @@ const (
 	windowsMaxCPUShares  = 9
 	windowsMaxCPUShares  = 9
 )
 )
 
 
+func getBlkioWeightDevices(config *runconfig.HostConfig) ([]*blkiodev.WeightDevice, error) {
+	return nil, nil
+}
+
 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
 func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
 	return nil
 	return nil
 }
 }

+ 12 - 9
daemon/execdriver/driver_unix.go

@@ -18,6 +18,7 @@ import (
 	"github.com/opencontainers/runc/libcontainer"
 	"github.com/opencontainers/runc/libcontainer"
 	"github.com/opencontainers/runc/libcontainer/cgroups/fs"
 	"github.com/opencontainers/runc/libcontainer/cgroups/fs"
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/configs"
+	blkiodev "github.com/opencontainers/runc/libcontainer/configs"
 )
 )
 
 
 // Mount contains information for a mount operation.
 // Mount contains information for a mount operation.
@@ -36,15 +37,16 @@ type Resources struct {
 
 
 	// Fields below here are platform specific
 	// Fields below here are platform specific
 
 
-	MemorySwap       int64            `json:"memory_swap"`
-	KernelMemory     int64            `json:"kernel_memory"`
-	CPUQuota         int64            `json:"cpu_quota"`
-	CpusetCpus       string           `json:"cpuset_cpus"`
-	CpusetMems       string           `json:"cpuset_mems"`
-	CPUPeriod        int64            `json:"cpu_period"`
-	Rlimits          []*ulimit.Rlimit `json:"rlimits"`
-	OomKillDisable   bool             `json:"oom_kill_disable"`
-	MemorySwappiness int64            `json:"memory_swappiness"`
+	BlkioWeightDevice []*blkiodev.WeightDevice `json:"blkio_weight_device"`
+	MemorySwap        int64                    `json:"memory_swap"`
+	KernelMemory      int64                    `json:"kernel_memory"`
+	CPUQuota          int64                    `json:"cpu_quota"`
+	CpusetCpus        string                   `json:"cpuset_cpus"`
+	CpusetMems        string                   `json:"cpuset_mems"`
+	CPUPeriod         int64                    `json:"cpu_period"`
+	Rlimits           []*ulimit.Rlimit         `json:"rlimits"`
+	OomKillDisable    bool                     `json:"oom_kill_disable"`
+	MemorySwappiness  int64                    `json:"memory_swappiness"`
 }
 }
 
 
 // Ipc settings of the container
 // Ipc settings of the container
@@ -153,6 +155,7 @@ func SetupCgroups(container *configs.Config, c *Command) error {
 		container.Cgroups.CpuPeriod = c.Resources.CPUPeriod
 		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.BlkioWeightDevice = c.Resources.BlkioWeightDevice
 		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
 		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
 		container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness
 		container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness
 	}
 	}

+ 3 - 0
docs/reference/api/docker_remote_api_v1.22.md

@@ -187,6 +187,7 @@ Create a container
              "CpusetCpus": "0,1",
              "CpusetCpus": "0,1",
              "CpusetMems": "0,1",
              "CpusetMems": "0,1",
              "BlkioWeight": 300,
              "BlkioWeight": 300,
+             "BlkioWeightDevice": [{}],
              "MemorySwappiness": 60,
              "MemorySwappiness": 60,
              "OomKillDisable": false,
              "OomKillDisable": false,
              "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
              "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
@@ -241,6 +242,7 @@ Json Parameters:
 -   **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.
 -   **BlkioWeight** - Block IO weight (relative weight) accepts a weight value between 10 and 1000.
 -   **BlkioWeight** - Block IO weight (relative weight) accepts a weight value between 10 and 1000.
+ -   **BlkioWeightDevice** - Block IO weight (relative device weight) in the form of:        `"BlkioWeightDevice": [{"Path": "device_path", "Weight": weight}]`
 -   **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
 -   **MemorySwappiness** - Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.
 -   **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not.
 -   **OomKillDisable** - Boolean value, whether to disable OOM Killer for the container or not.
 -   **AttachStdin** - Boolean value, attaches to `stdin`.
 -   **AttachStdin** - Boolean value, attaches to `stdin`.
@@ -391,6 +393,7 @@ Return low-level information on the container `id`
 		"HostConfig": {
 		"HostConfig": {
 			"Binds": null,
 			"Binds": null,
 			"BlkioWeight": 0,
 			"BlkioWeight": 0,
+			"BlkioWeightDevice": [{}],
 			"CapAdd": null,
 			"CapAdd": null,
 			"CapDrop": null,
 			"CapDrop": null,
 			"ContainerIDFile": "",
 			"ContainerIDFile": "",

+ 1 - 0
docs/reference/commandline/create.md

@@ -19,6 +19,7 @@ Creates a new container.
       -a, --attach=[]               Attach to STDIN, STDOUT or STDERR
       -a, --attach=[]               Attach to STDIN, STDOUT or STDERR
       --add-host=[]                 Add a custom host-to-IP mapping (host:ip)
       --add-host=[]                 Add a custom host-to-IP mapping (host:ip)
       --blkio-weight=0              Block IO weight (relative weight)
       --blkio-weight=0              Block IO weight (relative weight)
+      --blkio-weight-device=""      Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)
       --cpu-shares=0                CPU shares (relative weight)
       --cpu-shares=0                CPU shares (relative weight)
       --cap-add=[]                  Add Linux capabilities
       --cap-add=[]                  Add Linux capabilities
       --cap-drop=[]                 Drop Linux capabilities
       --cap-drop=[]                 Drop Linux capabilities

+ 1 - 0
docs/reference/commandline/run.md

@@ -17,6 +17,7 @@ parent = "smn_cli"
       -a, --attach=[]               Attach to STDIN, STDOUT or STDERR
       -a, --attach=[]               Attach to STDIN, STDOUT or STDERR
       --add-host=[]                 Add a custom host-to-IP mapping (host:ip)
       --add-host=[]                 Add a custom host-to-IP mapping (host:ip)
       --blkio-weight=0              Block IO weight (relative weight)
       --blkio-weight=0              Block IO weight (relative weight)
+      --blkio-weight-device=""      Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)
       --cpu-shares=0                CPU shares (relative weight)
       --cpu-shares=0                CPU shares (relative weight)
       --cap-add=[]                  Add Linux capabilities
       --cap-add=[]                  Add Linux capabilities
       --cap-drop=[]                 Drop Linux capabilities
       --cap-drop=[]                 Drop Linux capabilities

+ 22 - 2
docs/reference/run.md

@@ -623,6 +623,7 @@ container:
 | `--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                                         |
 | `--blkio-weight=0`         | Block IO weight (relative weight) accepts a weight value between 10 and 1000.               |
 | `--blkio-weight=0`         | Block IO weight (relative weight) accepts a weight value between 10 and 1000.               |
+| `--blkio-weight-device=""` | Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)                                                |
 | `--oom-kill-disable=false` | Whether to disable OOM Killer for the container or not.                                     |
 | `--oom-kill-disable=false` | Whether to disable OOM Killer for the container or not.                                     |
 | `--memory-swappiness=""  ` | Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.        |
 | `--memory-swappiness=""  ` | Tune a container's memory swappiness behavior. Accepts an integer between 0 and 100.        |
 
 
@@ -937,6 +938,9 @@ By default, all containers get the same proportion of block IO bandwidth
 container's blkio weight relative to the weighting of all other running
 container's blkio weight relative to the weighting of all other running
 containers using the `--blkio-weight` flag.
 containers using the `--blkio-weight` flag.
 
 
+> **Note:** The blkio weight setting is only available for direct IO. Buffered IO
+> is not currently supported.
+
 The `--blkio-weight` flag can set the weighting to a value between 10 to 1000.
 The `--blkio-weight` flag can set the weighting to a value between 10 to 1000.
 For example, the commands below create two containers with different blkio
 For example, the commands below create two containers with different blkio
 weight:
 weight:
@@ -951,8 +955,24 @@ If you do block IO in the two containers at the same time, by, for example:
 You'll find that the proportion of time is the same as the proportion of blkio
 You'll find that the proportion of time is the same as the proportion of blkio
 weights of the two containers.
 weights of the two containers.
 
 
-> **Note:** The blkio weight setting is only available for direct IO. Buffered IO
-> is not currently supported.
+The `--blkio-weight-device="DEVICE_NAME:WEIGHT"` flag sets a specific device weight.
+The `DEVICE_NAME:WEIGHT` is a string containing a colon-separated device name and weight.
+For example, to set `/dev/sda` device weight to `200`:
+
+$ docker run -it \
+    --blkio-weight-device "/dev/sda:200" \
+    ubuntu
+
+If you specify both the `--blkio-weight` and `--blkio-weight-device`, Docker
+uses the `--blkio-weight` as the default weight and uses `--blkio-weight-device` 
+to override this default with a new value on a specific device. 
+The following example uses a default weight of `300` and overrides this default 
+on `/dev/sda` setting that weight to `200`:
+
+$ docker run -it \
+    --blkio-weight 300 \
+    --blkio-weight-device "/dev/sda:200" \
+    ubuntu
 
 
 ## Additional groups
 ## Additional groups
     --group-add: Add Linux capabilities
     --group-add: Add Linux capabilities

+ 6 - 0
integration-cli/docker_cli_run_unix_test.go

@@ -217,6 +217,12 @@ func (s *DockerSuite) TestRunWithBlkioInvalidWeight(c *check.C) {
 	c.Assert(out, checker.Contains, expected)
 	c.Assert(out, checker.Contains, expected)
 }
 }
 
 
+func (s *DockerSuite) TestRunWithBlkioInvalidWeightDevice(c *check.C) {
+	testRequires(c, blkioWeight)
+	out, _, err := dockerCmdWithError("run", "--blkio-weight-device", "/dev/sda:5", "busybox", "true")
+	c.Assert(err, check.NotNil, check.Commentf(out))
+}
+
 func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
 func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
 	testRequires(c, oomControl)
 	testRequires(c, oomControl)
 	errChan := make(chan error)
 	errChan := make(chan error)

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

@@ -9,6 +9,7 @@ docker-create - Create a new container
 [**-a**|**--attach**[=*[]*]]
 [**-a**|**--attach**[=*[]*]]
 [**--add-host**[=*[]*]]
 [**--add-host**[=*[]*]]
 [**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
 [**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
+[**--blkio-weight-device**[=*[]*]]
 [**--cpu-shares**[=*0*]]
 [**--cpu-shares**[=*0*]]
 [**--cap-add**[=*[]*]]
 [**--cap-add**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cap-drop**[=*[]*]]
@@ -82,6 +83,9 @@ The initial status of the container created with **docker create** is 'created'.
 **--blkio-weight**=*0*
 **--blkio-weight**=*0*
    Block IO weight (relative weight) accepts a weight value between 10 and 1000.
    Block IO weight (relative weight) accepts a weight value between 10 and 1000.
 
 
+**--blkio-weight-device**=[]
+   Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`).
+
 **--cpu-shares**=*0*
 **--cpu-shares**=*0*
    CPU shares (relative weight)
    CPU shares (relative weight)
 
 

+ 11 - 0
man/docker-run.1.md

@@ -9,6 +9,7 @@ docker-run - Run a command in a new container
 [**-a**|**--attach**[=*[]*]]
 [**-a**|**--attach**[=*[]*]]
 [**--add-host**[=*[]*]]
 [**--add-host**[=*[]*]]
 [**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
 [**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
+[**--blkio-weight-device**[=*[]*]]
 [**--cpu-shares**[=*0*]]
 [**--cpu-shares**[=*0*]]
 [**--cap-add**[=*[]*]]
 [**--cap-add**[=*[]*]]
 [**--cap-drop**[=*[]*]]
 [**--cap-drop**[=*[]*]]
@@ -99,6 +100,9 @@ option can be set multiple times.
 **--blkio-weight**=*0*
 **--blkio-weight**=*0*
    Block IO weight (relative weight) accepts a weight value between 10 and 1000.
    Block IO weight (relative weight) accepts a weight value between 10 and 1000.
 
 
+**--blkio-weight-device**=[]
+   Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`).
+
 **--cpu-shares**=*0*
 **--cpu-shares**=*0*
    CPU shares (relative weight)
    CPU shares (relative weight)
 
 
@@ -755,6 +759,13 @@ Note:
 
 
 You would have to write policy defining a `svirt_apache_t` type.
 You would have to write policy defining a `svirt_apache_t` type.
 
 
+## Setting device weight
+
+If you want to set `/dev/sda` device weight to `200`, you can specify the device
+weight by `--blkio-weight-device` flag. Use the following command:
+
+   # docker run -it --blkio-weight-device "/dev/sda:200" ubuntu
+
 # HISTORY
 # HISTORY
 April 2014, Originally compiled by William Henry (whenry at redhat dot com)
 April 2014, Originally compiled by William Henry (whenry at redhat dot com)
 based on docker.com source material and internal work.
 based on docker.com source material and internal work.

+ 28 - 0
opts/opts.go

@@ -6,8 +6,10 @@ import (
 	"os"
 	"os"
 	"path"
 	"path"
 	"regexp"
 	"regexp"
+	"strconv"
 	"strings"
 	"strings"
 
 
+	"github.com/docker/docker/pkg/blkiodev"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers"
 )
 )
 
 
@@ -168,6 +170,9 @@ func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts {
 // ValidatorFctType defines a validator function that returns a validated string and/or an error.
 // ValidatorFctType defines a validator function that returns a validated string and/or an error.
 type ValidatorFctType func(val string) (string, error)
 type ValidatorFctType func(val string) (string, error)
 
 
+// ValidatorWeightFctType defines a validator function that returns a validated struct and/or an error.
+type ValidatorWeightFctType func(val string) (*blkiodev.WeightDevice, error)
+
 // ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
 // ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
 type ValidatorFctListType func(val string) ([]string, error)
 type ValidatorFctListType func(val string) ([]string, error)
 
 
@@ -182,6 +187,29 @@ func ValidateAttach(val string) (string, error) {
 	return val, fmt.Errorf("valid streams are STDIN, STDOUT and STDERR")
 	return val, fmt.Errorf("valid streams are STDIN, STDOUT and STDERR")
 }
 }
 
 
+// ValidateWeightDevice validates that the specified string has a valid device-weight format.
+func ValidateWeightDevice(val string) (*blkiodev.WeightDevice, error) {
+	split := strings.SplitN(val, ":", 2)
+	if len(split) != 2 {
+		return nil, fmt.Errorf("bad format: %s", val)
+	}
+	if !strings.HasPrefix(split[0], "/dev/") {
+		return nil, fmt.Errorf("bad format for device path: %s", val)
+	}
+	weight, err := strconv.ParseUint(split[1], 10, 0)
+	if err != nil {
+		return nil, fmt.Errorf("invalid weight for device: %s", val)
+	}
+	if weight > 0 && (weight < 10 || weight > 1000) {
+		return nil, fmt.Errorf("invalid weight for device: %s", val)
+	}
+
+	return &blkiodev.WeightDevice{
+		Path:   split[0],
+		Weight: uint16(weight),
+	}, nil
+}
+
 // ValidateLink validates that the specified string has a valid link format (containerName:alias).
 // ValidateLink validates that the specified string has a valid link format (containerName:alias).
 func ValidateLink(val string) (string, error) {
 func ValidateLink(val string) (string, error) {
 	if _, _, err := parsers.ParseLink(val); err != nil {
 	if _, _, err := parsers.ParseLink(val); err != nil {

+ 56 - 0
opts/weightdevice.go

@@ -0,0 +1,56 @@
+package opts
+
+import (
+	"fmt"
+
+	"github.com/docker/docker/pkg/blkiodev"
+)
+
+// WeightdeviceOpt defines a map of WeightDevices
+type WeightdeviceOpt struct {
+	values    []*blkiodev.WeightDevice
+	validator ValidatorWeightFctType
+}
+
+// NewWeightdeviceOpt creates a new WeightdeviceOpt
+func NewWeightdeviceOpt(validator ValidatorWeightFctType) WeightdeviceOpt {
+	values := []*blkiodev.WeightDevice{}
+	return WeightdeviceOpt{
+		values:    values,
+		validator: validator,
+	}
+}
+
+// Set validates a WeightDevice and sets its name as a key in WeightdeviceOpt
+func (opt *WeightdeviceOpt) Set(val string) error {
+	var value *blkiodev.WeightDevice
+	if opt.validator != nil {
+		v, err := opt.validator(val)
+		if err != nil {
+			return err
+		}
+		value = v
+	}
+	(opt.values) = append((opt.values), value)
+	return nil
+}
+
+// String returns Ulimit values as a string.
+func (opt *WeightdeviceOpt) String() string {
+	var out []string
+	for _, v := range opt.values {
+		out = append(out, v.String())
+	}
+
+	return fmt.Sprintf("%v", out)
+}
+
+// GetList returns a slice of pointers to WeightDevices.
+func (opt *WeightdeviceOpt) GetList() []*blkiodev.WeightDevice {
+	var weightdevice []*blkiodev.WeightDevice
+	for _, v := range opt.values {
+		weightdevice = append(weightdevice, v)
+	}
+
+	return weightdevice
+}

+ 15 - 0
pkg/blkiodev/blkiodev.go

@@ -0,0 +1,15 @@
+package blkiodev
+
+import (
+	"fmt"
+)
+
+// WeightDevice is a structure that hold device:weight pair
+type WeightDevice struct {
+	Path   string
+	Weight uint16
+}
+
+func (w *WeightDevice) String() string {
+	return fmt.Sprintf("%s:%d", w.Path, w.Weight)
+}

+ 3 - 0
pkg/sysinfo/sysinfo.go

@@ -60,6 +60,9 @@ type cgroupCPUInfo struct {
 type cgroupBlkioInfo struct {
 type cgroupBlkioInfo struct {
 	// Whether Block IO weight is supported or not
 	// Whether Block IO weight is supported or not
 	BlkioWeight bool
 	BlkioWeight bool
+
+	// Whether Block IO weight_device is supported or not
+	BlkioWeightDevice bool
 }
 }
 
 
 type cgroupCpusetInfo struct {
 type cgroupCpusetInfo struct {

+ 11 - 3
pkg/sysinfo/sysinfo_linux.go

@@ -117,11 +117,19 @@ func checkCgroupBlkioInfo(quiet bool) cgroupBlkioInfo {
 		return cgroupBlkioInfo{}
 		return cgroupBlkioInfo{}
 	}
 	}
 
 
-	w := cgroupEnabled(mountPoint, "blkio.weight")
-	if !quiet && !w {
+	weight := cgroupEnabled(mountPoint, "blkio.weight")
+	if !quiet && !weight {
 		logrus.Warn("Your kernel does not support cgroup blkio weight")
 		logrus.Warn("Your kernel does not support cgroup blkio weight")
 	}
 	}
-	return cgroupBlkioInfo{BlkioWeight: w}
+
+	weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device")
+	if !quiet && !weightDevice {
+		logrus.Warn("Your kernel does not support cgroup blkio weight_device")
+	}
+	return cgroupBlkioInfo{
+		BlkioWeight:       weight,
+		BlkioWeightDevice: weightDevice,
+	}
 }
 }
 
 
 // checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.
 // checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.

+ 3 - 1
runconfig/hostconfig.go

@@ -5,6 +5,7 @@ import (
 	"io"
 	"io"
 	"strings"
 	"strings"
 
 
+	"github.com/docker/docker/pkg/blkiodev"
 	"github.com/docker/docker/pkg/nat"
 	"github.com/docker/docker/pkg/nat"
 	"github.com/docker/docker/pkg/stringutils"
 	"github.com/docker/docker/pkg/stringutils"
 	"github.com/docker/docker/pkg/ulimit"
 	"github.com/docker/docker/pkg/ulimit"
@@ -180,7 +181,8 @@ type HostConfig struct {
 	VolumesFrom     []string      // List of volumes to take from other container
 	VolumesFrom     []string      // List of volumes to take from other container
 
 
 	// Applicable to UNIX platforms
 	// Applicable to UNIX platforms
-	BlkioWeight       uint16                // Block IO weight (relative weight vs. other containers)
+	BlkioWeight       uint16 // Block IO weight (relative weight vs. other containers)
+	BlkioWeightDevice []*blkiodev.WeightDevice
 	CapAdd            *stringutils.StrSlice // List of kernel capabilities to add to the container
 	CapAdd            *stringutils.StrSlice // List of kernel capabilities to add to the container
 	CapDrop           *stringutils.StrSlice // List of kernel capabilities to remove from the container
 	CapDrop           *stringutils.StrSlice // List of kernel capabilities to remove from the container
 	CgroupParent      string                // Parent cgroup.
 	CgroupParent      string                // Parent cgroup.

+ 9 - 6
runconfig/parse.go

@@ -48,12 +48,13 @@ var (
 func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
 func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
 	var (
 	var (
 		// FIXME: use utils.ListOpts for attach and volumes?
 		// FIXME: use utils.ListOpts for attach and volumes?
-		flAttach  = opts.NewListOpts(opts.ValidateAttach)
-		flVolumes = opts.NewListOpts(nil)
-		flLinks   = opts.NewListOpts(opts.ValidateLink)
-		flEnv     = opts.NewListOpts(opts.ValidateEnv)
-		flLabels  = opts.NewListOpts(opts.ValidateEnv)
-		flDevices = opts.NewListOpts(opts.ValidateDevice)
+		flAttach            = opts.NewListOpts(opts.ValidateAttach)
+		flVolumes           = opts.NewListOpts(nil)
+		flBlkioWeightDevice = opts.NewWeightdeviceOpt(opts.ValidateWeightDevice)
+		flLinks             = opts.NewListOpts(opts.ValidateLink)
+		flEnv               = opts.NewListOpts(opts.ValidateEnv)
+		flLabels            = opts.NewListOpts(opts.ValidateEnv)
+		flDevices           = opts.NewListOpts(opts.ValidateDevice)
 
 
 		flUlimits = opts.NewUlimitOpt(nil)
 		flUlimits = opts.NewUlimitOpt(nil)
 
 
@@ -108,6 +109,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 	)
 	)
 
 
 	cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
 	cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR")
+	cmd.Var(&flBlkioWeightDevice, []string{"-blkio-weight-device"}, "Block IO weight (relative device weight)")
 	cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume")
 	cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume")
 	cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container")
 	cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container")
 	cmd.Var(&flDevices, []string{"-device"}, "Add a host device to the container")
 	cmd.Var(&flDevices, []string{"-device"}, "Add a host device to the container")
@@ -344,6 +346,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		CpusetMems:        *flCpusetMems,
 		CpusetMems:        *flCpusetMems,
 		CPUQuota:          *flCPUQuota,
 		CPUQuota:          *flCPUQuota,
 		BlkioWeight:       *flBlkioWeight,
 		BlkioWeight:       *flBlkioWeight,
+		BlkioWeightDevice: flBlkioWeightDevice.GetList(),
 		OomKillDisable:    *flOomKillDisable,
 		OomKillDisable:    *flOomKillDisable,
 		MemorySwappiness:  flSwappiness,
 		MemorySwappiness:  flSwappiness,
 		Privileged:        *flPrivileged,
 		Privileged:        *flPrivileged,