mirror of https://github.com/zkat/cacache-rs.git
fix(mmap): pre-allocate temp file before mmapping
This avoids SIGBUS on memory write in case the temp file is sparse. Implemented for linux only; other target_os cfg values unchanged.
This commit is contained in:
parent
58de0b2d10
commit
f0cb8a4520
|
|
@ -16,6 +16,7 @@ digest = "0.10.6"
|
|||
either = "1.6.1"
|
||||
futures = "0.3.17"
|
||||
hex = "0.4.3"
|
||||
libc = "0.2.144"
|
||||
memmap2 = { version = "0.5.8", optional = true }
|
||||
miette = "5.7.0"
|
||||
reflink = "0.1.3"
|
||||
|
|
|
|||
|
|
@ -413,21 +413,44 @@ impl AsyncWriter {
|
|||
#[cfg(feature = "mmap")]
|
||||
fn make_mmap(tmpfile: &mut NamedTempFile, size: Option<usize>) -> Result<Option<MmapMut>> {
|
||||
if let Some(size @ 0..=MAX_MMAP_SIZE) = size {
|
||||
tmpfile
|
||||
.as_file_mut()
|
||||
.set_len(size as u64)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Failed to configure file length for temp file at {}",
|
||||
tmpfile.path().display()
|
||||
)
|
||||
})?;
|
||||
allocate_file(tmpfile.as_file(), size).with_context(|| {
|
||||
format!(
|
||||
"Failed to configure file length for temp file at {}",
|
||||
tmpfile.path().display()
|
||||
)
|
||||
})?;
|
||||
Ok(unsafe { MmapMut::map_mut(tmpfile.as_file()).ok() })
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mmap")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn allocate_file(file: &std::fs::File, size: usize) -> std::io::Result<()> {
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
let fd = file.as_raw_fd();
|
||||
match unsafe { libc::posix_fallocate64(fd, 0, size as i64) } {
|
||||
0 => Ok(()),
|
||||
libc::ENOSPC => Err(Error::new(
|
||||
ErrorKind::Other, // ErrorKind::StorageFull is unstable
|
||||
"cannot allocate file: no space left on device",
|
||||
)),
|
||||
err => Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("posix_fallocate64 failed with code {err}"),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mmap")]
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn allocate_file(file: &std::fs::File, size: usize) -> std::io::Result<()> {
|
||||
file.set_len(size as u64)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "mmap"))]
|
||||
fn make_mmap(_: &mut NamedTempFile, _: Option<usize>) -> Result<Option<MmapMut>> {
|
||||
Ok(None)
|
||||
|
|
|
|||
Loading…
Reference in New Issue