diff --git a/src/runtime-rs/Cargo.lock b/src/runtime-rs/Cargo.lock index c7050fc563..763901c3a8 100644 --- a/src/runtime-rs/Cargo.lock +++ b/src/runtime-rs/Cargo.lock @@ -135,6 +135,18 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener 5.4.0", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -142,31 +154,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] -name = "async-executor" -version = "1.5.1" +name = "async-channel" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" dependencies = [ - "async-lock", "async-task", "concurrent-queue", - "fastrand 1.9.0", + "fastrand", "futures-lite", + "pin-project-lite", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel", + "async-channel 2.5.0", "async-executor", "async-io", "async-lock", @@ -177,40 +201,87 @@ dependencies = [ [[package]] name = "async-io" -version = "1.13.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" dependencies = [ "async-lock", - "autocfg", "cfg-if 1.0.0", "concurrent-queue", + "futures-io", "futures-lite", - "log", "parking", "polling", - "rustix 0.37.28", + "rustix 1.0.7", "slab", - "socket2 0.4.9", - "waker-fn", + "windows-sys 0.60.2", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener", + "event-listener 5.4.0", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00" +dependencies = [ + "async-channel 2.5.0", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if 1.0.0", + "event-listener 5.4.0", + "futures-lite", + "rustix 1.0.7", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "async-signal" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if 1.0.0", + "futures-core", + "futures-io", + "rustix 1.0.7", + "signal-hook-registry", + "slab", + "windows-sys 0.60.2", ] [[package]] name = "async-std" -version = "1.12.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-global-executor", "async-io", "async-lock", @@ -232,9 +303,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.4.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" @@ -292,6 +363,12 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -360,17 +437,15 @@ dependencies = [ [[package]] name = "blocking" -version = "1.3.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.5.0", "async-task", - "atomic-waker", - "fastrand 1.9.0", + "futures-io", "futures-lite", - "log", + "piper", ] [[package]] @@ -501,14 +576,17 @@ dependencies = [ [[package]] name = "cgroups-rs" -version = "0.3.5" -source = "git+https://github.com/kata-containers/cgroups-rs?rev=v0.3.5#de9625ff57d156967b5b2a637c2c41bb2366e39b" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879433e90a9bf3c38e4e854ad36bd14507751dbd3a0df15429283ff5c10ff0e4" dependencies = [ + "bit-vec", "libc", "log", "nix 0.25.1", - "regex", + "oci-spec 0.8.1", "thiserror 1.0.69", + "zbus", ] [[package]] @@ -584,9 +662,9 @@ checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -1209,6 +1287,33 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "env_home" version = "0.1.0" @@ -1238,7 +1343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1247,6 +1352,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener 5.4.0", + "pin-project-lite", +] + [[package]] name = "event-manager" version = "0.2.1" @@ -1268,15 +1394,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.3.0" @@ -1413,9 +1530,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" @@ -1436,17 +1553,15 @@ checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-lite" -version = "1.13.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ - "fastrand 1.9.0", + "fastrand", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", - "waker-fn", ] [[package]] @@ -1549,9 +1664,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -1741,7 +1856,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower-service", "tracing", @@ -2003,15 +2118,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "integer-encoding" version = "3.0.4" @@ -2064,7 +2170,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2578,6 +2684,19 @@ dependencies = [ "memoffset 0.9.0", ] +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.9.0", + "cfg-if 1.0.0", + "cfg_aliases", + "libc", + "memoffset 0.9.0", +] + [[package]] name = "nom" version = "7.1.3" @@ -2949,6 +3068,16 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "overload" version = "0.1.1" @@ -2967,9 +3096,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -3120,6 +3249,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -3128,18 +3268,16 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "polling" -version = "2.8.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +checksum = "8ee9b2fa7a4517d2c91ff5bc6c297a427a96749d15f98fcdbb22c05571a4d4b7" dependencies = [ - "autocfg", - "bitflags 1.3.2", "cfg-if 1.0.0", "concurrent-queue", - "libc", - "log", + "hermit-abi 0.5.2", "pin-project-lite", - "windows-sys 0.48.0", + "rustix 1.0.7", + "windows-sys 0.60.2", ] [[package]] @@ -3170,7 +3308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52" dependencies = [ "libc", - "nix 0.29.0", + "nix 0.30.1", ] [[package]] @@ -3489,9 +3627,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -3699,7 +3837,7 @@ dependencies = [ "async-trait", "bitflags 2.9.0", "byte-unit", - "cgroups-rs 0.3.5", + "cgroups-rs 0.4.0", "flate2", "futures 0.3.28", "hypervisor", @@ -3891,7 +4029,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3904,7 +4042,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4069,6 +4207,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4368,16 +4517,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.7" @@ -4394,6 +4533,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.11.1" @@ -4551,11 +4696,11 @@ version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "fastrand 2.3.0", + "fastrand", "getrandom 0.3.2", "once_cell", "rustix 1.0.7", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4743,7 +4888,7 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "slab", - "socket2 0.5.7", + "socket2", "tokio-macros", "windows-sys 0.52.0", ] @@ -4980,6 +5125,17 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset 0.9.0", + "tempfile", + "winapi", +] + [[package]] name = "unicode-ident" version = "1.0.11" @@ -5211,12 +5367,6 @@ dependencies = [ "nix 0.24.3", ] -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - [[package]] name = "walkdir" version = "2.5.0" @@ -5384,7 +5534,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -5479,6 +5629,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + [[package]] name = "windows-targets" version = "0.48.1" @@ -5503,13 +5671,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" @@ -5522,6 +5706,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -5534,6 +5724,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -5546,12 +5742,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -5564,6 +5772,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" @@ -5576,6 +5790,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" @@ -5588,6 +5808,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -5600,6 +5826,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.10" @@ -5682,6 +5914,66 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "5.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb4f9a464286d42851d18a605f7193b8febaf5b0919d71c6399b7b26e5b0aad" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener 5.4.0", + "futures-core", + "futures-lite", + "hex", + "nix 0.30.1", + "ordered-stream", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "windows-sys 0.59.0", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef9859f68ee0c4ee2e8cde84737c78e3f4c54f946f2a38645d0d4c7a95327659" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.96", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +dependencies = [ + "serde", + "static_assertions", + "winnow", + "zvariant", +] + [[package]] name = "zerofrom" version = "0.1.6" @@ -5765,3 +6057,44 @@ dependencies = [ "libc", "pkg-config", ] + +[[package]] +name = "zvariant" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91b3680bb339216abd84714172b5138a4edac677e641ef17e1d8cb1b3ca6e6f" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8c68501be459a8dbfffbe5d792acdd23b4959940fc87785fb013b32edbc208" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.96", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "static_assertions", + "syn 2.0.96", + "winnow", +] diff --git a/src/runtime-rs/crates/resource/Cargo.toml b/src/runtime-rs/crates/resource/Cargo.toml index 54be2253fe..c3c556080b 100644 --- a/src/runtime-rs/crates/resource/Cargo.toml +++ b/src/runtime-rs/crates/resource/Cargo.toml @@ -17,7 +17,7 @@ anyhow = { workspace = true } async-trait = { workspace = true } bitflags = "2.9.0" byte-unit = "5.1.6" -cgroups-rs = { git = "https://github.com/kata-containers/cgroups-rs", rev = "v0.3.5" } +cgroups-rs = { version = "0.4.0", features = ["oci"] } futures = "0.3.11" lazy_static = { workspace = true } libc = { workspace = true } diff --git a/src/runtime-rs/crates/resource/src/cgroups/mod.rs b/src/runtime-rs/crates/resource/src/cgroups/mod.rs index 7dfe037fdf..bdfc141e31 100644 --- a/src/runtime-rs/crates/resource/src/cgroups/mod.rs +++ b/src/runtime-rs/crates/resource/src/cgroups/mod.rs @@ -5,30 +5,19 @@ // pub mod cgroup_persist; +mod resource; +pub use resource::CgroupsResource; +mod resource_inner; mod utils; -use anyhow::{anyhow, Context, Result}; -use async_trait::async_trait; -use cgroup_persist::CgroupState; -use cgroups_rs::{cgroup_builder::CgroupBuilder, Cgroup, CgroupPid, CpuResources, Resources}; -use hypervisor::Hypervisor; +use anyhow::{anyhow, Result}; +use cgroups_rs::manager::is_systemd_cgroup; +use hypervisor::HYPERVISOR_DRAGONBALL; use kata_sys_util::spec::load_oci_spec; use kata_types::config::TomlConfig; -use oci::LinuxResources; -use oci_spec::runtime as oci; -use persist::sandbox_persist::Persist; -use std::{ - collections::{HashMap, HashSet}, - error::Error, - io, - iter::FromIterator, - sync::Arc, -}; -use tokio::sync::RwLock; -use crate::ResourceUpdateOp; +use crate::cgroups::cgroup_persist::CgroupState; -const OS_ERROR_NO_SUCH_PROCESS: i32 = 3; const SANDBOXED_CGROUP_PATH: &str = "kata_sandboxed_pod"; pub struct CgroupArgs { @@ -44,7 +33,6 @@ pub struct CgroupConfig { impl CgroupConfig { fn new(sid: &str, toml_config: &TomlConfig) -> Result { - let overhead_path = utils::gen_overhead_path(sid); let path = if let Ok(spec) = load_oci_spec() { spec.linux() .clone() @@ -60,260 +48,38 @@ impl CgroupConfig { } else { format!("{}/{}", SANDBOXED_CGROUP_PATH, sid) }; + + let overhead_path = utils::gen_overhead_path(is_systemd_cgroup(&path), sid); + + // Dragonball and runtime are the same process, so that the + // sandbox_cgroup_only is overwriten to true. + let sandbox_cgroup_only = if toml_config.runtime.hypervisor_name == HYPERVISOR_DRAGONBALL { + true + } else { + toml_config.runtime.sandbox_cgroup_only + }; + Ok(Self { path, overhead_path, - sandbox_cgroup_only: toml_config.runtime.sandbox_cgroup_only, + sandbox_cgroup_only, }) } -} -pub struct CgroupsResource { - resources: Arc>>, - cgroup_manager: Cgroup, - overhead_cgroup_manager: Option, - cgroup_config: CgroupConfig, -} - -impl CgroupsResource { - pub fn new(sid: &str, toml_config: &TomlConfig) -> Result { - let config = CgroupConfig::new(sid, toml_config)?; - - // Create the sandbox cgroups manager (cgroups on Linux). - // Depending on the sandbox_cgroup_only value, this cgroup - // will either hold all the pod threads (sandbox_cgroup_only is true) - // or only the virtual CPU ones (sandbox_cgroup_only is false). - let hier = cgroups_rs::hierarchies::auto(); - let cgroup_manager = CgroupBuilder::new(&config.path).build(hier)?; - - // The shim configuration is requesting that we do not put all threads - // into the sandbox resource controller. - // We're creating an overhead controller, with no constraints. Everything but - // the vCPU threads will eventually make it there. - let overhead_cgroup_manager = if !config.sandbox_cgroup_only { - let hier = cgroups_rs::hierarchies::auto(); - Some(CgroupBuilder::new(&config.overhead_path).build(hier)?) - } else { - None - }; - - // Add the runtime to the VMM sandbox resource controller - - // By adding the runtime process to either the sandbox or overhead controller, we are making - // sure that any child process of the runtime (i.e. *all* processes serving a Kata pod) - // will initially live in this controller. Depending on the sandbox_cgroup_only settings, we will - // then move the vCPU threads between resource controllers. - let pid = CgroupPid { pid: 0 }; - if let Some(manager) = overhead_cgroup_manager.as_ref() { - manager.add_task_by_tgid(pid).context("add task by tgid")?; - } else { - cgroup_manager - .add_task_by_tgid(pid) - .context("add task by tgid with sandbox only")?; - } + fn restore(state: &CgroupState) -> Result { + let path = state + .path + .as_ref() + .ok_or_else(|| anyhow!("cgroup path is missing in state"))?; + let overhead_path = state + .overhead_path + .as_ref() + .ok_or_else(|| anyhow!("overhead path is missing in state"))?; Ok(Self { - cgroup_manager, - resources: Arc::new(RwLock::new(HashMap::new())), - overhead_cgroup_manager, - cgroup_config: config, - }) - } - - /// delete will move the running processes in the cgroup_manager and - /// overhead_cgroup_manager to the parent and then delete the cgroups. - pub async fn delete(&self) -> Result<()> { - for cg_pid in self.cgroup_manager.procs() { - // For now, we can't guarantee that the process in cgroup_manager does still - // exist. Once it exit, we should ignore that error returned by remove_task_by_tgid - // to let it go. - if let Err(error) = self.cgroup_manager.remove_task_by_tgid(cg_pid) { - match error.source() { - Some(err) => match err.downcast_ref::() { - Some(e) => { - if e.raw_os_error() != Some(OS_ERROR_NO_SUCH_PROCESS) { - return Err(error.into()); - } - } - None => return Err(error.into()), - }, - None => return Err(error.into()), - } - } - } - - self.cgroup_manager - .delete() - .context("delete cgroup manager")?; - - if let Some(overhead) = self.overhead_cgroup_manager.as_ref() { - for cg_pid in overhead.tasks() { - overhead.remove_task(cg_pid)?; - } - overhead.delete().context("delete overhead")?; - } - - Ok(()) - } - - pub async fn update_cgroups( - &self, - cid: &str, - linux_resources: Option<&LinuxResources>, - op: ResourceUpdateOp, - h: &dyn Hypervisor, - ) -> Result<()> { - let new_resources = self.calc_resource(linux_resources); - let old_resources = self.update_resources(cid, new_resources.clone(), op).await; - - if let Some(old_resource) = old_resources.clone() { - if old_resource == new_resources { - return Ok(()); - } - } - - match self.do_update_cgroups(h).await { - Err(e) => { - // if update failed, we should roll back the records in resources - let mut resources = self.resources.write().await; - match op { - ResourceUpdateOp::Add => { - resources.remove(cid); - } - ResourceUpdateOp::Update | ResourceUpdateOp::Del => { - if let Some(old_resource) = old_resources { - resources.insert(cid.to_owned(), old_resource); - } - } - } - Err(e) - } - Ok(()) => Ok(()), - } - } - - async fn update_resources( - &self, - cid: &str, - new_resource: Resources, - op: ResourceUpdateOp, - ) -> Option { - let mut resources = self.resources.write().await; - match op { - ResourceUpdateOp::Add | ResourceUpdateOp::Update => { - resources.insert(cid.to_owned(), new_resource.clone()) - } - ResourceUpdateOp::Del => resources.remove(cid), - } - } - - async fn do_update_cgroups(&self, h: &dyn Hypervisor) -> Result<()> { - let merged_resources = self.merge_resources().await; - self.cgroup_manager - .apply(&merged_resources) - .map_err(|e| anyhow!(e))?; - - if self.overhead_cgroup_manager.is_some() { - // If we have an overhead controller, new vCPU threads would start there, - // as being children of the VMM PID. - // We need to constrain them by moving them into the sandbox controller. - self.constrain_hypervisor(h).await? - } - - Ok(()) - } - - /// constrain_hypervisor will place the VMM and vCPU threads into resource controllers (cgroups on Linux). - async fn constrain_hypervisor(&self, h: &dyn Hypervisor) -> Result<()> { - let tids = h.get_thread_ids().await?; - let tids = tids.vcpus.values(); - - // All vCPU threads move to the sandbox controller. - for tid in tids { - self.cgroup_manager - .add_task(CgroupPid { pid: *tid as u64 })? - } - - Ok(()) - } - - async fn merge_resources(&self) -> Resources { - let resources = self.resources.read().await; - - let mut cpu_list: HashSet = HashSet::new(); - let mut mem_list: HashSet = HashSet::new(); - - resources.values().for_each(|r| { - if let Some(cpus) = &r.cpu.cpus { - cpu_list.insert(cpus.clone()); - } - if let Some(mems) = &r.cpu.mems { - mem_list.insert(mems.clone()); - } - }); - - let cpu_resource = CpuResources { - cpus: Some(Vec::from_iter(cpu_list.into_iter()).join(",")), - mems: Some(Vec::from_iter(mem_list.into_iter()).join(",")), - ..Default::default() - }; - - Resources { - cpu: cpu_resource, - ..Default::default() - } - } - - fn calc_cpu_resources(&self, linux_resources: Option<&LinuxResources>) -> CpuResources { - let cpus = linux_resources - .and_then(|res| res.cpu().clone()) - .and_then(|cpu| cpu.cpus().clone()); - - let mems = linux_resources - .and_then(|res| res.cpu().clone()) - .and_then(|cpu| cpu.mems().clone()); - - CpuResources { - cpus, - mems, - ..Default::default() - } - } - - fn calc_resource(&self, linux_resources: Option<&LinuxResources>) -> Resources { - Resources { - cpu: self.calc_cpu_resources(linux_resources), - ..Default::default() - } - } -} - -#[async_trait] -impl Persist for CgroupsResource { - type State = CgroupState; - type ConstructorArgs = CgroupArgs; - /// Save a state of the component. - async fn save(&self) -> Result { - Ok(CgroupState { - path: Some(self.cgroup_config.path.clone()), - overhead_path: Some(self.cgroup_config.overhead_path.clone()), - sandbox_cgroup_only: self.cgroup_config.sandbox_cgroup_only, - }) - } - /// Restore a component from a specified state. - async fn restore( - cgroup_args: Self::ConstructorArgs, - cgroup_state: Self::State, - ) -> Result { - let hier = cgroups_rs::hierarchies::auto(); - let config = CgroupConfig::new(&cgroup_args.sid, &cgroup_args.config)?; - let path = cgroup_state.path.unwrap_or_default(); - let cgroup_manager = Cgroup::load(hier, path.as_str()); - Ok(Self { - cgroup_manager, - resources: Arc::new(RwLock::new(HashMap::new())), - overhead_cgroup_manager: None, - cgroup_config: config, + path: path.clone(), + overhead_path: overhead_path.clone(), + sandbox_cgroup_only: state.sandbox_cgroup_only, }) } } diff --git a/src/runtime-rs/crates/resource/src/cgroups/resource.rs b/src/runtime-rs/crates/resource/src/cgroups/resource.rs new file mode 100644 index 0000000000..c76913bd77 --- /dev/null +++ b/src/runtime-rs/crates/resource/src/cgroups/resource.rs @@ -0,0 +1,99 @@ +// Copyright (c) 2019-2022 Alibaba Cloud +// Copyright (c) 2019-2025 Ant Group +// +// SPDX-License-Identifier: Apache-2.0 +// + +use std::sync::Arc; + +use anyhow::{Context, Result}; +use async_trait::async_trait; +use hypervisor::Hypervisor; +use kata_types::config::TomlConfig; +use oci_spec::runtime::LinuxResources; +use persist::sandbox_persist::Persist; +use tokio::sync::RwLock; + +use crate::cgroups::cgroup_persist::CgroupState; +use crate::cgroups::resource_inner::CgroupsResourceInner; +use crate::cgroups::{CgroupArgs, CgroupConfig}; +use crate::ResourceUpdateOp; + +/// CgroupsResource manages sandbox cgroup and overhead cgroup. +/// +/// Putting the processes under the cgroup from OCI spec (a.k.a sandbox +/// cgroup) by default. The container runtime (e.g. containerd) imposes +/// limits on the parent of that cgroup. In case of disabling +/// `sandbox_cgroup_only`, the runtime and other components except for VMM +/// (e.g. virtiofsd) are put under the overhead cgroup, which no resource +/// limits are imposed on it. +pub struct CgroupsResource { + cgroup_config: CgroupConfig, + inner: Arc>, +} + +impl CgroupsResource { + pub fn new(sid: &str, toml_config: &TomlConfig) -> Result { + let cgroup_config = CgroupConfig::new(sid, toml_config)?; + let inner = CgroupsResourceInner::new(&cgroup_config)?; + let inner = Arc::new(RwLock::new(inner)); + + Ok(Self { + cgroup_config, + inner, + }) + } +} + +impl CgroupsResource { + pub async fn delete(&self) -> Result<()> { + let mut inner = self.inner.write().await; + inner.delete().await + } + + pub async fn update( + &self, + cid: &str, + resources: Option<&LinuxResources>, + op: ResourceUpdateOp, + hypervisor: &dyn Hypervisor, + ) -> Result<()> { + let mut inner = self.inner.write().await; + inner.update(cid, resources, op, hypervisor).await + } + + pub async fn setup_after_start_vm(&self, hypervisor: &dyn Hypervisor) -> Result<()> { + let mut inner = self.inner.write().await; + inner.setup_after_start_vm(hypervisor).await + } +} + +#[async_trait] +impl Persist for CgroupsResource { + type State = CgroupState; + type ConstructorArgs = CgroupArgs; + /// Save a state of the component. + async fn save(&self) -> Result { + Ok(CgroupState { + path: Some(self.cgroup_config.path.clone()), + overhead_path: Some(self.cgroup_config.overhead_path.clone()), + sandbox_cgroup_only: self.cgroup_config.sandbox_cgroup_only, + }) + } + + /// Restore a component from a specified state. + async fn restore( + _cgroup_args: Self::ConstructorArgs, + cgroup_state: Self::State, + ) -> Result { + let cgroup_config = CgroupConfig::restore(&cgroup_state)?; + let inner = CgroupsResourceInner::restore(&cgroup_config) + .context("restore cgroups resource inner")?; + let inner = Arc::new(RwLock::new(inner)); + + Ok(Self { + cgroup_config, + inner, + }) + } +} diff --git a/src/runtime-rs/crates/resource/src/cgroups/resource_inner.rs b/src/runtime-rs/crates/resource/src/cgroups/resource_inner.rs new file mode 100644 index 0000000000..3b385e6aa7 --- /dev/null +++ b/src/runtime-rs/crates/resource/src/cgroups/resource_inner.rs @@ -0,0 +1,298 @@ +// Copyright (c) 2019-2022 Alibaba Cloud +// Copyright (c) 2019-2025 Ant Group +// +// SPDX-License-Identifier: Apache-2.0 +// + +use std::collections::{HashMap, HashSet}; +use std::process; + +use anyhow::{anyhow, Context, Result}; +use cgroups_rs::manager::is_systemd_cgroup; +use cgroups_rs::{CgroupPid, FsManager, Manager, SystemdManager}; +use hypervisor::Hypervisor; +use oci_spec::runtime::{LinuxCpu, LinuxCpuBuilder, LinuxResources, LinuxResourcesBuilder}; + +use crate::cgroups::utils::get_tgid_from_pid; +use crate::cgroups::CgroupConfig; +use crate::ResourceUpdateOp; + +pub type CgroupManager = Box; + +pub(crate) struct CgroupsResourceInner { + /// Container resources, key is container id, and value is resources. + resources: HashMap, + sandbox_cgroup: CgroupManager, + overhead_cgroup: Option, +} + +impl CgroupsResourceInner { + /// Create cgroup managers according to the cgroup configuration. + /// + /// # Returns + /// + /// - `Ok((CgroupManager, Option))`: A tuple containing + /// the sandbox cgroup manager and an optional overhead cgroup + /// manager. + fn new_cgroup_managers( + config: &CgroupConfig, + ) -> Result<(CgroupManager, Option)> { + let use_systemd = is_systemd_cgroup(&config.path); + let sandbox_cgroup = if use_systemd { + let mut manager = SystemdManager::new(&config.path).context("new systemd manager")?; + // Set SIGTERM timeout to 5mins, so that the runtime has up to + // 5mins to do graceful shutdown. Exceeding this timeout, the + // systemd will forcibly kill the runtime by sending SIGKILL. + manager.set_term_timeout(300).context("set term timeout")?; + Box::new(manager) as Box + } else { + let manager = FsManager::new(&config.path).context("new fs manager")?; + Box::new(manager) as Box + }; + + let overhead_cgroup = if config.sandbox_cgroup_only { + None + } else if use_systemd { + let mut manager = SystemdManager::new(&config.overhead_path) + .context("new systemd manager for overhead")?; + manager + .set_term_timeout(300) + .context("set term timeout for overhead")?; + Some(Box::new(manager) as Box) + } else { + let manager = + FsManager::new(&config.overhead_path).context("new fs manager for overhead")?; + Some(Box::new(manager) as Box) + }; + + Ok((sandbox_cgroup, overhead_cgroup)) + } + + /// Create a new `CgroupsResourceInner` instance. + pub(crate) fn new(config: &CgroupConfig) -> Result { + let (mut sandbox_cgroup, mut overhead_cgroup) = + Self::new_cgroup_managers(config).context("create new cgroups")?; + + // The runtime is prioritized to be added to the overhead cgroup. + let pid = CgroupPid::from(process::id() as u64); + if let Some(overhead_cgroup) = overhead_cgroup.as_mut() { + overhead_cgroup + .add_proc(pid) + .context("add runtime to overhead cgroup")?; + } else { + sandbox_cgroup + .add_proc(pid) + .context("add runtime to sandbox cgroup")?; + } + + Ok(Self { + resources: HashMap::new(), + sandbox_cgroup, + overhead_cgroup, + }) + } + + pub(crate) fn restore(config: &CgroupConfig) -> Result { + let (sandbox_cgroup, overhead_cgroup) = + Self::new_cgroup_managers(config).context("restore cgroups")?; + + Ok(Self { + resources: HashMap::new(), + sandbox_cgroup, + overhead_cgroup, + }) + } +} + +impl CgroupsResourceInner { + /// Add cpuset resources of all containers to the sandbox cgroup. + fn collect_resources(&self) -> Result { + let mut cpu_cpus = HashSet::new(); + let mut cpu_mems = HashSet::new(); + + for res in self.resources.values() { + if let Some(cpu) = res.cpu() { + if let Some(cpus) = cpu.cpus() { + cpu_cpus.insert(cpus.to_string()); + } + if let Some(mems) = cpu.mems() { + cpu_mems.insert(mems.to_string()); + } + } + } + + let mut resources_builder = LinuxResourcesBuilder::default(); + + let mut cpu_builder = LinuxCpuBuilder::default(); + if !cpu_cpus.is_empty() { + cpu_builder = cpu_builder.cpus(cpu_cpus.into_iter().collect::>().join(",")); + } + if !cpu_mems.is_empty() { + cpu_builder = cpu_builder.mems(cpu_mems.into_iter().collect::>().join(",")); + } + let cpu = cpu_builder.build().context("build linux cpu")?; + if cpu != LinuxCpu::default() { + resources_builder = resources_builder.cpu(cpu); + } + + let resources = resources_builder.build().context("build linux resources")?; + + Ok(resources) + } + + async fn move_vcpus_to_sandbox_cgroup(&mut self, hypervisor: &dyn Hypervisor) -> Result { + let hv_pids = hypervisor.get_thread_ids().await?; + let mut pids = hv_pids.vcpus.values(); + + // Use threaded mode only in cgroup v1 + cgroupfs + if !self.sandbox_cgroup.systemd() && !self.sandbox_cgroup.v2() { + for pid in pids { + let pid = CgroupPid::from(*pid as u64); + self.sandbox_cgroup + .add_thread(pid) + .with_context(|| format!("add vcpu pid {}", pid.pid))? + } + } else { + // No vCPU, exits early + let vcpu = match pids.next() { + Some(pid) => *pid, + None => return Ok(0), + }; + + let tgid = get_tgid_from_pid(vcpu as i32).context("get tgid from vCPU thread")? as u64; + self.sandbox_cgroup + .add_proc(CgroupPid::from(tgid)) + .with_context(|| format!("add vcpu tgid {}", tgid))?; + } + + Ok(hv_pids.vcpus.len()) + } + + async fn update_sandbox_cgroups(&mut self, hypervisor: &dyn Hypervisor) -> Result { + // The runtime is under overhead cgroup if available. The + // hypervisor as a child of the runtime is under the overhead + // cgroup by default. We should move VMM process/vCPU threads to + // the sandbox cgroup to prevent them from consuming excessive + // resources. + if self.overhead_cgroup.is_some() { + let vcpu_num = self + .move_vcpus_to_sandbox_cgroup(hypervisor) + .await + .context("move vcpus to sandbox cgroup")?; + // The cgroup managers will not create cgroups if no processes + // are added to it. `vcpu_num == 0` reflects that the + // hypervisor hasn't been started yet. We skip resource + // setting, as the sandbox cgroup might not be created yet. + if vcpu_num == 0 { + return Ok(false); + } + } + + let sandbox_resources = self.collect_resources().context("collect resources")?; + self.sandbox_cgroup.set(&sandbox_resources).context("set")?; + + Ok(true) + } +} + +impl CgroupsResourceInner { + pub(crate) async fn delete(&mut self) -> Result<()> { + self.sandbox_cgroup + .destroy() + .context("destroy sandbox cgroup")?; + + if let Some(overhead_cgroup) = self.overhead_cgroup.as_mut() { + overhead_cgroup + .destroy() + .context("destroy overhead cgroup")?; + } + + Ok(()) + } + + pub(crate) async fn update( + &mut self, + cid: &str, + resources: Option<&LinuxResources>, + op: ResourceUpdateOp, + hypervisor: &dyn Hypervisor, + ) -> Result<()> { + let old = match op { + ResourceUpdateOp::Add | ResourceUpdateOp::Update => { + let resources = resources.ok_or_else(|| { + anyhow::anyhow!("resources should not be empty for Add or Update operation") + })?; + let new = new_cpuset_resources(resources).context("new cpuset resources")?; + let old = self.resources.insert(cid.to_string(), new.clone()); + // If the new resources are the same as the old ones, we + // can skip the update. + if let Some(old) = old.as_ref() { + if old == &new { + return Ok(()); + } + } + old + } + ResourceUpdateOp::Del => self.resources.remove(cid), + }; + + let ret = self + .update_sandbox_cgroups(hypervisor) + .await + .context("update sandbox cgroups"); + + // Rollback if the update fails + if ret.is_err() { + match op { + ResourceUpdateOp::Add => { + self.resources.remove(cid); + } + ResourceUpdateOp::Update | ResourceUpdateOp::Del => { + if let Some(old) = old { + self.resources.insert(cid.to_string(), old); + } + } + } + } + + ret.map(|_| ()) + } + + pub(crate) async fn setup_after_start_vm(&mut self, hypervisor: &dyn Hypervisor) -> Result<()> { + let updated = self + .update_sandbox_cgroups(hypervisor) + .await + .context("update sandbox cgroups after start vm")?; + + // There is an overhead cgroup and we are falling to move the vCPUs + // to the sandbox cgroup, it results in those threads being under + // the overhead cgroup, and allowing them to consume more resources + // than we have allocated for the sandbox. + if self.overhead_cgroup.is_some() && !updated { + return Err(anyhow!("hypervisor cannot be moved to sandbox cgroup")); + } + + Ok(()) + } +} + +/// Copy cpu.cpus and cpu.mems from the given resources to new resources. +fn new_cpuset_resources(resources: &LinuxResources) -> Result { + let cpu = resources.cpu(); + let cpus = cpu.as_ref().and_then(|c| c.cpus().clone()); + let mems = cpu.as_ref().and_then(|c| c.mems().clone()); + + let mut builder = LinuxCpuBuilder::default(); + if let Some(cpus) = cpus { + builder = builder.cpus(cpus); + } + if let Some(mems) = mems { + builder = builder.mems(mems); + } + let linux_cpu = builder.build().context("build linux cpu")?; + + let builder = LinuxResourcesBuilder::default().cpu(linux_cpu); + let resources = builder.build().context("build linux resources")?; + + Ok(resources) +} diff --git a/src/runtime-rs/crates/resource/src/cgroups/utils.rs b/src/runtime-rs/crates/resource/src/cgroups/utils.rs index 7a2d630982..068f3b1e49 100644 --- a/src/runtime-rs/crates/resource/src/cgroups/utils.rs +++ b/src/runtime-rs/crates/resource/src/cgroups/utils.rs @@ -1,9 +1,11 @@ // Copyright (c) 2019-2022 Alibaba Cloud -// Copyright (c) 2019-2022 Ant Group +// Copyright (c) 2019-2025 Ant Group // // SPDX-License-Identifier: Apache-2.0 // +use anyhow::{anyhow, Context, Result}; + // When the Kata overhead threads (I/O, VMM, etc) are not // placed in the sandbox resource controller (A cgroup on Linux), // they are moved to a specific, unconstrained resource controller. @@ -11,6 +13,55 @@ // on a cgroup v1 system, the Kata overhead memory cgroup will be at // /sys/fs/cgroup/memory/kata_overhead/$CGPATH where $CGPATH is // defined by the orchestrator. -pub(crate) fn gen_overhead_path(path: &str) -> String { - format!("kata_overhead/{}", path.trim_start_matches('/')) +pub(crate) fn gen_overhead_path(systemd: bool, path: &str) -> String { + if systemd { + format!("kata-overhead.slice:runtime-rs:{}", path) + } else { + format!("kata_overhead/{}", path.trim_start_matches('/')) + } +} + +/// Get the thread group ID (TGID) from `/proc/{pid}/status`. +pub(crate) fn get_tgid_from_pid(pid: i32) -> Result { + let status = std::fs::read_to_string(format!("/proc/{}/status", pid)) + .map_err(|e| anyhow!("failed to read /proc/{}/status: {}", pid, e))?; + status + .lines() + .find_map(|line| { + if line.starts_with("Tgid") { + let part = line.split(":").nth(1)?; + part.trim().parse::().ok() + } else { + None + } + }) + .ok_or(anyhow!("tgid not found")) + .with_context(|| anyhow!("failed to parse tgid")) +} + +#[cfg(test)] +mod tests { + use crate::cgroups::utils::*; + + #[test] + fn test_gen_overhead_path() { + let systemd = true; + let path = "kata_sandboxed_pod"; + let expected = "kata-overhead.slice:runtime-rs:kata_sandboxed_pod"; + let actual = gen_overhead_path(systemd, path); + assert_eq!(actual, expected); + + let systemd = false; + let expected = "kata_overhead/kata_sandboxed_pod"; + let actual = gen_overhead_path(systemd, path); + assert_eq!(actual, expected); + } + + #[test] + fn test_get_tgid_from_pid() { + let pid = unsafe { libc::gettid() }; + let expected = unsafe { libc::getpid() }; + let actual = get_tgid_from_pid(pid).unwrap(); + assert_eq!(actual, expected); + } } diff --git a/src/runtime-rs/crates/resource/src/manager_inner.rs b/src/runtime-rs/crates/resource/src/manager_inner.rs index fb6c3d01e0..ad83848825 100644 --- a/src/runtime-rs/crates/resource/src/manager_inner.rs +++ b/src/runtime-rs/crates/resource/src/manager_inner.rs @@ -288,6 +288,11 @@ impl ResourceManagerInner { } pub async fn setup_after_start_vm(&mut self) -> Result<()> { + self.cgroups_resource + .setup_after_start_vm(self.hypervisor.as_ref()) + .await + .context("setup cgroups after start vm")?; + if let Some(share_fs) = self.share_fs.as_ref() { share_fs .setup_device_after_start_vm(self.hypervisor.as_ref(), &self.device_manager) @@ -563,7 +568,7 @@ impl ResourceManagerInner { // we should firstly update the vcpus and mems, and then update the host cgroups self.cgroups_resource - .update_cgroups(cid, linux_resources, op, self.hypervisor.as_ref()) + .update(cid, linux_resources, op, self.hypervisor.as_ref()) .await?; if let Some(swap) = self.swap_resource.as_ref() {