Skip to content

Commit 0335b8a

Browse files
committed
Added snapshot feature for vhost-device-vsock.
There is a hang issue during snapshot disable vring, my solution is to check vring enable/disable status but it requires a new function get_enabled from vring. Signed-off-by: Wei-Chung Hsu <[email protected]>
1 parent d7a67c1 commit 0335b8a

File tree

2 files changed

+84
-5
lines changed

2 files changed

+84
-5
lines changed

vhost-device-vsock/src/vhu_vsock.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
use std::{
44
collections::{HashMap, HashSet},
5-
io::{self, Result as IoResult},
5+
io::{self, Result as IoResult, BufReader, Read},
66
path::PathBuf,
77
sync::{Arc, Mutex, RwLock},
8+
fs::File,
9+
thread::{self, JoinHandle},
810
};
911

1012
use log::warn;
1113
use thiserror::Error as ThisError;
12-
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
14+
use vhost::vhost_user::message::{
15+
VhostTransferStateDirection, VhostTransferStatePhase, VhostUserProtocolFeatures, VhostUserVirtioFeatures
16+
};
1317
use vhost_user_backend::{VhostUserBackend, VringRwLock};
1418
use virtio_bindings::bindings::{
1519
virtio_config::VIRTIO_F_NOTIFY_ON_EMPTY, virtio_config::VIRTIO_F_VERSION_1,
@@ -252,12 +256,27 @@ struct VirtioVsockConfig {
252256
// reading its content from byte array.
253257
unsafe impl ByteValued for VirtioVsockConfig {}
254258

259+
pub(crate) struct HandlerThread {
260+
pub handle: Option<JoinHandle<()>>,
261+
pub created: bool,
262+
}
263+
264+
impl HandlerThread {
265+
pub fn new(handle: Option<JoinHandle<()>>, created: bool) -> Result<Self> {
266+
Ok(Self {
267+
handle: handle,
268+
created: created,
269+
})
270+
}
271+
}
272+
255273
pub(crate) struct VhostUserVsockBackend {
256274
config: VirtioVsockConfig,
257275
queue_size: usize,
258276
pub threads: Vec<Mutex<VhostUserVsockThread>>,
259277
queues_per_thread: Vec<u64>,
260278
pub exit_event: EventFd,
279+
pub handler_thread: Mutex<HandlerThread>,
261280
}
262281

263282
impl VhostUserVsockBackend {
@@ -279,6 +298,7 @@ impl VhostUserVsockBackend {
279298
threads: vec![thread],
280299
queues_per_thread,
281300
exit_event: EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?,
301+
handler_thread: Mutex::new(HandlerThread::new(None, false)?),
282302
})
283303
}
284304
}
@@ -303,7 +323,54 @@ impl VhostUserBackend for VhostUserVsockBackend {
303323
}
304324

305325
fn protocol_features(&self) -> VhostUserProtocolFeatures {
306-
VhostUserProtocolFeatures::MQ | VhostUserProtocolFeatures::CONFIG
326+
VhostUserProtocolFeatures::MQ | VhostUserProtocolFeatures::CONFIG | VhostUserProtocolFeatures::DEVICE_STATE
327+
}
328+
329+
fn set_device_state_fd(
330+
&self,
331+
direction: VhostTransferStateDirection,
332+
phase: VhostTransferStatePhase,
333+
file: File,
334+
) -> IoResult<Option<File>> {
335+
self.handler_thread.lock().unwrap().created = true;
336+
let handle = thread::spawn(move || {
337+
match direction {
338+
SAVE => {
339+
// save
340+
// No device state to save yet, just close the FD.
341+
drop(file);
342+
}
343+
LOAD => {
344+
// load
345+
// No device state to load yet, just verify it is empty.
346+
let mut data = Vec::new();
347+
let mut reader = BufReader::new(file);
348+
if reader.read_to_end(&mut data).is_err() {
349+
println!("vhost-device-vsock loaded device state read failed");
350+
return;
351+
}
352+
353+
if data.len() > 0 {
354+
println!("vhost-device-vsock loaded device state is non-empty. BUG!");
355+
return;
356+
}
357+
}
358+
_ => {
359+
println!("invalid transfer_direction");
360+
return;
361+
}
362+
}
363+
});
364+
self.handler_thread.lock().unwrap().handle = Some(handle);
365+
return Ok(None);
366+
}
367+
368+
fn check_device_state(&self) -> IoResult<()> {
369+
if (self.handler_thread.lock().unwrap().created) {
370+
self.handler_thread.lock().unwrap().created = false;
371+
self.handler_thread.lock().unwrap().handle.take().unwrap().join().unwrap();
372+
}
373+
return Ok(());
307374
}
308375

309376
fn set_event_idx(&self, enabled: bool) {

vhost-device-vsock/src/vhu_vsock_thread.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ impl VhostUserVsockThread {
586586

587587
let mut vring_mut = vring.get_mut();
588588

589+
if !vring_mut.get_enabled() {
590+
return Ok(true);
591+
}
592+
589593
let queue = vring_mut.get_queue_mut();
590594

591595
while let Some(mut avail_desc) = queue
@@ -657,6 +661,8 @@ impl VhostUserVsockThread {
657661
loop {
658662
if !self.thread_backend.pending_rx() {
659663
break;
664+
} else if !vring.get_enabled() {
665+
break;
660666
}
661667
vring.disable_notification().unwrap();
662668

@@ -677,6 +683,8 @@ impl VhostUserVsockThread {
677683
loop {
678684
if !self.thread_backend.pending_raw_pkts() {
679685
break;
686+
} else if !vring.get_enabled() {
687+
break;
680688
}
681689
vring.disable_notification().unwrap();
682690

@@ -722,8 +730,12 @@ impl VhostUserVsockThread {
722730
None => return Err(Error::NoMemoryConfigured),
723731
};
724732

725-
while let Some(mut avail_desc) = vring
726-
.get_mut()
733+
let mut vring_mut = vring.get_mut();
734+
if !vring_mut.get_enabled() {
735+
return Ok(true);
736+
}
737+
738+
while let Some(mut avail_desc) = vring_mut
727739
.get_queue_mut()
728740
.iter(atomic_mem.memory())
729741
.map_err(|_| Error::IterateQueue)?

0 commit comments

Comments
 (0)