(
&mut self,
device_cfg: &mut UserDeviceConfig,
)
| 4647 | } |
| 4648 | |
| 4649 | pub fn add_user_device( |
| 4650 | &mut self, |
| 4651 | device_cfg: &mut UserDeviceConfig, |
| 4652 | ) -> DeviceManagerResult<PciDeviceInfo> { |
| 4653 | self.validate_identifier(&device_cfg.pci_common.id)?; |
| 4654 | |
| 4655 | // Reject duplicate socket up-front: libvfio-user servers accept a |
| 4656 | // single client, so a second Client::new() on the same socket blocks |
| 4657 | // indefinitely in the handshake recvmsg() and hangs the VMM thread. |
| 4658 | if let Some(existing) = &self.config.lock().unwrap().user_devices |
| 4659 | && existing.iter().any(|d| d.socket == device_cfg.socket) |
| 4660 | { |
| 4661 | return Err(DeviceManagerError::UserDeviceSocketInUse( |
| 4662 | device_cfg.socket.clone(), |
| 4663 | )); |
| 4664 | } |
| 4665 | |
| 4666 | let (bdf, device_name) = self.add_vfio_user_device(device_cfg)?; |
| 4667 | |
| 4668 | // Update the PCIU bitmap |
| 4669 | self.pci_segments[device_cfg.pci_common.pci_segment as usize].pci_devices_up |= |
| 4670 | 1 << bdf.device(); |
| 4671 | |
| 4672 | Ok(PciDeviceInfo { |
| 4673 | id: device_name, |
| 4674 | bdf, |
| 4675 | }) |
| 4676 | } |
| 4677 | |
| 4678 | pub fn remove_device(&mut self, id: &str) -> DeviceManagerResult<()> { |
| 4679 | // The node can be directly a PCI node in case the 'id' refers to a |
nothing calls this directly
no test coverage detected