vhost_user: Add support for REM_MEM_REG
Adding support for a new message REM_MEM_REG. This command request an existing memory region to be removed and unmapped from the vhost-user backend. It is designed for supporting memory hot-unplug, rather than using SET_MEM_TABLE, which is less efficient as it would remap all remaining regions. It is only available if the protocol feature VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS has been negotiated. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
7e3ab1af4e
commit
ee3e872270
5 changed files with 52 additions and 1 deletions
|
|
@ -1 +1 @@
|
|||
{"coverage_score": 81.3, "exclude_path": "src/vhost_kern/", "crate_features": "vhost-user-master,vhost-user-slave"}
|
||||
{"coverage_score": 81.2, "exclude_path": "src/vhost_kern/", "crate_features": "vhost-user-master,vhost-user-slave"}
|
||||
|
|
|
|||
|
|
@ -252,4 +252,8 @@ impl VhostUserSlaveReqHandlerMut for DummySlaveReqHandler {
|
|||
fn add_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion, _fd: RawFd) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_mem_region(&mut self, _region: &VhostUserSingleMemoryRegion) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ pub trait VhostUserMaster: VhostBackend {
|
|||
|
||||
/// Add a new guest memory mapping for vhost to use.
|
||||
fn add_mem_region(&mut self, region: &VhostUserMemoryRegionInfo) -> Result<()>;
|
||||
|
||||
/// Remove a guest memory mapping from vhost.
|
||||
fn remove_mem_region(&mut self, region: &VhostUserMemoryRegionInfo) -> Result<()>;
|
||||
}
|
||||
|
||||
fn error_code<T>(err: VhostUserError) -> Result<T> {
|
||||
|
|
@ -475,6 +478,26 @@ impl VhostUserMaster for Master {
|
|||
let hdr = node.send_request_with_body(MasterReq::ADD_MEM_REG, &body, Some(&fds))?;
|
||||
node.wait_for_ack(&hdr).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn remove_mem_region(&mut self, region: &VhostUserMemoryRegionInfo) -> Result<()> {
|
||||
let mut node = self.node();
|
||||
if node.acked_protocol_features & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits() == 0
|
||||
{
|
||||
return error_code(VhostUserError::InvalidOperation);
|
||||
}
|
||||
if region.memory_size == 0 {
|
||||
return error_code(VhostUserError::InvalidParam);
|
||||
}
|
||||
|
||||
let body = VhostUserSingleMemoryRegion::new(
|
||||
region.guest_phys_addr,
|
||||
region.memory_size,
|
||||
region.userspace_addr,
|
||||
region.mmap_offset,
|
||||
);
|
||||
let hdr = node.send_request_with_body(MasterReq::REM_MEM_REG, &body, None)?;
|
||||
node.wait_for_ack(&hdr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Master {
|
||||
|
|
|
|||
|
|
@ -341,6 +341,9 @@ mod tests {
|
|||
// add_mem_region()
|
||||
slave.handle_request().unwrap();
|
||||
|
||||
// remove_mem_region()
|
||||
slave.handle_request().unwrap();
|
||||
|
||||
sbar.wait();
|
||||
});
|
||||
|
||||
|
|
@ -416,6 +419,8 @@ mod tests {
|
|||
};
|
||||
master.add_mem_region(®ion).unwrap();
|
||||
|
||||
master.remove_mem_region(®ion).unwrap();
|
||||
|
||||
mbar.wait();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ pub trait VhostUserSlaveReqHandler {
|
|||
fn set_slave_req_fd(&self, _vu_req: SlaveFsCacheReq) {}
|
||||
fn get_max_mem_slots(&self) -> Result<u64>;
|
||||
fn add_mem_region(&self, region: &VhostUserSingleMemoryRegion, fd: RawFd) -> Result<()>;
|
||||
fn remove_mem_region(&self, region: &VhostUserSingleMemoryRegion) -> Result<()>;
|
||||
}
|
||||
|
||||
/// Services provided to the master by the slave without interior mutability.
|
||||
|
|
@ -106,6 +107,7 @@ pub trait VhostUserSlaveReqHandlerMut {
|
|||
fn set_slave_req_fd(&mut self, _vu_req: SlaveFsCacheReq) {}
|
||||
fn get_max_mem_slots(&mut self) -> Result<u64>;
|
||||
fn add_mem_region(&mut self, region: &VhostUserSingleMemoryRegion, fd: RawFd) -> Result<()>;
|
||||
fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()>;
|
||||
}
|
||||
|
||||
impl<T: VhostUserSlaveReqHandlerMut> VhostUserSlaveReqHandler for Mutex<T> {
|
||||
|
|
@ -202,6 +204,10 @@ impl<T: VhostUserSlaveReqHandlerMut> VhostUserSlaveReqHandler for Mutex<T> {
|
|||
fn add_mem_region(&self, region: &VhostUserSingleMemoryRegion, fd: RawFd) -> Result<()> {
|
||||
self.lock().unwrap().add_mem_region(region, fd)
|
||||
}
|
||||
|
||||
fn remove_mem_region(&self, region: &VhostUserSingleMemoryRegion) -> Result<()> {
|
||||
self.lock().unwrap().remove_mem_region(region)
|
||||
}
|
||||
}
|
||||
|
||||
/// Server to handle service requests from masters from the master communication channel.
|
||||
|
|
@ -462,6 +468,19 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||
let res = self.backend.add_mem_region(&msg, fd);
|
||||
self.send_ack_message(&hdr, res)?;
|
||||
}
|
||||
MasterReq::REM_MEM_REG => {
|
||||
if self.acked_protocol_features
|
||||
& VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
|
||||
== 0
|
||||
{
|
||||
return Err(Error::InvalidOperation);
|
||||
}
|
||||
|
||||
let msg =
|
||||
self.extract_request_body::<VhostUserSingleMemoryRegion>(&hdr, size, &buf)?;
|
||||
let res = self.backend.remove_mem_region(&msg);
|
||||
self.send_ack_message(&hdr, res)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::InvalidMessage);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue