mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: vhost_user: Enable snapshot/restore for vhost-user-*
Enable the DEVICE_STATE protocol feature negotiation for all vhost-user devices (block, fs, net, and generic). Restoring the state (including the backend state if present) and vrings. Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -72,6 +72,7 @@ impl Blk {
|
|||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
config,
|
config,
|
||||||
paused,
|
paused,
|
||||||
|
vring_bases,
|
||||||
) = if let Some(state) = state {
|
) = if let Some(state) = state {
|
||||||
info!("Restoring vhost-user-block {id}");
|
info!("Restoring vhost-user-block {id}");
|
||||||
|
|
||||||
@@ -80,6 +81,8 @@ impl Blk {
|
|||||||
state.acked_protocol_features,
|
state.acked_protocol_features,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
vu.restore_state(&state)?;
|
||||||
|
|
||||||
(
|
(
|
||||||
state.avail_features,
|
state.avail_features,
|
||||||
state.acked_features,
|
state.acked_features,
|
||||||
@@ -87,6 +90,7 @@ impl Blk {
|
|||||||
state.vu_num_queues,
|
state.vu_num_queues,
|
||||||
state.config,
|
state.config,
|
||||||
true,
|
true,
|
||||||
|
state.vring_bases,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Filling device and vring features VMM supports.
|
// Filling device and vring features VMM supports.
|
||||||
@@ -111,7 +115,8 @@ impl Blk {
|
|||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK
|
| VhostUserProtocolFeatures::REPLY_ACK
|
||||||
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
||||||
| VhostUserProtocolFeatures::LOG_SHMFD;
|
| VhostUserProtocolFeatures::LOG_SHMFD
|
||||||
|
| VhostUserProtocolFeatures::DEVICE_STATE;
|
||||||
|
|
||||||
let (acked_features, acked_protocol_features) =
|
let (acked_features, acked_protocol_features) =
|
||||||
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
||||||
@@ -160,6 +165,7 @@ impl Blk {
|
|||||||
num_queues,
|
num_queues,
|
||||||
config,
|
config,
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,6 +185,7 @@ impl Blk {
|
|||||||
acked_protocol_features,
|
acked_protocol_features,
|
||||||
socket_path: vu_cfg.socket,
|
socket_path: vu_cfg.socket,
|
||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
|
vring_bases,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ impl Fs {
|
|||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
config,
|
config,
|
||||||
paused,
|
paused,
|
||||||
|
vring_bases,
|
||||||
) = if let Some(state) = state {
|
) = if let Some(state) = state {
|
||||||
info!("Restoring vhost-user-fs {id}");
|
info!("Restoring vhost-user-fs {id}");
|
||||||
|
|
||||||
@@ -109,6 +110,8 @@ impl Fs {
|
|||||||
state.acked_protocol_features,
|
state.acked_protocol_features,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
vu.restore_state(&state)?;
|
||||||
|
|
||||||
(
|
(
|
||||||
state.avail_features,
|
state.avail_features,
|
||||||
state.acked_features,
|
state.acked_features,
|
||||||
@@ -116,6 +119,7 @@ impl Fs {
|
|||||||
state.vu_num_queues,
|
state.vu_num_queues,
|
||||||
state.config,
|
state.config,
|
||||||
true,
|
true,
|
||||||
|
state.vring_bases,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Filling device and vring features VMM supports.
|
// Filling device and vring features VMM supports.
|
||||||
@@ -125,7 +129,8 @@ impl Fs {
|
|||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK
|
| VhostUserProtocolFeatures::REPLY_ACK
|
||||||
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
||||||
| VhostUserProtocolFeatures::LOG_SHMFD;
|
| VhostUserProtocolFeatures::LOG_SHMFD
|
||||||
|
| VhostUserProtocolFeatures::DEVICE_STATE;
|
||||||
|
|
||||||
let (acked_features, acked_protocol_features) =
|
let (acked_features, acked_protocol_features) =
|
||||||
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
||||||
@@ -168,6 +173,7 @@ impl Fs {
|
|||||||
num_queues,
|
num_queues,
|
||||||
config,
|
config,
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,6 +193,7 @@ impl Fs {
|
|||||||
acked_protocol_features,
|
acked_protocol_features,
|
||||||
socket_path: path.to_string(),
|
socket_path: path.to_string(),
|
||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
|
vring_bases,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -68,64 +68,74 @@ impl GenericVhostUser {
|
|||||||
// Connect to the vhost-user socket.
|
// Connect to the vhost-user socket.
|
||||||
let mut vu = VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false)?;
|
let mut vu = VhostUserHandle::connect_vhost_user(false, path, num_queues as u64, false)?;
|
||||||
|
|
||||||
let (avail_features, acked_features, acked_protocol_features, vu_num_queues, paused) =
|
let (
|
||||||
if let Some(state) = state {
|
avail_features,
|
||||||
info!("Restoring generic vhost-user {id}");
|
acked_features,
|
||||||
vu.set_protocol_features_vhost_user(
|
acked_protocol_features,
|
||||||
state.acked_features,
|
vu_num_queues,
|
||||||
state.acked_protocol_features,
|
paused,
|
||||||
)?;
|
vring_bases,
|
||||||
|
) = if let Some(state) = state {
|
||||||
|
info!("Restoring generic vhost-user {id}");
|
||||||
|
vu.set_protocol_features_vhost_user(
|
||||||
|
state.acked_features,
|
||||||
|
state.acked_protocol_features,
|
||||||
|
)?;
|
||||||
|
|
||||||
(
|
vu.restore_state(&state)?;
|
||||||
state.avail_features,
|
|
||||||
state.acked_features,
|
|
||||||
state.acked_protocol_features,
|
|
||||||
state.vu_num_queues,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let avail_protocol_features = VhostUserProtocolFeatures::CONFIG
|
|
||||||
| VhostUserProtocolFeatures::MQ
|
|
||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK
|
|
||||||
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
|
||||||
| VhostUserProtocolFeatures::LOG_SHMFD;
|
|
||||||
|
|
||||||
let avail_features = super::DEFAULT_VIRTIO_FEATURES;
|
(
|
||||||
|
state.avail_features,
|
||||||
|
state.acked_features,
|
||||||
|
state.acked_protocol_features,
|
||||||
|
state.vu_num_queues,
|
||||||
|
true,
|
||||||
|
state.vring_bases,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let avail_protocol_features = VhostUserProtocolFeatures::CONFIG
|
||||||
|
| VhostUserProtocolFeatures::MQ
|
||||||
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
|
| VhostUserProtocolFeatures::REPLY_ACK
|
||||||
|
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
||||||
|
| VhostUserProtocolFeatures::LOG_SHMFD
|
||||||
|
| VhostUserProtocolFeatures::DEVICE_STATE;
|
||||||
|
|
||||||
let (acked_features, acked_protocol_features) =
|
let avail_features = super::DEFAULT_VIRTIO_FEATURES;
|
||||||
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
|
||||||
|
|
||||||
let backend_num_queues =
|
let (acked_features, acked_protocol_features) =
|
||||||
if acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
||||||
vu.socket_handle()
|
|
||||||
.get_queue_num()
|
|
||||||
.map_err(Error::VhostUserGetQueueMaxNum)?
|
|
||||||
as usize
|
|
||||||
} else {
|
|
||||||
num_queues
|
|
||||||
};
|
|
||||||
|
|
||||||
if num_queues > backend_num_queues {
|
let backend_num_queues =
|
||||||
error!(
|
if acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() != 0 {
|
||||||
"generic vhost-user requested too many queues ({num_queues}) \
|
vu.socket_handle()
|
||||||
|
.get_queue_num()
|
||||||
|
.map_err(Error::VhostUserGetQueueMaxNum)? as usize
|
||||||
|
} else {
|
||||||
|
num_queues
|
||||||
|
};
|
||||||
|
|
||||||
|
if num_queues > backend_num_queues {
|
||||||
|
error!(
|
||||||
|
"generic vhost-user requested too many queues ({num_queues}) \
|
||||||
since the backend only supports {backend_num_queues}\n",
|
since the backend only supports {backend_num_queues}\n",
|
||||||
);
|
);
|
||||||
return Err(Error::BadQueueNum);
|
return Err(Error::BadQueueNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
acked_features,
|
acked_features,
|
||||||
// If part of the available features that have been acked, the
|
// If part of the available features that have been acked, the
|
||||||
// PROTOCOL_FEATURES bit must be already set through the VIRTIO
|
// PROTOCOL_FEATURES bit must be already set through the VIRTIO
|
||||||
// acked features as we know the guest would never ack it, thus
|
// acked features as we know the guest would never ack it, thus
|
||||||
// the feature would be lost.
|
// the feature would be lost.
|
||||||
acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(),
|
acked_features & VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(),
|
||||||
acked_protocol_features,
|
acked_protocol_features,
|
||||||
num_queues,
|
num_queues,
|
||||||
false,
|
false,
|
||||||
)
|
None,
|
||||||
};
|
)
|
||||||
|
};
|
||||||
|
|
||||||
Ok(GenericVhostUser {
|
Ok(GenericVhostUser {
|
||||||
common: VirtioCommon {
|
common: VirtioCommon {
|
||||||
@@ -143,6 +153,7 @@ since the backend only supports {backend_num_queues}\n",
|
|||||||
acked_protocol_features,
|
acked_protocol_features,
|
||||||
socket_path: path.to_string(),
|
socket_path: path.to_string(),
|
||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
|
vring_bases,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ impl Net {
|
|||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
config,
|
config,
|
||||||
paused,
|
paused,
|
||||||
|
vring_bases,
|
||||||
) = if let Some(state) = state {
|
) = if let Some(state) = state {
|
||||||
info!("Restoring vhost-user-net {id}");
|
info!("Restoring vhost-user-net {id}");
|
||||||
|
|
||||||
@@ -95,6 +96,8 @@ impl Net {
|
|||||||
state.acked_protocol_features,
|
state.acked_protocol_features,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
vu.restore_state(&state)?;
|
||||||
|
|
||||||
// If the control queue feature has been negotiated, let's
|
// If the control queue feature has been negotiated, let's
|
||||||
// increase the number of queues.
|
// increase the number of queues.
|
||||||
if state.acked_features & (1 << VIRTIO_NET_F_CTRL_VQ) != 0 {
|
if state.acked_features & (1 << VIRTIO_NET_F_CTRL_VQ) != 0 {
|
||||||
@@ -108,6 +111,7 @@ impl Net {
|
|||||||
state.vu_num_queues,
|
state.vu_num_queues,
|
||||||
state.config,
|
state.config,
|
||||||
true,
|
true,
|
||||||
|
state.vring_bases,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Filling device and vring features VMM supports.
|
// Filling device and vring features VMM supports.
|
||||||
@@ -144,7 +148,8 @@ impl Net {
|
|||||||
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
| VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS
|
||||||
| VhostUserProtocolFeatures::REPLY_ACK
|
| VhostUserProtocolFeatures::REPLY_ACK
|
||||||
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
| VhostUserProtocolFeatures::INFLIGHT_SHMFD
|
||||||
| VhostUserProtocolFeatures::LOG_SHMFD;
|
| VhostUserProtocolFeatures::LOG_SHMFD
|
||||||
|
| VhostUserProtocolFeatures::DEVICE_STATE;
|
||||||
|
|
||||||
let (mut acked_features, acked_protocol_features) =
|
let (mut acked_features, acked_protocol_features) =
|
||||||
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
|
||||||
@@ -187,6 +192,7 @@ impl Net {
|
|||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
config,
|
config,
|
||||||
false,
|
false,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -208,6 +214,7 @@ impl Net {
|
|||||||
socket_path: vu_cfg.socket,
|
socket_path: vu_cfg.socket,
|
||||||
vu_num_queues,
|
vu_num_queues,
|
||||||
server,
|
server,
|
||||||
|
vring_bases,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
config,
|
config,
|
||||||
|
|||||||
Reference in New Issue
Block a user