diff --git a/iommufd-ioctls/CHANGELOG.md b/iommufd-ioctls/CHANGELOG.md index 7d3860a..a8634a5 100644 --- a/iommufd-ioctls/CHANGELOG.md +++ b/iommufd-ioctls/CHANGELOG.md @@ -3,6 +3,10 @@ ## Changed ## Added +- [[9]](https://github.com/cloud-hypervisor/iommufd/pull/9) Add `Iommufd::destroy_iommu_object` to release iommufd + objects explicitly. +- [[9]](https://github.com/cloud-hypervisor/iommufd/pull/9) Add `Iommufd::new_from_fd` to construct a `Iommufd` from + a pre-opened iommufd file. ## Fixed diff --git a/iommufd-ioctls/src/iommufd_ioctls.rs b/iommufd-ioctls/src/iommufd_ioctls.rs index 921c9c8..b91a4a7 100644 --- a/iommufd-ioctls/src/iommufd_ioctls.rs +++ b/iommufd-ioctls/src/iommufd_ioctls.rs @@ -26,6 +26,20 @@ impl IommuFd { Ok(IommuFd { iommufd }) } + /// New from an already-opened `/dev/iommu` file. Caller transfers + /// ownership; closing the fd is now `IommuFd`'s responsibility. + pub fn new_from_fd(file: File) -> Self { + IommuFd { iommufd: file } + } + + pub fn destroy_iommu_object(&self, id: u32) -> Result<()> { + let destroy_data = iommu_destroy { + size: std::mem::size_of::() as u32, + id, + }; + iommufd_syscall::destroy_iommu_object(self, &destroy_data) + } + pub fn alloc_iommu_ioas(&self, alloc_data: &mut iommu_ioas_alloc) -> Result<()> { iommufd_syscall::alloc_iommu_ioas(self, alloc_data) } @@ -44,6 +58,7 @@ impl AsRawFd for IommuFd { } } +ioctl_io_nr!(IOMMU_DESTROY, IOMMUFD_TYPE as u32, IOMMUFD_CMD_DESTROY); ioctl_io_nr!( IOMMU_IOAS_ALLOC, IOMMUFD_TYPE as u32, @@ -64,6 +79,23 @@ pub(crate) mod iommufd_syscall { use super::*; use vmm_sys_util::ioctl::{ioctl_with_mut_ref, ioctl_with_ref}; + pub(crate) fn destroy_iommu_object( + iommufd: &IommuFd, + destroy_data: &iommu_destroy, + ) -> Result<()> { + // SAFETY: + // 1. The file descriptor provided by 'iommufd' is valid and open. + // 2. The 'destroy_data' points to initialized memory with expected data structure, + // and remains valid for the duration of sysca + // 3. The return value is checked. + let ret = unsafe { ioctl_with_ref(iommufd, IOMMU_DESTROY(), destroy_data) }; + if ret < 0 { + Err(IommufdError::IommuDestroy(SysError::last())) + } else { + Ok(()) + } + } + pub(crate) fn alloc_iommu_ioas( iommufd: &IommuFd, alloc_data: &mut iommu_ioas_alloc, @@ -115,6 +147,7 @@ mod tests { #[test] fn test_iommufd_ioctl_code() { + assert_eq!(IOMMU_DESTROY(), 15232); assert_eq!(IOMMU_IOAS_ALLOC(), 15233); assert_eq!(IOMMU_IOAS_MAP(), 15237); assert_eq!(IOMMU_IOAS_UNMAP(), 15238); diff --git a/iommufd-ioctls/src/lib.rs b/iommufd-ioctls/src/lib.rs index 44475d2..cad0691 100644 --- a/iommufd-ioctls/src/lib.rs +++ b/iommufd-ioctls/src/lib.rs @@ -18,6 +18,8 @@ pub use iommufd_ioctls::*; pub enum IommufdError { #[error("failed to open /dev/iommufd: {0}")] OpenIommufd(#[source] io::Error), + #[error("failed to destroy iommufd object: {0}")] + IommuDestroy(#[source] SysError), #[error("failed to allocate IOAS: {0}")] IommuIoasAlloc(#[source] SysError), #[error("failed to map an IOVA range to the IOAS: {0}")]