1
0
mirror of https://github.com/containers/youki synced 2024-11-23 17:32:15 +01:00

Merge pull request #543 from knight42/fix/set-blkio-weight

fix(libcgroup): make cgroup manager be able to set blkio weight
This commit is contained in:
utam0k 2021-12-17 22:48:48 +09:00 committed by GitHub
commit 7d63d2a36e
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 15 deletions

@ -33,8 +33,12 @@ const BLKIO_THROTTLE_IO_SERVICE_BYTES: &str = "blkio.throttle.io_service_bytes";
// Proportional weight division policy
// ---------------------------------------
// Specifies the relative proportion of block I/O access available to the cgroup
// Format: weight (weight can range from 100 to 1000)
// Format: weight (weight can range from 10 to 1000)
const BLKIO_WEIGHT: &str = "blkio.weight";
// Similar to BLKIO_WEIGHT, but is only available in kernels starting with version 5.0
// with blk-mq and when using BFQ I/O scheduler
// Format: weight (weight can range from 1 to 10000)
const BLKIO_BFQ_WEIGHT: &str = "blkio.bfq.weight";
// Specifies the relative proportion of block I/O access for specific devices available
// to the cgroup. This overrides the the blkio.weight value for the specified device
// Format: Major:Minor weight (weight can range from 100 to 1000)
@ -103,6 +107,19 @@ impl StatsProvider for Blkio {
impl Blkio {
fn apply(root_path: &Path, blkio: &LinuxBlockIo) -> Result<()> {
if let Some(blkio_weight) = blkio.weight() {
// be aligned with what runc does
// See also: https://github.com/opencontainers/runc/blob/81044ad7c902f3fc153cb8ffadaf4da62855193f/libcontainer/cgroups/fs/blkio.go#L28-L33
if blkio_weight != 0 {
let cgroup_file = root_path.join(BLKIO_WEIGHT);
if cgroup_file.exists() {
common::write_cgroup_file(&cgroup_file, blkio_weight)?;
} else {
common::write_cgroup_file(&root_path.join(BLKIO_BFQ_WEIGHT), blkio_weight)?;
}
}
}
if let Some(throttle_read_bps_device) = blkio.throttle_read_bps_device().as_ref() {
for trbd in throttle_read_bps_device {
common::write_cgroup_file_str(
@ -226,6 +243,21 @@ mod tests {
use anyhow::Result;
use oci_spec::runtime::{LinuxBlockIoBuilder, LinuxThrottleDeviceBuilder};
#[test]
fn test_set_blkio_weight() {
for cgroup_file in &[BLKIO_WEIGHT, BLKIO_BFQ_WEIGHT] {
let (tmp, weight_file) = setup("test_set_blkio_weight", cgroup_file);
let blkio = LinuxBlockIoBuilder::default()
.weight(200_u16)
.build()
.unwrap();
Blkio::apply(&tmp, &blkio).expect("apply blkio");
let content = fs::read_to_string(weight_file).expect("read blkio weight");
assert_eq!("200", content);
}
}
#[test]
fn test_set_blkio_read_bps() {
let (tmp, throttle) = setup("test_set_blkio_read_bps", BLKIO_THROTTLE_READ_BPS);

@ -79,6 +79,17 @@ impl StatsProvider for Io {
}
impl Io {
// Since the OCI spec is designed for cgroup v1, in some cases
// there is need to convert from the cgroup v1 configuration to cgroup v2
// the formula for BlkIOWeight to IOWeight is y = (1 + (x - 10) * 9999 / 990)
// convert linearly from [10-1000] to [1-10000]
fn convert_cfq_io_weight_to_bfq(v: u16) -> u16 {
if v == 0 {
return 0;
}
1 + (v - 10) * 9999 / 990
}
fn io_max_path(path: &Path) -> PathBuf {
path.join("io.max")
}
@ -99,13 +110,20 @@ impl Io {
}
}
if let Some(io_weight) = blkio.weight() {
// be aligned with what runc does
// See also: https://github.com/opencontainers/runc/blob/81044ad7c902f3fc153cb8ffadaf4da62855193f/libcontainer/cgroups/fs2/io.go#L57-L69
if io_weight > 0 {
let cgroup_file = root_path.join(CGROUP_BFQ_IO_WEIGHT);
if cgroup_file.exists() {
common::write_cgroup_file(cgroup_file, io_weight)?;
} else {
common::write_cgroup_file(
root_path.join(CGROUP_IO_WEIGHT),
format!("{}", io_weight),
Self::convert_cfq_io_weight_to_bfq(io_weight),
)?;
}
}
}
if let Some(throttle_read_bps_device) = blkio.throttle_read_bps_device() {
for trbd in throttle_read_bps_device {
@ -259,17 +277,33 @@ mod test {
#[test]
fn test_set_ioweight() {
let (tmp, throttle) = setup("test_set_io_weight", CGROUP_IO_WEIGHT);
struct TestCase {
cgroup_file: &'static str,
weight: u16,
expected_weight: String,
}
for case in &[
TestCase {
cgroup_file: CGROUP_BFQ_IO_WEIGHT,
weight: 100,
expected_weight: String::from("100"),
},
TestCase {
cgroup_file: CGROUP_IO_WEIGHT,
weight: 10,
expected_weight: String::from("1"),
},
] {
let (tmp, weight_file) = setup("test_set_io_weight", case.cgroup_file);
let blkio = LinuxBlockIoBuilder::default()
.weight(100u16)
.weight(case.weight)
.build()
.unwrap();
Io::apply(&tmp, &blkio).expect("apply blkio");
let content =
fs::read_to_string(throttle).unwrap_or_else(|_| panic!("read bfq_io_weight content"));
assert_eq!("100", content);
let content = fs::read_to_string(weight_file).expect("read blkio weight");
assert_eq!(case.expected_weight, content);
}
}
#[test]