mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-02 07:02:16 +00:00
runtime-rs: plumb block discard unmap
Pass block-device discard support through the runtime-rs QEMU stack. Block device configuration now reaches both QEMU startup and hotplug paths. The backend receives discard=unmap, and virtio-blk frontend devices advertise discard support when requested. The SCSI hotplug path keeps its existing frontend arguments. Signed-off-by: Manuel Huber <manuelh@nvidia.com> Assisted-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
@@ -943,6 +943,7 @@ struct BlockBackend {
|
||||
cache_direct: bool,
|
||||
cache_no_flush: bool,
|
||||
read_only: bool,
|
||||
discard_unmap: bool,
|
||||
}
|
||||
|
||||
impl BlockBackend {
|
||||
@@ -955,6 +956,7 @@ impl BlockBackend {
|
||||
cache_direct,
|
||||
cache_no_flush: false,
|
||||
read_only: true,
|
||||
discard_unmap: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,6 +989,12 @@ impl BlockBackend {
|
||||
self.read_only = read_only;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn set_discard_unmap(&mut self, discard_unmap: bool) -> &mut Self {
|
||||
self.discard_unmap = discard_unmap;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -1012,6 +1020,9 @@ impl ToQemuParams for BlockBackend {
|
||||
} else {
|
||||
params.push("auto-read-only=off".to_owned());
|
||||
}
|
||||
if self.discard_unmap {
|
||||
params.push("discard=unmap".to_owned());
|
||||
}
|
||||
Ok(vec!["-blockdev".to_owned(), params.join(",")])
|
||||
}
|
||||
}
|
||||
@@ -1070,6 +1081,7 @@ struct DeviceVirtioBlk {
|
||||
id: String,
|
||||
config_wce: bool,
|
||||
share_rw: bool,
|
||||
discard: bool,
|
||||
devno: Option<String>,
|
||||
}
|
||||
|
||||
@@ -1080,6 +1092,7 @@ impl DeviceVirtioBlk {
|
||||
id: id.to_owned(),
|
||||
config_wce: false,
|
||||
share_rw: true,
|
||||
discard: false,
|
||||
devno,
|
||||
}
|
||||
}
|
||||
@@ -1095,6 +1108,12 @@ impl DeviceVirtioBlk {
|
||||
self.share_rw = share_rw;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn set_discard(&mut self, discard: bool) -> &mut Self {
|
||||
self.discard = discard;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -1113,6 +1132,9 @@ impl ToQemuParams for DeviceVirtioBlk {
|
||||
} else {
|
||||
params.push("share-rw=off".to_owned());
|
||||
}
|
||||
if self.discard {
|
||||
params.push("discard=on".to_owned());
|
||||
}
|
||||
params.push(format!("serial=image-{}", self.id));
|
||||
if let Some(devno) = &self.devno {
|
||||
params.push(format!("devno={devno}"));
|
||||
@@ -2870,16 +2892,19 @@ impl<'a> QemuCmdLine<'a> {
|
||||
path: &str,
|
||||
is_direct: bool,
|
||||
is_scsi: bool,
|
||||
discard_unmap: bool,
|
||||
) -> Result<()> {
|
||||
self.devices
|
||||
.push(Box::new(BlockBackend::new(device_id, path, is_direct)));
|
||||
let mut backend = BlockBackend::new(device_id, path, is_direct);
|
||||
backend.set_discard_unmap(discard_unmap);
|
||||
self.devices.push(Box::new(backend));
|
||||
let devno = get_devno_ccw(&mut self.ccw_subchannel, device_id);
|
||||
if is_scsi {
|
||||
self.devices
|
||||
.push(Box::new(DeviceScsiHd::new(device_id, "scsi0.0", devno)));
|
||||
} else {
|
||||
self.devices
|
||||
.push(Box::new(DeviceVirtioBlk::new(device_id, bus_type(), devno)));
|
||||
let mut device = DeviceVirtioBlk::new(device_id, bus_type(), devno);
|
||||
device.set_discard(discard_unmap);
|
||||
self.devices.push(Box::new(device));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -3468,3 +3493,32 @@ impl ToQemuParams for SeccompSandbox {
|
||||
Ok(vec!["-sandbox".to_owned(), self.param.clone()])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn contains_param(params: &[String], expected: &str) -> bool {
|
||||
params
|
||||
.iter()
|
||||
.flat_map(|param| param.split(','))
|
||||
.any(|param| param == expected)
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_qemu_block_discard_unmap_params() {
|
||||
let mut backend = BlockBackend::new("blk0", "/tmp/disk.img", true);
|
||||
backend.set_discard_unmap(true);
|
||||
let backend_params = backend.qemu_params().await.unwrap();
|
||||
assert!(contains_param(&backend_params, "discard=unmap"));
|
||||
|
||||
let mut virtio_blk = DeviceVirtioBlk::new("blk0", VirtioBusType::Pci, None);
|
||||
virtio_blk.set_discard(true);
|
||||
let virtio_blk_params = virtio_blk.qemu_params().await.unwrap();
|
||||
assert!(contains_param(&virtio_blk_params, "discard=on"));
|
||||
|
||||
let scsi_hd = DeviceScsiHd::new("blk0", "scsi0.0", None);
|
||||
let scsi_hd_params = scsi_hd.qemu_params().await.unwrap();
|
||||
assert!(!contains_param(&scsi_hd_params, "discard=on"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,7 @@ impl QemuInner {
|
||||
.is_direct
|
||||
.unwrap_or(self.config.blockdev_info.block_device_cache_direct),
|
||||
block_dev.config.driver_option.as_str() == KATA_SCSI_DEV_TYPE,
|
||||
block_dev.config.discard_unmap,
|
||||
)?,
|
||||
unsupported => {
|
||||
info!(sl!(), "unsupported block device driver: {}", unsupported)
|
||||
@@ -1027,6 +1028,7 @@ impl QemuInner {
|
||||
),
|
||||
block_device.config.is_readonly,
|
||||
block_device.config.no_drop,
|
||||
block_device.config.discard_unmap,
|
||||
block_device.config.logical_sector_size,
|
||||
block_device.config.physical_sector_size,
|
||||
&block_device.config.format,
|
||||
@@ -1079,6 +1081,7 @@ impl QemuInner {
|
||||
is_direct,
|
||||
is_readonly,
|
||||
no_drop,
|
||||
discard_unmap,
|
||||
driver,
|
||||
logical_sector_size,
|
||||
physical_sector_size,
|
||||
@@ -1094,6 +1097,7 @@ impl QemuInner {
|
||||
),
|
||||
cfg.is_readonly,
|
||||
cfg.no_drop,
|
||||
cfg.discard_unmap,
|
||||
self.config.blockdev_info.block_device_driver.clone(),
|
||||
cfg.logical_sector_size,
|
||||
cfg.physical_sector_size,
|
||||
@@ -1110,6 +1114,7 @@ impl QemuInner {
|
||||
is_direct,
|
||||
is_readonly,
|
||||
no_drop,
|
||||
discard_unmap,
|
||||
logical_sector_size,
|
||||
physical_sector_size,
|
||||
&BlockDeviceFormat::default(),
|
||||
|
||||
@@ -14,7 +14,7 @@ use kata_types::config::hypervisor::{VIRTIO_BLK_CCW, VIRTIO_SCSI};
|
||||
use kata_types::rootless::is_rootless;
|
||||
use nix::sys::socket::{sendmsg, ControlMessage, MsgFlags};
|
||||
use qapi_qmp::{
|
||||
self as qmp, BlockdevAioOptions, BlockdevOptions, BlockdevOptionsBase,
|
||||
self as qmp, BlockdevAioOptions, BlockdevDiscardOptions, BlockdevOptions, BlockdevOptionsBase,
|
||||
BlockdevOptionsGenericCOWFormat, BlockdevOptionsGenericFormat, BlockdevOptionsRaw, BlockdevRef,
|
||||
MigrationInfo, PciDeviceInfo,
|
||||
};
|
||||
@@ -775,6 +775,7 @@ impl Qmp {
|
||||
is_direct: Option<bool>,
|
||||
is_readonly: bool,
|
||||
no_drop: bool,
|
||||
discard_unmap: bool,
|
||||
logical_block_size: u32,
|
||||
physical_block_size: u32,
|
||||
format: &BlockDeviceFormat,
|
||||
@@ -782,6 +783,7 @@ impl Qmp {
|
||||
) -> Result<(Option<PciPath>, Option<String>)> {
|
||||
// `blockdev-add`
|
||||
let node_name = block_node_name(index);
|
||||
let discard_option = || discard_unmap.then_some(BlockdevDiscardOptions::unmap);
|
||||
|
||||
let create_base_options = || qapi_qmp::BlockdevOptionsBase {
|
||||
auto_read_only: None,
|
||||
@@ -794,7 +796,7 @@ impl Qmp {
|
||||
})
|
||||
},
|
||||
detect_zeroes: None,
|
||||
discard: None,
|
||||
discard: discard_option(),
|
||||
force_share: None,
|
||||
node_name: None,
|
||||
read_only: Some(is_readonly),
|
||||
@@ -832,7 +834,7 @@ impl Qmp {
|
||||
base: BlockdevOptionsBase {
|
||||
detect_zeroes: None,
|
||||
cache: None,
|
||||
discard: None,
|
||||
discard: discard_option(),
|
||||
force_share: if is_readonly { Some(true) } else { None },
|
||||
auto_read_only: None,
|
||||
node_name: Some(node_name.clone()),
|
||||
@@ -857,7 +859,7 @@ impl Qmp {
|
||||
base: BlockdevOptionsBase {
|
||||
detect_zeroes: None,
|
||||
cache: None,
|
||||
discard: None,
|
||||
discard: discard_option(),
|
||||
force_share: Some(true),
|
||||
auto_read_only: None,
|
||||
node_name: Some(node_name.clone()),
|
||||
@@ -882,6 +884,9 @@ impl Qmp {
|
||||
// `device_add`
|
||||
let mut blkdev_add_args = Dictionary::new();
|
||||
blkdev_add_args.insert("drive".to_owned(), node_name.clone().into());
|
||||
if discard_unmap && block_driver != VIRTIO_SCSI {
|
||||
blkdev_add_args.insert("discard".to_owned(), true.into());
|
||||
}
|
||||
|
||||
if logical_block_size > 0 {
|
||||
blkdev_add_args.insert("logical_block_size".to_owned(), logical_block_size.into());
|
||||
|
||||
Reference in New Issue
Block a user