diff --git a/src/runtime-rs/crates/resource/src/manager_inner.rs b/src/runtime-rs/crates/resource/src/manager_inner.rs index d1b063060d..8551aab78e 100644 --- a/src/runtime-rs/crates/resource/src/manager_inner.rs +++ b/src/runtime-rs/crates/resource/src/manager_inner.rs @@ -492,17 +492,15 @@ impl ResourceManagerInner { cid: &str, spec: &oci::Spec, ) -> Result>> { + let capabilities = self.hypervisor.capabilities().await?; let ctx = crate::volume::VolumeContext { share_fs: &self.share_fs, d: self.device_manager.as_ref(), sid: &self.sid, agent: self.agent.clone(), emptydir_mode: &self.toml_config.runtime.emptydir_mode, - fs_sharing_supported: self - .hypervisor - .capabilities() - .await? - .is_fs_sharing_supported(), + fs_sharing_supported: capabilities.is_fs_sharing_supported(), + block_device_discard_supported: capabilities.is_block_device_discard_supported(), }; self.volume_resource.handler_volumes(&ctx, cid, spec).await } diff --git a/src/runtime-rs/crates/resource/src/volume/block_emptydir_volume.rs b/src/runtime-rs/crates/resource/src/volume/block_emptydir_volume.rs index a4b74d77b8..da7b9ffbd1 100644 --- a/src/runtime-rs/crates/resource/src/volume/block_emptydir_volume.rs +++ b/src/runtime-rs/crates/resource/src/volume/block_emptydir_volume.rs @@ -60,9 +60,11 @@ impl BlockEmptyDirVolume { m: &oci::Mount, sid: &str, emptydir_mode: &str, + block_device_discard_supported: bool, ) -> Result { let encrypted = emptydir_mode == EMPTYDIR_MODE_BLOCK_ENCRYPTED; - let discard_unmap = emptydir_mode == EMPTYDIR_MODE_BLOCK_PLAIN; + let discard_unmap = + emptydir_mode == EMPTYDIR_MODE_BLOCK_PLAIN && block_device_discard_supported; let source = m .source() .as_ref() @@ -127,7 +129,7 @@ impl BlockEmptyDirVolume { mount.set_typ(Some("bind".to_string())); let mut storage = storage; - configure_block_emptydir_storage(&mut storage, encrypted); + configure_block_emptydir_storage(&mut storage, encrypted, discard_unmap); // Mirror the Go runtime's handleBlkOCIMounts: the agent mounts the // block device at $(spath)/$(b64_device_id) which genpolicy expands to @@ -188,7 +190,11 @@ fn block_emptydir_mount_options(discard_unmap: bool) -> Vec { } } -fn configure_block_emptydir_storage(storage: &mut agent::Storage, encrypted: bool) { +fn configure_block_emptydir_storage( + storage: &mut agent::Storage, + encrypted: bool, + discard_unmap: bool, +) { if encrypted { storage.driver_options.push(format!( "{}={}", @@ -198,7 +204,7 @@ fn configure_block_emptydir_storage(storage: &mut agent::Storage, encrypted: boo storage .driver_options .push(KATA_BLOCK_VOLUME_CREATE_FS.to_string()); - if !encrypted { + if discard_unmap { storage.options.push(DISCARD_MOUNT_OPTION.to_string()); } storage.shared = true; @@ -283,7 +289,7 @@ mod tests { let mut storage = agent::Storage::default(); - configure_block_emptydir_storage(&mut storage, false); + configure_block_emptydir_storage(&mut storage, false, true); assert_eq!( storage.driver_options, @@ -293,6 +299,22 @@ mod tests { assert!(storage.shared); } + #[test] + fn block_plain_emptydir_skips_discard_when_hypervisor_cannot_expose_it() { + assert!(block_emptydir_mount_options(false).is_empty()); + + let mut storage = agent::Storage::default(); + + configure_block_emptydir_storage(&mut storage, false, false); + + assert_eq!( + storage.driver_options, + vec![KATA_BLOCK_VOLUME_CREATE_FS.to_string()] + ); + assert!(storage.options.is_empty()); + assert!(storage.shared); + } + #[test] fn block_encrypted_emptydir_requests_encryption_and_filesystem_creation() { let metadata = block_emptydir_metadata(true, 0); @@ -310,7 +332,7 @@ mod tests { let mut storage = agent::Storage::default(); - configure_block_emptydir_storage(&mut storage, true); + configure_block_emptydir_storage(&mut storage, true, false); assert_eq!( storage.driver_options, diff --git a/src/runtime-rs/crates/resource/src/volume/mod.rs b/src/runtime-rs/crates/resource/src/volume/mod.rs index b2cfc258a0..c8a8c03bb5 100644 --- a/src/runtime-rs/crates/resource/src/volume/mod.rs +++ b/src/runtime-rs/crates/resource/src/volume/mod.rs @@ -39,6 +39,7 @@ pub struct VolumeContext<'a> { pub agent: Arc, pub emptydir_mode: &'a str, pub fs_sharing_supported: bool, + pub block_device_discard_supported: bool, } #[async_trait] @@ -101,9 +102,15 @@ impl VolumeResource { .with_context(|| format!("new ephemeral volume {m:?}"))?, ) } else if block_emptydir_volume::is_block_emptydir_volume(m, emptydir_mode) { - let vol = block_emptydir_volume::BlockEmptyDirVolume::new(d, m, sid, emptydir_mode) - .await - .with_context(|| format!("new block emptydir volume {m:?}"))?; + let vol = block_emptydir_volume::BlockEmptyDirVolume::new( + d, + m, + sid, + emptydir_mode, + ctx.block_device_discard_supported, + ) + .await + .with_context(|| format!("new block emptydir volume {m:?}"))?; let vol_arc: Arc = Arc::new(vol.clone()); let mut inner = self.inner.write().await; inner.ephemeral_disks.push(vol.disk_info);