mirror of
https://github.com/containers/youki
synced 2024-11-23 09:21:57 +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:
commit
7d63d2a36e
@ -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,11 +110,18 @@ 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 {
|
||||
common::write_cgroup_file(
|
||||
root_path.join(CGROUP_IO_WEIGHT),
|
||||
format!("{}", io_weight),
|
||||
)?;
|
||||
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),
|
||||
Self::convert_cfq_io_weight_to_bfq(io_weight),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,17 +277,33 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_set_ioweight() {
|
||||
let (tmp, throttle) = setup("test_set_io_weight", CGROUP_IO_WEIGHT);
|
||||
let blkio = LinuxBlockIoBuilder::default()
|
||||
.weight(100u16)
|
||||
.build()
|
||||
.unwrap();
|
||||
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(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);
|
||||
Io::apply(&tmp, &blkio).expect("apply blkio");
|
||||
let content = fs::read_to_string(weight_file).expect("read blkio weight");
|
||||
assert_eq!(case.expected_weight, content);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user