runtime-rs: Gate block emptyDir discard by hypervisor capability

Only enable discard for block-plain emptyDir volumes when the
hypervisor reports block device discard support.

The resource manager now queries hypervisor capabilities once and
passes block discard support through VolumeContext. Block emptyDir
volume setup uses that capability to decide whether to add the
discard mount option and related mount metadata, avoiding unsupported
discard mounts on hypervisors that cannot expose discard/unmap to the
guest.

It will correctly adjust the related codes with the new support.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
This commit is contained in:
Alex Lyn
2026-07-13 11:14:40 +08:00
committed by Fabiano Fidêncio
parent 4f28b68af0
commit 89509fd3ea
3 changed files with 41 additions and 14 deletions

View File

@@ -492,17 +492,15 @@ impl ResourceManagerInner {
cid: &str,
spec: &oci::Spec,
) -> Result<Vec<Arc<dyn Volume>>> {
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
}

View File

@@ -60,9 +60,11 @@ impl BlockEmptyDirVolume {
m: &oci::Mount,
sid: &str,
emptydir_mode: &str,
block_device_discard_supported: bool,
) -> Result<Self> {
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<String> {
}
}
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,

View File

@@ -39,6 +39,7 @@ pub struct VolumeContext<'a> {
pub agent: Arc<dyn Agent>,
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<dyn Volume> = Arc::new(vol.clone());
let mut inner = self.inner.write().await;
inner.ephemeral_disks.push(vol.disk_info);