Skip to content

Commit e807644

Browse files
committed
vhost-user: honor requested config size and ignore offset
QEMU and Cloud-Hypervisor differ in how they request config: - QEMU always uses offset 0 and may request a smaller, feature-dependent size. - Cloud-Hypervisor uses VHOST_USER_CONFIG_OFFSET (0x100) and always requests the full config size. The vhost-user spec requires the backend response size to exactly match the frontend request. To satisfy both implementations, ignore the offset and return the first N bytes of the config, where N is the requested size. backport of commit 788307c.
1 parent 6b29864 commit e807644

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ jobs:
3737
meson setup build --prefix=/usr/local
3838
meson compile -C build
3939
sudo --preserve-env=PATH,RUSTUP_HOME,CARGO_HOME,HOME meson install -C build
40+
sudo ldconfig
4041
4142
- name: Clone and build isa-l_crypto
4243
run: |

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ubiblk"
3-
version = "0.2.1"
3+
version = "0.2.2"
44
edition = "2021"
55

66
[profile.release]

src/vhost_backend/backend.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use super::{backend_thread::UbiBlkBackendThread, KeyEncryptionCipher, Options};
1919
use crate::block_device::{init_metadata as init_metadata_file, UbiMetadata};
2020
use crate::utils::aligned_buffer::BUFFER_ALIGNMENT;
2121
use crate::Result;
22-
use log::{debug, error, info};
22+
use log::{debug, error, info, warn};
2323
use nix::sys::statfs::statfs;
2424
use std::path::Path;
2525
use vhost::vhost_user::message::*;
@@ -271,8 +271,37 @@ impl VhostUserBackend for UbiBlkBackend {
271271
}
272272
}
273273

274-
fn get_config(&self, _offset: u32, _size: u32) -> Vec<u8> {
275-
self.config.as_slice().to_vec()
274+
fn get_config(&self, _offset: u32, size: u32) -> Vec<u8> {
275+
// 1. QEMU (tag v8.2.2):
276+
// a. sets offset to 0 at vhost_user_get_config
277+
// (hw/virtio/vhost-user.c:2414)
278+
// b. calculates size dynamically based on available features in
279+
// virtio_get_config_size (hw/virtio/virtio.c:2956). This can be
280+
// less than the full config struct size.
281+
// 2. Cloud-Hypervisor (tag v46.0):
282+
// a. sets offset to VHOST_USER_CONFIG_OFFSET (0x100), which is the
283+
// starting position of the device configuration space in virtio
284+
// devices (virtio-devices/src/vhost_user/blk.rs:147)
285+
// b. always sets size to the full config struct size
286+
// (virtio-devices/src/vhost_user/blk.rs:142)
287+
// 3. vhost-user spec's requirement for VHOST_USER_GET_CONFIG:
288+
// > vhost-user back-end’s payload size MUST match the front-end’s
289+
// > request
290+
// Based on above, we ignore the offset and return the first "size"
291+
// bytes of the config struct, which works for both QEMU and
292+
// Cloud-Hypervisor.
293+
let config_bytes = self.config.as_slice();
294+
let requested_size = size as usize;
295+
if size as usize > config_bytes.len() {
296+
warn!(
297+
"get_config requested size {size} exceeds config struct size {}, padding with zeros",
298+
config_bytes.len()
299+
);
300+
}
301+
let mut buf = vec![0u8; requested_size];
302+
let copy_len = std::cmp::min(requested_size, config_bytes.len());
303+
buf[..copy_len].copy_from_slice(&config_bytes[..copy_len]);
304+
buf
276305
}
277306

278307
fn exit_event(&self, thread_index: usize) -> Option<EventFd> {

0 commit comments

Comments
 (0)