Skip to content

Commit 6d6fc65

Browse files
feat(config): extends config yaml with core config and delay mode
This allows configuration of the core pin per node. Signed-off-by: Tiago Castro <tiagolobocastro@gmail.com>
1 parent 26b253b commit 6d6fc65

File tree

5 files changed

+85
-23
lines changed

5 files changed

+85
-23
lines changed

io-engine/src/bin/io-engine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
291291
let ms = MayastorEnvironment::new(args.clone()).init();
292292
start_tokio_runtime(&args);
293293

294-
Reactors::current().running();
294+
Reactors::current().init_running();
295295
Reactors::current().poll_reactor();
296296

297297
ms.fini();

io-engine/src/core/env.rs

+46-8
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,23 @@ pub struct MayastorCliArgs {
249249
/// LVM pools can then be created by specifying the LVM pool type.
250250
/// If LVM is enabled and LVM_SUPPRESS_FD_WARNINGS is not set then it will
251251
/// be set to 1.
252-
#[clap(long = "enable-lvm", env = "ENABLE_LVM")]
252+
#[clap(long = "enable-lvm", env = "ENABLE_LVM", value_parser = delay_compat)]
253253
pub lvm: bool,
254254
/// Enables experimental Snapshot Rebuild support.
255-
#[clap(long = "enable-snapshot-rebuild", env = "ENABLE_SNAPSHOT_REBUILD")]
255+
#[clap(long = "enable-snapshot-rebuild", env = "ENABLE_SNAPSHOT_REBUILD", value_parser = delay_compat)]
256256
pub snap_rebuild: bool,
257+
/// Reactors sleep 1ms before each poll.
258+
/// # Warning: Don't use this in production.
259+
#[clap(long, env = "MAYASTOR_DELAY", hide = true, value_parser = delay_compat)]
260+
pub developer_delay: bool,
261+
}
262+
263+
fn delay_compat(s: &str) -> Result<bool, String> {
264+
match s {
265+
"1" | "true" => Ok(true),
266+
"" | "0" | "false" => Ok(false),
267+
_else => Err(format!("Must be one of: 1,true,0,false")),
268+
}
257269
}
258270

259271
/// Mayastor features.
@@ -312,6 +324,7 @@ impl Default for MayastorCliArgs {
312324
enable_nexus_channel_debug: false,
313325
lvm: false,
314326
snap_rebuild: false,
327+
developer_delay: false,
315328
}
316329
}
317330
}
@@ -411,6 +424,7 @@ pub struct MayastorEnvironment {
411424
api_versions: Vec<ApiVersion>,
412425
skip_sig_handler: bool,
413426
enable_io_all_thrd_nexus_channels: bool,
427+
developer_delay: bool,
414428
}
415429

416430
impl Default for MayastorEnvironment {
@@ -458,6 +472,7 @@ impl Default for MayastorEnvironment {
458472
api_versions: vec![ApiVersion::V0, ApiVersion::V1],
459473
skip_sig_handler: false,
460474
enable_io_all_thrd_nexus_channels: false,
475+
developer_delay: false,
461476
}
462477
}
463478
}
@@ -562,7 +577,8 @@ struct SubsystemCtx {
562577

563578
static MAYASTOR_FEATURES: OnceCell<MayastorFeatures> = OnceCell::new();
564579

565-
static MAYASTOR_DEFAULT_ENV: OnceCell<MayastorEnvironment> = OnceCell::new();
580+
static MAYASTOR_DEFAULT_ENV: OnceCell<parking_lot::Mutex<MayastorEnvironment>> =
581+
OnceCell::new();
566582

567583
impl MayastorEnvironment {
568584
pub fn new(args: MayastorCliArgs) -> Self {
@@ -597,6 +613,7 @@ impl MayastorEnvironment {
597613
nvmf_tgt_crdt: args.nvmf_tgt_crdt,
598614
api_versions: args.api_versions,
599615
skip_sig_handler: args.skip_sig_handler,
616+
developer_delay: args.developer_delay,
600617
enable_io_all_thrd_nexus_channels: args
601618
.enable_io_all_thrd_nexus_channels,
602619
..Default::default()
@@ -610,15 +627,23 @@ impl MayastorEnvironment {
610627
}
611628

612629
fn setup_static(self) -> Self {
613-
MAYASTOR_DEFAULT_ENV.get_or_init(|| self.clone());
630+
match MAYASTOR_DEFAULT_ENV.get() {
631+
None => {
632+
MAYASTOR_DEFAULT_ENV
633+
.get_or_init(|| parking_lot::Mutex::new(self.clone()));
634+
}
635+
Some(some) => {
636+
*some.lock() = self.clone();
637+
}
638+
}
614639
self
615640
}
616641

617642
/// Get the global environment (first created on new)
618643
/// or otherwise the default one (used by the tests)
619644
pub fn global_or_default() -> Self {
620645
match MAYASTOR_DEFAULT_ENV.get() {
621-
Some(env) => env.clone(),
646+
Some(env) => env.lock().clone(),
622647
None => MayastorEnvironment::default(),
623648
}
624649
}
@@ -913,9 +938,9 @@ impl MayastorEnvironment {
913938
}
914939
}
915940

916-
/// load the config and apply it before any subsystems have started.
941+
/// Load the config and apply it before any subsystems have started.
917942
/// there is currently no run time check that enforces this.
918-
fn load_yaml_config(&self) {
943+
fn load_yaml_config(&mut self) {
919944
let cfg = if let Some(yaml) = &self.mayastor_config {
920945
info!("loading mayastor config YAML file {}", yaml);
921946
Config::get_or_init(|| {
@@ -930,6 +955,19 @@ impl MayastorEnvironment {
930955
Config::get_or_init(Config::default)
931956
};
932957
cfg.apply();
958+
if let Some(mask) = cfg.eal_opts.reactor_mask.as_ref() {
959+
self.reactor_mask = mask.clone();
960+
}
961+
if cfg.eal_opts.core_list.is_some() {
962+
self.core_list = cfg.eal_opts.core_list.clone();
963+
}
964+
if let Some(delay) = cfg.eal_opts.developer_delay {
965+
self.developer_delay = delay;
966+
}
967+
if let Some(interface) = &cfg.nvmf_tcp_tgt_conf.interface {
968+
self.nvmf_tgt_interface = Some(interface.clone());
969+
}
970+
self.clone().setup_static();
933971
}
934972

935973
/// load the pool config file.
@@ -991,7 +1029,7 @@ impl MayastorEnvironment {
9911029
}
9921030

9931031
// allocate a Reactor per core
994-
Reactors::init();
1032+
Reactors::init(self.developer_delay);
9951033

9961034
// launch the remote cores if any. note that during init these have to
9971035
// be running as during setup cross call will take place.

io-engine/src/core/reactor.rs

+19-14
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ pub struct Reactor {
117117
incoming: crossbeam::queue::SegQueue<spdk_rs::Thread>,
118118
/// the logical core this reactor is created on
119119
lcore: u32,
120+
/// Sleeps for 1ms before each poll.
121+
/// # Warning: for development only.
122+
developer_delay: bool,
120123
/// represents the state of the reactor
121124
flags: Cell<ReactorState>,
122125
/// Unique identifier of the thread on which reactor is running.
@@ -134,7 +137,7 @@ thread_local! {
134137

135138
impl Reactors {
136139
/// initialize the reactor subsystem for each core assigned to us
137-
pub fn init() {
140+
pub fn init(developer_delay: bool) {
138141
REACTOR_LIST.get_or_init(|| {
139142
let rc = unsafe {
140143
spdk_thread_lib_init_ext(
@@ -149,7 +152,7 @@ impl Reactors {
149152
Reactors(
150153
Cores::count()
151154
.into_iter()
152-
.map(Reactor::new)
155+
.map(|core| Reactor::new(core, developer_delay))
153156
.collect::<Vec<_>>(),
154157
)
155158
});
@@ -282,7 +285,7 @@ impl<'a> IntoIterator for &'a Reactors {
282285

283286
impl Reactor {
284287
/// create a new ['Reactor'] instance
285-
fn new(core: u32) -> Self {
288+
fn new(core: u32, developer_delay: bool) -> Self {
286289
// create a channel to receive futures on
287290
let (sx, rx) =
288291
unbounded::<Pin<Box<dyn Future<Output = ()> + 'static>>>();
@@ -291,6 +294,7 @@ impl Reactor {
291294
threads: RefCell::new(VecDeque::new()),
292295
incoming: crossbeam::queue::SegQueue::new(),
293296
lcore: core,
297+
developer_delay,
294298
flags: Cell::new(ReactorState::Init),
295299
tid: Cell::new(0),
296300
sx,
@@ -308,11 +312,7 @@ impl Reactor {
308312
warn!("calling poll on a reactor who is not in the INIT state");
309313
}
310314

311-
if std::env::var("MAYASTOR_DELAY").is_ok() {
312-
reactor.developer_delayed();
313-
} else {
314-
reactor.running();
315-
}
315+
reactor.init_running();
316316
// loops
317317
reactor.poll_reactor();
318318
0
@@ -417,9 +417,18 @@ impl Reactor {
417417
self.set_state(ReactorState::Running)
418418
}
419419

420+
/// Init the reactor to running or developer delayed state.
421+
pub fn init_running(&self) {
422+
if self.developer_delay {
423+
self.developer_delayed();
424+
} else {
425+
self.running();
426+
}
427+
}
428+
420429
/// set the reactor to sleep each iteration
421430
pub fn developer_delayed(&self) {
422-
info!("core {} set to developer delayed poll mode", self.lcore);
431+
warn!("core {} set to developer delayed poll mode", self.lcore);
423432
self.set_state(ReactorState::Delayed);
424433
}
425434

@@ -667,11 +676,7 @@ impl Future for &'static Reactor {
667676
Poll::Pending
668677
}
669678
ReactorState::Init => {
670-
if std::env::var("MAYASTOR_DELAY").is_ok() {
671-
self.developer_delayed();
672-
} else {
673-
self.running();
674-
}
679+
self.init_running();
675680
cx.waker().wake_by_ref();
676681
Poll::Pending
677682
}

io-engine/src/subsys/config/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,19 @@ impl ConfigSubsystem {
114114
}
115115
}
116116

117+
/// Various EAL (Environment Abstraction Layer) configuration options.
118+
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
119+
#[serde(default, deny_unknown_fields)]
120+
pub struct EalOpts {
121+
/// The reactor mask to be used for starting up the instance.
122+
pub reactor_mask: Option<String>,
123+
/// List of cores to run on instead of using the core mask. When specified
124+
/// it supersedes the reactor mask.
125+
pub core_list: Option<String>,
126+
/// Delay core polling by 1ms.
127+
pub developer_delay: Option<bool>,
128+
}
129+
117130
/// Main config structure of Mayastor. This structure can be persisted to disk.
118131
#[derive(Default, Debug, PartialEq, Serialize, Deserialize)]
119132
#[serde(default, deny_unknown_fields)]
@@ -133,6 +146,8 @@ pub struct Config {
133146
pub socket_opts: PosixSocketOpts,
134147
/// iobuf specific options
135148
pub iobuf_opts: IoBufOpts,
149+
/// Environment Abstraction Layer options.
150+
pub eal_opts: EalOpts,
136151
}
137152

138153
impl Config {
@@ -196,6 +211,7 @@ impl Config {
196211
nexus_opts: self.nexus_opts.get(),
197212
socket_opts: self.socket_opts.get(),
198213
iobuf_opts: self.iobuf_opts.get(),
214+
eal_opts: self.eal_opts.clone(),
199215
}
200216
}
201217

io-engine/src/subsys/config/opts.rs

+3
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ pub struct NvmfTgtConfig {
9292
pub crdt: [u16; TARGET_CRDT_LEN],
9393
/// TCP transport options
9494
pub opts: NvmfTcpTransportOpts,
95+
/// NVMF target interface (ip, mac, name or subnet).
96+
pub interface: Option<String>,
9597
}
9698

9799
impl From<NvmfTgtConfig> for Box<spdk_nvmf_target_opts> {
@@ -112,6 +114,7 @@ impl Default for NvmfTgtConfig {
112114
max_namespaces: 2048,
113115
crdt: args.nvmf_tgt_crdt,
114116
opts: NvmfTcpTransportOpts::default(),
117+
interface: None,
115118
}
116119
}
117120
}

0 commit comments

Comments
 (0)