# HG changeset patch # User Raphaël Gomès # Date 1669635200 -3600 # Node ID be019ac8c1e4b76e56cfec2f89a63fe0103ce72c # Parent f2e13d8d30e094b8694716cd47644e015a3c7642 dirstate-v2: don't mmap the data file when on NFS `mmap` on NFS will trigger a SIGBUS when the mmap'ed file is deleted, which wouldn't work in our case. Also, the performance advantage of using mmap on NFS is debatable at best. diff -r f2e13d8d30e0 -r be019ac8c1e4 rust/hg-core/src/repo.rs --- a/rust/hg-core/src/repo.rs Thu Dec 08 16:38:39 2022 +0100 +++ b/rust/hg-core/src/repo.rs Mon Nov 28 12:33:20 2022 +0100 @@ -320,7 +320,14 @@ .set(Some(docket.uuid.to_owned())); let data_size = docket.data_size(); let metadata = docket.tree_metadata(); - if let Some(data_mmap) = self + if crate::vfs::is_on_nfs_mount(docket.data_filename()) { + // Don't mmap on NFS to prevent `SIGBUS` error on deletion + OwningDirstateMap::new_v2( + self.hg_vfs().read(docket.data_filename())?, + data_size, + metadata, + ) + } else if let Some(data_mmap) = self .hg_vfs() .mmap_open(docket.data_filename()) .io_not_found_as_none()? diff -r f2e13d8d30e0 -r be019ac8c1e4 rust/hg-core/src/vfs.rs --- a/rust/hg-core/src/vfs.rs Thu Dec 08 16:38:39 2022 +0100 +++ b/rust/hg-core/src/vfs.rs Mon Nov 28 12:33:20 2022 +0100 @@ -172,3 +172,24 @@ pub(crate) fn is_file(path: impl AsRef) -> Result { Ok(fs_metadata(path)?.map_or(false, |meta| meta.is_file())) } + +/// Returns whether the given `path` is on a network file system. +/// Taken from `cargo`'s codebase. +#[cfg(target_os = "linux")] +pub(crate) fn is_on_nfs_mount(path: impl AsRef) -> bool { + use std::ffi::CString; + use std::mem; + use std::os::unix::prelude::*; + + let path = match CString::new(path.as_ref().as_os_str().as_bytes()) { + Ok(path) => path, + Err(_) => return false, + }; + + unsafe { + let mut buf: libc::statfs = mem::zeroed(); + let r = libc::statfs(path.as_ptr(), &mut buf); + + r == 0 && buf.f_type as u32 == libc::NFS_SUPER_MAGIC as u32 + } +}