From eb43ab34d9aa33d98981a24f33ccb6e9b32daaa3 Mon Sep 17 00:00:00 2001 From: Patrick Mooney Date: Thu, 4 Jan 2024 19:53:27 -0600 Subject: [PATCH] Gripe when using non-raw block device If the S_IFBLK instance of a block device is used, rather than the S_IFCHR raw instance, flush operations can be very expensive as the OS is forced to walk the page cache looking for necessary work. While we will not strictly forbid the operator from choosing to use such a device, we can at least admonish their choice in the logs. Fixes #518 --- bin/propolis-server/src/lib/initializer.rs | 11 +++++++++++ bin/propolis-standalone/src/config.rs | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/bin/propolis-server/src/lib/initializer.rs b/bin/propolis-server/src/lib/initializer.rs index b557b8e2b..1b0c0506f 100644 --- a/bin/propolis-server/src/lib/initializer.rs +++ b/bin/propolis-server/src/lib/initializer.rs @@ -6,6 +6,7 @@ use std::convert::TryInto; use std::fs::File; use std::io::{Error, ErrorKind}; use std::num::NonZeroUsize; +use std::os::unix::fs::FileTypeExt; use std::sync::Arc; use std::time::{SystemTime, UNIX_EPOCH}; @@ -327,6 +328,16 @@ impl<'a> MachineInitializer<'a> { info!(self.log, "Creating file disk backend"; "path" => &spec.path); + // Check if raw device is being used and gripe if it isn't + let meta = std::fs::metadata(&spec.path)?; + if meta.file_type().is_block_device() { + slog::warn!( + self.log, + "Block backend using standard device rather than raw"; + "path" => &spec.path + ); + } + let nworkers = NonZeroUsize::new(8).unwrap(); let be = propolis::block::FileBackend::create( &spec.path, diff --git a/bin/propolis-standalone/src/config.rs b/bin/propolis-standalone/src/config.rs index 86427f992..5a33c03a4 100644 --- a/bin/propolis-standalone/src/config.rs +++ b/bin/propolis-standalone/src/config.rs @@ -4,6 +4,7 @@ use std::collections::BTreeMap; use std::num::NonZeroUsize; +use std::os::unix::fs::FileTypeExt; use std::str::FromStr; use std::sync::Arc; @@ -58,6 +59,14 @@ pub fn block_backend( "file" => { let parsed: FileConfig = opt_deser(&be.options).unwrap(); + // Check if raw device is being used and gripe if it isn't + let meta = std::fs::metadata(&parsed.path) + .expect("file device path is valid"); + if meta.file_type().is_block_device() { + slog::warn!(log, "Block backend using standard device rather than raw"; + "path" => &parsed.path); + } + let be = block::FileBackend::create( &parsed.path, opts,