From 55f1829e77313166957161e7524931cf1ae8926b Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 2 Jul 2023 16:23:22 +0200 Subject: [PATCH] Call funmap if applicable. --- src/context/memory.rs | 59 +++++++++++++++++++++++-------------------- src/scheme/mod.rs | 3 +++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/context/memory.rs b/src/context/memory.rs index 3d35e577..fbff1be1 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -40,13 +40,28 @@ pub fn map_flags(page_flags: PageFlags<RmmA>) -> MapFlags { pub struct UnmapResult { pub file_desc: Option<GrantFileRef>, + pub size: usize, } -impl Drop for UnmapResult { - fn drop(&mut self) { - if let Some(fd) = self.file_desc.take().and_then(|d| Arc::try_unwrap(d.description).ok()) { - // TODO: Funmap? - let _ = fd.into_inner().try_close(); +impl UnmapResult { + pub fn unmap(mut self) -> Result<()> { + let Some(GrantFileRef { base_offset, description }) = self.file_desc.take() else { + return Ok(()); + }; + + let (scheme_id, number) = match description.write() { + ref desc => (desc.scheme, desc.number), + }; + + let funmap_result = crate::scheme::schemes() + .get(scheme_id).map(Arc::clone).ok_or(Error::new(ENODEV)) + .and_then(|scheme| scheme.kfunmap(number, base_offset, self.size)); + + if let Ok(fd) = Arc::try_unwrap(description) { + fd.into_inner().try_close()?; } + funmap_result?; + + Ok(()) } } @@ -225,33 +240,17 @@ impl AddrSpace { } // Remove irrelevant region - let UnmapResult { ref mut file_desc } = grant.unmap(&mut this.table.utable, &mut flusher); + let unmap_result = grant.unmap(&mut this.table.utable, &mut flusher); // Notify scheme that holds grant - if let Some(file_ref) = file_desc.take() { - notify_files.push((file_ref, intersection)); + if unmap_result.file_desc.is_some() { + notify_files.push(unmap_result); } } drop(self); - for (file_ref, intersection) in notify_files { - let scheme_id = { file_ref.description.read().scheme }; - - let scheme = match crate::scheme::schemes().get(scheme_id) { - Some(scheme) => Arc::clone(scheme), - // One could argue that EBADFD could be returned here, but we have already unmapped - // the memory. - None => continue, - }; - // Same here, we don't really care about errors when schemes respond to unmap events. - // The caller wants the memory to be unmapped, period. When already unmapped, what - // would we do with error codes anyway? - // FIXME - //let _ = scheme.funmap(intersection.base.start_address().data(), intersection.count * PAGE_SIZE); - - if let Ok(desc) = Arc::try_unwrap(file_ref.description) { - let _ = desc.into_inner().try_close(); - } + for unmap_result in notify_files { + let _ = unmap_result.unmap(); } Ok(()) @@ -839,6 +838,7 @@ impl Grant { self.info.flags = flags; } + #[must_use = "will not unmap itself"] pub fn unmap(mut self, mapper: &mut PageMapper, mut flusher: impl Flusher<RmmA>) -> UnmapResult { assert!(self.info.mapped); @@ -873,6 +873,7 @@ impl Grant { let provider = core::mem::replace(&mut self.info.provider, Provider::PhysBorrowed { base: dangling_frame }); UnmapResult { + size: self.info.page_count * PAGE_SIZE, file_desc: match provider { Provider::Allocated { cow_file_ref } => cow_file_ref, Provider::FmapBorrowed { file_ref } => Some(file_ref), @@ -1028,8 +1029,10 @@ impl Drop for AddrSpace { // TODO: Optimize away clearing the actual page tables? Since this address space is no // longer arc-rwlock wrapped, it cannot be referenced `External`ly by borrowing grants, // so it should suffice to iterate over PageInfos and decrement and maybe deallocate - // the underlying pages (and send some funmaps possibly). - grant.unmap(&mut self.table.utable, ()); + // the underlying pages (and send some funmaps). + let res = grant.unmap(&mut self.table.utable, ()); + + let _ = res.unmap(); } } } diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index bda596f7..a9052e4b 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -311,6 +311,9 @@ pub trait KernelScheme: Scheme + Send + Sync + 'static { fn kfmap(&self, number: usize, addr_space: &Arc<RwLock<AddrSpace>>, map: &crate::syscall::data::Map, consume: bool) -> Result<usize> { Err(Error::new(EOPNOTSUPP)) } + fn kfunmap(&self, number: usize, offset: usize, size: usize) -> Result<()> { + Err(Error::new(EOPNOTSUPP)) + } fn kopen(&self, path: &str, flags: usize, caller: CallerCtx) -> Result<OpenResult> { self.open(path, flags, caller.uid, caller.gid).map(OpenResult::SchemeLocal) -- GitLab