From 69ac9d9a5e2a9bfd42bda5b6d20f1d6121d95606 Mon Sep 17 00:00:00 2001 From: Lucas Lersch Date: Wed, 4 Mar 2026 06:39:16 -0800 Subject: [PATCH] Zero trimmed ranges under verifier flags to make Trim() observable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Linux with ext4/xfs, fallocate(FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE) causes reads from the punched range to return zeros, so Trim() is already observable there. On macOS, Windows, tmpfs, NFS, and filesystems that do not support PUNCH_HOLE, Trim() returns false and does nothing — meaning the trim path is effectively untested in most CI environments. Under DUCKDB_RUN_SLOW_VERIFIERS or DUCKDB_ALTERNATIVE_VERIFY, explicitly zero the trimmed range with Write() before attempting fallocate. This makes Trim() observable everywhere: any code that reads a trimmed block will see zeros regardless of the underlying filesystem or OS. The two flags are triggered independently and serve different purposes: - DUCKDB_RUN_SLOW_VERIFIERS enables additive extra verification on top of the production code path. Zeroing fits here because it turns a silent no-op (on non-Linux or unsupporting filesystems) into a detectable operation without changing what the production path does. - DUCKDB_ALTERNATIVE_VERIFY selects alternative implementations of the same operation. Zeroing is precisely an alternative implementation of trim: it achieves the same observable effect as PUNCH_HOLE (reads from trimmed blocks return zeros) through explicit writes rather than a kernel hole-punching syscall. The two blocks are independent: on Linux with glibc >= 2.18, both the zeroing and the fallocate execute, exercising the production code path while still making the result observable. --- src/common/local_file_system.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/common/local_file_system.cpp b/src/common/local_file_system.cpp index db5352f9e75e..c7364d21ffb7 100644 --- a/src/common/local_file_system.cpp +++ b/src/common/local_file_system.cpp @@ -571,19 +571,24 @@ int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_byte } bool LocalFileSystem::Trim(FileHandle &handle, idx_t offset_bytes, idx_t length_bytes) { + bool trimmed = false; +#if defined(DUCKDB_RUN_SLOW_VERIFIERS) || defined(DUCKDB_ALTERNATIVE_VERIFY) + std::vector zeros(length_bytes, '\0'); + Write(handle, zeros.data(), length_bytes, offset_bytes); + trimmed = true; +#endif #if defined(__linux__) // FALLOC_FL_PUNCH_HOLE requires glibc 2.18 or up #if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 18) - return false; + // Nothing #else int fd = handle.Cast().fd; int res = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, UnsafeNumericCast(offset_bytes), UnsafeNumericCast(length_bytes)); - return res == 0; + trimmed = (res == 0); #endif -#else - return false; #endif + return trimmed; } int64_t LocalFileSystem::GetFileSize(FileHandle &handle) {