From 818fc072662b23ba5325fb9e6a52b580f7d94682 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Wed, 8 Jul 2026 12:18:58 -0700 Subject: [PATCH] vmm: config: Fix generic vhost-user parsing The generic vhost-user device took its virtio device type on the command line via the `virtio_id` parameter, but the same value is called `device_type` in the API and the resulting config struct. This irregularity was due to churn during the review process, `device_type` was the intended name. Accept `device_type` on the command line and keep `virtio_id` as a deprecated alias that logs a warning. The alias will then be removed in a later release. Fixes: #8545 Assisted-by: Claude:Opus-4.8 Signed-off-by: Rob Bradford --- .../tests/common/tests_wrappers.rs | 4 +-- docs/generic-vhost-user.md | 4 +-- vmm/src/config.rs | 36 ++++++++++++++----- vmm/src/lib.rs | 2 +- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/cloud-hypervisor/tests/common/tests_wrappers.rs b/cloud-hypervisor/tests/common/tests_wrappers.rs index 6e177ff83..d88e6d139 100644 --- a/cloud-hypervisor/tests/common/tests_wrappers.rs +++ b/cloud-hypervisor/tests/common/tests_wrappers.rs @@ -957,7 +957,7 @@ pub(crate) fn _test_virtio_fs( "socket={},id=myfs0,{}{}", virtiofsd_socket_path, if use_generic_vhost_user { - "queue_sizes=[1024,1024],virtio_id=26" + "queue_sizes=[1024,1024],device_type=26" } else { "tag=myfs,num_queues=1,queue_size=1024" }, @@ -1090,7 +1090,7 @@ pub(crate) fn _test_virtio_fs( "id=myfs0,socket={},{}{}", virtiofsd_socket_path, if use_generic_vhost_user { - "queue_sizes=[1024,1024],virtio_id=26" + "queue_sizes=[1024,1024],device_type=26" } else { "tag=myfs,num_queues=1,queue_size=1024" }, diff --git a/docs/generic-vhost-user.md b/docs/generic-vhost-user.md index 6af813e28..5d68de708 100644 --- a/docs/generic-vhost-user.md +++ b/docs/generic-vhost-user.md @@ -43,14 +43,14 @@ similar to this: --disk path=your-linux-image.iso \ --kernel vmlinux \ --cmdline "console=hvc0 root=/dev/vda1 rw" \ - --generic-vhost-user "socket=\"${path_to_virtiofsd_socket//\"/\"\"}\",virtio_id=26,queue_sizes=[512,512]" \ + --generic-vhost-user "socket=\"${path_to_virtiofsd_socket//\"/\"\"}\",device_type=26,queue_sizes=[512,512]" \ "${other_cloud_hypervisor_options[@]}" ``` 26 is the ID for a virtio-fs device. The IDs for other devices are defined by the VIRTIO specification. The odd-looking variable expansion escapes any double quotes in the socket path. It is also possible to provide -the name that is defined by the virtio specification, so `virtio_id=fs` +the name that is defined by the virtio specification, so `device_type=fs` will also work. Inside the guest, you can mount the virtio-fs device with diff --git a/vmm/src/config.rs b/vmm/src/config.rs index dbd0d2a5e..900fd3173 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -53,14 +53,14 @@ pub enum Error { /// Filesystem socket is missing #[error("Error parsing --fs: socket missing")] ParseFsSockMissing, - /// Generic vhost-user virtio ID is invalid + /// Generic vhost-user device type is invalid #[error( - "Error parsing --generic-vhost-user: virtio ID {0:?} invalid (leading zeros or unknown string)" + "Error parsing --generic-vhost-user: device_type {0:?} invalid (leading zeros or unknown string)" )] ParseGenericVhostUserVirtioIdInvalid(String), - /// Generic vhost-user virtio ID is unsupported + /// Generic vhost-user device type is unsupported #[error( - "Error parsing --generic-vhost-user: device with virtio ID {0:?} cannot be implemented via vhost-user" + "Error parsing --generic-vhost-user: device with device_type {0:?} cannot be implemented via vhost-user" )] ParseGenericVhostUserVirtioIdUnsupported(String), /// Generic vhost-user socket is missing @@ -69,8 +69,8 @@ pub enum Error { /// Generic vhost-user number of queues is missing #[error("Error parsing --generic-vhost-user: number of queues missing")] ParseGenericVhostUserNumResponseQueuesMissing, - /// Generic vhost-user virtio ID is missing - #[error("Error parsing --generic-vhost-user: virtio ID missing")] + /// Generic vhost-user device type is missing + #[error("Error parsing --generic-vhost-user: device_type missing")] ParseGenericVhostUserVirtioIdMissing, /// Generic vhost-user available features is missing #[error("Error parsing --generic-vhost-user: available features missing")] @@ -1998,7 +1998,7 @@ impl BalloonConfig { impl GenericVhostUserConfig { pub const SYNTAX: &'static str = "generic vhost-user parameters \ - \"virtio_id=,\ + \"device_type=,\ socket=,\ queue_sizes=,\ id=,pci_segment=,pci_device_id=\""; @@ -2006,6 +2006,8 @@ impl GenericVhostUserConfig { pub fn parse(vhost_user: &str) -> Result { let mut parser = OptionParser::new(); parser + .add("device_type") + // TODO: Remove 'virtio_id' as a deprecated alias for 'device_type' .add("virtio_id") .add("queue_sizes") .add("socket") @@ -2022,9 +2024,16 @@ impl GenericVhostUserConfig { .convert::>("queue_sizes") .map_err(Error::ParseGenericVhostUser)? .ok_or(Error::ParseGenericVhostUserQueueSizeMissing)?; - let device_type_str = parser + let legacy_virtio_id = parser .convert::("virtio_id") + .map_err(Error::ParseGenericVhostUser)?; + if legacy_virtio_id.is_some() { + warn!("'virtio_id' in --generic-vhost-user is deprecated; use 'device_type'."); + } + let device_type_str = parser + .convert::("device_type") .map_err(Error::ParseGenericVhostUser)? + .or(legacy_virtio_id) .ok_or(Error::ParseGenericVhostUserVirtioIdMissing)?; let device_type = match device_type_str.as_bytes() { b"net" => VIRTIO_ID_NET, @@ -4583,7 +4592,7 @@ mod unit_tests { assert!(!socket.contains(",[]\n\r\0\"")); assert!(!id.contains(",[]\n\r\0\"")); let config = GenericVhostUserConfig::parse(&format!( - "virtio_id={virtio_id},socket=\"{socket}\",\ + "device_type={virtio_id},socket=\"{socket}\",\ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" )); if pci_segment <= u16::MAX.into() @@ -4658,6 +4667,15 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}" 10, &IntegerList(vec![20u64]), ); + + // The deprecated 'virtio_id' key is an alias for 'device_type' and must + // parse to an identical configuration. + assert_eq!( + GenericVhostUserConfig::parse("virtio_id=26,socket=/tmp/sock,queue_sizes=[1024]") + .unwrap(), + GenericVhostUserConfig::parse("device_type=26,socket=/tmp/sock,queue_sizes=[1024]") + .unwrap(), + ); Ok(()) } diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 38434f208..1af7022b2 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -3590,7 +3590,7 @@ mod unit_tests { fn test_vmm_vm_cold_add_generic_vhost_user() { let mut vmm = create_dummy_vmm(); let generic_vhost_user_config = - GenericVhostUserConfig::parse("virtio_id=26,socket=/tmp/sock,queue_sizes=[1024]") + GenericVhostUserConfig::parse("device_type=26,socket=/tmp/sock,queue_sizes=[1024]") .unwrap(); assert!(matches!(