about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Yziquel <guillaume@vizyon.ai>2024-03-10 20:00:42 +0000
committerBen Kimock <kimockb@gmail.com>2024-03-15 18:31:07 -0400
commit3fc5ed8067f98e2cae8c259a2e367024c59a3ad3 (patch)
treec548d2004c9afb4b5bad8dea1f9c4ce3416e3769
parent5a6c1aa2bccfcbfa42f486a54c09bd698378faef (diff)
downloadrust-3fc5ed8067f98e2cae8c259a2e367024c59a3ad3.tar.gz
rust-3fc5ed8067f98e2cae8c259a2e367024c59a3ad3.zip
Issue 122262: MAP_PRIVATE for more reliability on virtualised filesystems.
Adding support of quirky filesystems occuring in virtualised settings not
having full POSIX support for memory mapped files. Example: current virtiofs
with cache disabled, occuring in Incus/LXD or Kata Containers. Has been
hitting various virtualised filesystems since 2016, depending on their levels
of maturity at the time. The situation will perhaps improve when virtiofs DAX
support patches will have made it into the qemu mainline.

On a reliability level, using the MAP_PRIVATE sycall flag instead of the
MAP_SHARED syscall flag for the mmap() system call does have some undefined
behaviour when the caller update the memory mapping of the mmap()ed file, but
MAP_SHARED does allow not only the calling process but other processes to
modify the memory mapping. Thus, in the current context, using MAP_PRIVATE
copy-on-write is marginally more reliable than MAP_SHARED.

This discussion of reliability is orthogonal to the type system enforced safety
policy of rust, which does not claim to handle memory modification of memory
mapped files triggered through the operating system and not the running rust
process.
-rw-r--r--compiler/rustc_data_structures/src/memmap.rs10
1 files changed, 8 insertions, 2 deletions
diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs
index 30403a61442..c7f66b2fee8 100644
--- a/compiler/rustc_data_structures/src/memmap.rs
+++ b/compiler/rustc_data_structures/src/memmap.rs
@@ -18,8 +18,14 @@ impl Mmap {
     /// However in practice most callers do not ensure this, so uses of this function are likely unsound.
     #[inline]
     pub unsafe fn map(file: File) -> io::Result<Self> {
-        // Safety: the caller must ensure that this is safe.
-        unsafe { memmap2::Mmap::map(&file).map(Mmap) }
+        // By default, memmap2 creates shared mappings, implying that we could see updates to the
+        // file through the mapping. That would violate our precondition; so by requesting a
+        // map_copy_read_only we do not lose anything.
+        // This mapping mode also improves our support for filesystems such as cacheless virtiofs.
+        // For more details see https://github.com/rust-lang/rust/issues/122262
+        //
+        // SAFETY: The caller must ensure that this is safe.
+        unsafe { memmap2::MmapOptions::new().map_copy_read_only(&file).map(Mmap) }
     }
 }