From 17e9a2cff5c8b08438dfcfde59de7b239bb2654f Mon Sep 17 00:00:00 2001 From: Maksym Pavlenko Date: Wed, 24 Feb 2021 17:03:57 -0800 Subject: [PATCH] agent: don't error of virtiofs share is already mounted Port kata-containers/agent#883 to the Rust Agent. In the event that the virtiofs device is already mounted at the requested destination, don't error out. We'll check before attempting to mount to see if the destination is already a mount point. If so, skip doing the mount in the agent. This facilitates mounting the sharedfs automatically in the guest before the agent service starts. Signed-off-by: Eric Ernst eric.g.ernst@gmail.com Fixes: #1398 Signed-off-by: Maksym Pavlenko --- src/agent/src/mount.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/agent/src/mount.rs b/src/agent/src/mount.rs index 188c2073a6..fcdd98d593 100644 --- a/src/agent/src/mount.rs +++ b/src/agent/src/mount.rs @@ -44,6 +44,8 @@ pub const DRIVER_LOCAL_TYPE: &str = "local"; pub const TYPE_ROOTFS: &str = "rootfs"; +pub const MOUNT_GUEST_TAG: &str = "kataShared"; + #[rustfmt::skip] lazy_static! { pub static ref FLAGS: HashMap<&'static str, (bool, MsFlags)> = { @@ -383,6 +385,14 @@ async fn nvdimm_storage_handler( fn mount_storage(logger: &Logger, storage: &Storage) -> Result<()> { let logger = logger.new(o!("subsystem" => "mount")); + // Check share before attempting to mount to see if the destination is already a mount point. + // If so, skip doing the mount. This facilitates mounting the sharedfs automatically + // in the guest before the agent service starts. + if storage.source == MOUNT_GUEST_TAG && is_mounted(&storage.mount_point)? { + warn!(logger, "kataShared already mounted, ignoring..."); + return Ok(()); + } + match storage.fstype.as_str() { DRIVER_9P_TYPE | DRIVER_VIRTIOFS_TYPE => { let dest_path = Path::new(storage.mount_point.as_str()); @@ -418,6 +428,24 @@ fn mount_storage(logger: &Logger, storage: &Storage) -> Result<()> { bare_mount.mount() } +/// Looks for `mount_point` entry in the /proc/mounts. +fn is_mounted(mount_point: &str) -> Result { + let mount_point = mount_point.trim_end_matches('/'); + let found = fs::metadata(mount_point).is_ok() + // Looks through /proc/mounts and check if the mount exists + && fs::read_to_string("/proc/mounts")? + .lines() + .any(|line| { + // The 2nd column reveals the mount point. + line.split_whitespace() + .nth(1) + .map(|target| mount_point.eq(target)) + .unwrap_or(false) + }); + + Ok(found) +} + fn parse_mount_flags_and_options(options_vec: Vec<&str>) -> (MsFlags, String) { let mut flags = MsFlags::empty(); let mut options: String = "".to_string(); @@ -897,6 +925,14 @@ mod tests { } } + #[test] + fn test_is_mounted() { + assert!(is_mounted("/proc").unwrap()); + assert!(!is_mounted("").unwrap()); + assert!(!is_mounted("!").unwrap()); + assert!(!is_mounted("/not_existing_path").unwrap()); + } + #[test] fn test_remove_mounts() { skip_if_not_root!();