diff --git a/seaweed-volume/src/storage/volume.rs b/seaweed-volume/src/storage/volume.rs index c1c25923b..f1bf8b03b 100644 --- a/seaweed-volume/src/storage/volume.rs +++ b/seaweed-volume/src/storage/volume.rs @@ -513,8 +513,7 @@ impl Volume { .create(true) .open(&dat_path)?; if preallocate > 0 { - file.set_len(preallocate)?; - file.set_len(0)?; // truncate back — the preallocate is just a hint + preallocate_file(&file, preallocate); } self.dat_file = Some(file); } else { @@ -2149,6 +2148,33 @@ pub fn scan_volume_file( Ok(()) } +/// Reserve disk blocks for a file without changing its visible size. +/// On Linux, uses `fallocate(FALLOC_FL_KEEP_SIZE)` to actually reserve blocks. +/// On other platforms, this is a no-op. +fn preallocate_file(file: &File, size: u64) { + #[cfg(target_os = "linux")] + { + use std::os::unix::io::AsRawFd; + let fd = file.as_raw_fd(); + // FALLOC_FL_KEEP_SIZE = 1: allocate blocks without changing file size + let ret = unsafe { libc::fallocate(fd, 1, 0, size as libc::off_t) }; + if ret == 0 { + tracing::info!(bytes = size, "preallocated disk space"); + } else { + tracing::warn!( + bytes = size, + error = %io::Error::last_os_error(), + "fallocate failed" + ); + } + } + #[cfg(not(target_os = "linux"))] + { + let _ = (file, size); + tracing::debug!(bytes = size, "preallocation not supported on this platform"); + } +} + // ============================================================================ // Tests // ============================================================================