summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien Boeuf <sebastien.boeuf@intel.com>2021-03-05 10:34:14 +0100
committerJiang Liu <gerry@linux.alibaba.com>2021-03-10 23:37:29 +0800
commitee3e8722706c984b3dfe12d3a130e92101b78e8f (patch)
treee26b739a1df9fd4a9fa2934d159ca0f0b632a120
parent7e3ab1af4e1c2157e206798683b64eb384c3693a (diff)
downloadvmm_vhost-ee3e8722706c984b3dfe12d3a130e92101b78e8f.tar.gz
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>
-rw-r--r--coverage_config_x86_64.json2
-rw-r--r--src/vhost_user/dummy_slave.rs4
-rw-r--r--src/vhost_user/master.rs23
-rw-r--r--src/vhost_user/mod.rs5
-rw-r--r--src/vhost_user/slave_req_handler.rs19
5 files changed, 52 insertions, 1 deletions
diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json
index a4ed64f..2b2c164 100644
--- a/coverage_config_x86_64.json
+++ b/coverage_config_x86_64.json
@@ -1 +1 @@
-{"coverage_score": 81.3, "exclude_path": "src/vhost_kern/", "crate_features": "vhost-user-master,vhost-user-slave"} \ No newline at end of file
+{"coverage_score": 81.2, "exclude_path": "src/vhost_kern/", "crate_features": "vhost-user-master,vhost-user-slave"}
diff --git a/src/vhost_user/dummy_slave.rs b/src/vhost_user/dummy_slave.rs
index 895537b..b2b83d2 100644
--- a/src/vhost_user/dummy_slave.rs
+++ b/src/vhost_user/dummy_slave.rs
@@ -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(())
+ }
}
diff --git a/src/vhost_user/master.rs b/src/vhost_user/master.rs
index d27e4fb..227f1d7 100644
--- a/src/vhost_user/master.rs
+++ b/src/vhost_user/master.rs
@@ -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 {
diff --git a/src/vhost_user/mod.rs b/src/vhost_user/mod.rs
index 3158436..4e1b529 100644
--- a/src/vhost_user/mod.rs
+++ b/src/vhost_user/mod.rs
@@ -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(&region).unwrap();
+ master.remove_mem_region(&region).unwrap();
+
mbar.wait();
}
diff --git a/src/vhost_user/slave_req_handler.rs b/src/vhost_user/slave_req_handler.rs
index 3d8d6d5..18459a2 100644
--- a/src/vhost_user/slave_req_handler.rs
+++ b/src/vhost_user/slave_req_handler.rs
@@ -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);
}