Skip to content

Commit 3c4768b

Browse files
committed
feat: add support for transparent hugepages
Signed-off-by: Piyush Jena <jepiyush@amazon.com>
1 parent 02abede commit 3c4768b

2 files changed

Lines changed: 104 additions & 3 deletions

File tree

  • bottlerocket-settings-models

bottlerocket-settings-models/modeled-types/src/hugepages.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{error, NonNegativeInteger};
2+
use bottlerocket_scalar_derive::Scalar;
23
use bottlerocket_string_impls_for::string_impls_for;
34
use lazy_static::lazy_static;
45
use regex::Regex;
@@ -9,6 +10,8 @@ use std::collections::HashMap;
910
/// HugepagesSettings contains hugepages and transparent hugepages related settings.
1011
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
1112
pub struct HugepagesSettings {
13+
#[serde(skip_serializing_if = "Option::is_none")]
14+
pub transparent: Option<HugepagesTransparent>,
1215
#[serde(flatten)]
1316
pub hugepages_config: HashMap<HugepageSize, HugepageConfig>,
1417
}
@@ -92,6 +95,86 @@ impl TryFrom<&str> for HugepageSize {
9295

9396
string_impls_for!(HugepageSize, "HugepageSize");
9497

98+
/// Supported transparent hugepages knobs in Bottlerocket
99+
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
100+
pub struct HugepagesTransparent {
101+
#[serde(skip_serializing_if = "Option::is_none")]
102+
pub enabled: Option<TransparentHugepagePolicy>,
103+
#[serde(skip_serializing_if = "Option::is_none")]
104+
pub defrag: Option<TransparentHugepageDefragPolicy>,
105+
}
106+
107+
/// Acceptable transparent hugepages policies
108+
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Scalar, Default)]
109+
#[serde(rename_all = "lowercase")]
110+
pub enum TransparentHugepagePolicy {
111+
#[default]
112+
Never,
113+
Madvise,
114+
Always,
115+
}
116+
117+
#[cfg(test)]
118+
mod test_thp_policy {
119+
use super::TransparentHugepagePolicy;
120+
use std::convert::TryFrom;
121+
use test_case::test_case;
122+
123+
#[test_case("never")]
124+
#[test_case("madvise")]
125+
#[test_case("always")]
126+
fn good_policy(input: &str) {
127+
assert!(TransparentHugepagePolicy::try_from(input).is_ok());
128+
}
129+
130+
#[test_case("disable")]
131+
#[test_case("enable")]
132+
#[test_case("")]
133+
#[test_case("sometimes")]
134+
#[test_case(&"a".repeat(64))]
135+
fn bad_policy(input: &str) {
136+
assert!(TransparentHugepagePolicy::try_from(input).is_err());
137+
}
138+
}
139+
140+
/// Acceptable transparent hugepages defragmentation policies
141+
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Scalar, Default)]
142+
#[serde(rename_all = "lowercase")]
143+
pub enum TransparentHugepageDefragPolicy {
144+
#[default]
145+
Never,
146+
Madvise,
147+
Defer,
148+
#[serde(rename = "defer+madvise")]
149+
DeferMadvise,
150+
Always,
151+
}
152+
153+
#[cfg(test)]
154+
mod test_thp_defrag_policy {
155+
use super::TransparentHugepageDefragPolicy;
156+
use std::convert::TryFrom;
157+
use test_case::test_case;
158+
159+
#[test_case("never")]
160+
#[test_case("madvise")]
161+
#[test_case("defer")]
162+
#[test_case("defer+madvise")]
163+
#[test_case("always")]
164+
fn good_policy(input: &str) {
165+
assert!(TransparentHugepageDefragPolicy::try_from(input).is_ok());
166+
}
167+
168+
#[test_case("disable")]
169+
#[test_case("enable")]
170+
#[test_case("")]
171+
#[test_case("sometimes")]
172+
#[test_case(&"a".repeat(64))]
173+
fn bad_policy(input: &str) {
174+
assert!(TransparentHugepageDefragPolicy::try_from(input).is_err());
175+
}
176+
}
177+
95178
#[cfg(test)]
96179
mod test_hugepage_size {
97180
use super::HugepageSize;

bottlerocket-settings-models/settings-extensions/kernel/src/lib.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ impl SettingsModel for KernelSettingsV1 {
5353
#[cfg(test)]
5454
mod test {
5555
use super::*;
56-
use bottlerocket_modeled_types::{HugepageConfig, HugepageSize, NonNegativeInteger};
56+
use bottlerocket_modeled_types::{
57+
HugepageConfig, HugepageSize, HugepagesTransparent, NonNegativeInteger,
58+
TransparentHugepageDefragPolicy, TransparentHugepagePolicy,
59+
};
5760

5861
#[test]
5962
fn test_generate_kernel() {
@@ -78,7 +81,8 @@ mod test {
7881
"sysctl": {"key": "value"},
7982
"hugepages": {
8083
"2Mi": {"count": 512},
81-
"1Gi": {"count": 4}
84+
"1Gi": {"count": 4},
85+
"transparent": {"enabled": "always", "defrag": "defer+madvise"}
8286
}
8387
}"#;
8488

@@ -112,7 +116,13 @@ mod test {
112116
},
113117
);
114118

115-
let hugepages = Some(HugepagesSettings { hugepages_config });
119+
let hugepages = Some(HugepagesSettings {
120+
transparent: Some(HugepagesTransparent {
121+
enabled: Some(TransparentHugepagePolicy::try_from("always").unwrap()),
122+
defrag: Some(TransparentHugepageDefragPolicy::try_from("defer+madvise").unwrap()),
123+
}),
124+
hugepages_config,
125+
});
116126

117127
assert_eq!(
118128
kernel,
@@ -128,5 +138,13 @@ mod test {
128138
let hugepages_out = &roundtrip["hugepages"];
129139
assert_eq!(hugepages_out["2Mi"]["count"], serde_json::json!(512));
130140
assert_eq!(hugepages_out["1Gi"]["count"], serde_json::json!(4));
141+
assert_eq!(
142+
hugepages_out["transparent"]["enabled"],
143+
serde_json::json!("always")
144+
);
145+
assert_eq!(
146+
hugepages_out["transparent"]["defrag"],
147+
serde_json::json!("defer+madvise")
148+
);
131149
}
132150
}

0 commit comments

Comments
 (0)