diff --git a/changelog/2555.added.md b/changelog/2555.added.md new file mode 100644 index 0000000000..fee7e93b8c --- /dev/null +++ b/changelog/2555.added.md @@ -0,0 +1 @@ +Add `MremapFlags::MREMAP_DONTUNMAP` to `sys::mman::mremap` for linux target. diff --git a/src/sys/mman.rs b/src/sys/mman.rs index 0524788e55..779e9a2172 100644 --- a/src/sys/mman.rs +++ b/src/sys/mman.rs @@ -205,6 +205,10 @@ libc_bitflags! { /// Place the mapping at exactly the address specified in `new_address`. #[cfg(target_os = "linux")] MREMAP_FIXED; + /// Works in conjunction with `MREMAP_MAYMOVE` but does not unmap `old_address`. + /// Note that, in this case, `old_size` and `new_size` must be the same. + #[cfg(target_os = "linux")] + MREMAP_DONTUNMAP; /// Place the mapping at exactly the address specified in `new_address`. #[cfg(target_os = "netbsd")] MAP_FIXED; diff --git a/test/sys/test_mman.rs b/test/sys/test_mman.rs index 3689f642be..c5116238de 100644 --- a/test/sys/test_mman.rs +++ b/test/sys/test_mman.rs @@ -119,3 +119,40 @@ fn test_mremap_shrink() { // The first KB should still be accessible and have the old data in it. assert_eq!(slice[ONE_K - 1], 0xFF); } + +#[test] +#[cfg(target_os = "linux")] +fn test_mremap_dontunmap() { + use nix::libc::size_t; + use nix::sys::mman::{mremap, MRemapFlags}; + use std::num::NonZeroUsize; + use std::ptr::NonNull; + + const ONE_K: size_t = 1024; + let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap(); + + let slice: &mut [u8] = unsafe { + let mem = mmap_anonymous( + None, + one_k_non_zero, + ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, + MapFlags::MAP_PRIVATE, + ) + .unwrap(); + std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K) + }; + + // because we do not unmap `slice`, `old_size` and `new_size` + // need to be equal or `EINVAL` is set. + let _new_slice: &mut [u8] = unsafe { + let mem = mremap( + NonNull::from(&mut slice[..]).cast(), + ONE_K, + ONE_K, + MRemapFlags::MREMAP_MAYMOVE | MRemapFlags::MREMAP_DONTUNMAP, + None, + ) + .unwrap(); + std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K) + }; +}