Hi hackers, While reviewing relation extension paths, I noticed three places that still manually perform zero-fill operations using smgrextend(), even though smgrzeroextend() (and its underlying mdzeroextend()) exists specifically for this purpose.
*The Problem* Currently, RelationCopyStorageUsingBuffer(), smgr_bulk_flush(), and segment padding in _mdfd_getseg() manually construct or loop over zeroed buffers to extend relations. This bypasses the dedicated zero-extension interfaces, leading to inconsistent code patterns. It also misses out on platform-specific optimizations like posix_fallocate() or FileZero() that mdzeroextend() leverages instead of relying on sparse-file hole semantics. *The Fix* The attached patch refactors these remaining instances to use smgrzeroextend() (and mdzeroextend() directly in md.c): 1. bufmgr.c: Replaces memset() + smgrextend() with a single smgrzeroextend() call to bulk-extend the destination relation. 2. bulk_write.c: Eliminates the file-scope zero_buffer and the while loop, substituting a single smgrzeroextend() call to fill non-sequential write gaps efficiently. 3. md.c: Removes the aligned palloc_aligned zero-buffer allocation in _mdfd_getseg(), replacing it with a direct call to mdzeroextend() to pad short segments. This unifies all zero-fill relation extensions, improves code readability, and ensures optimized zero-extension paths are used consistently across the storage manager. Reviewed by: Heikki Linnakangas *The Broader Vision* Beyond simple code cleanup, enforcing the responsibility separation of smgrextend() and smgrzeroextend() opens up a clean way to address a long-standing data validation challenge. Today, PostgreSQL can generate all-zero pages during relation extension and accept an all-zero page into the buffer cache as if it were valid. Because the engine cannot distinguish whether an all-zero page was created intentionally or corrupted by an external bug, corrupted pages can enter the buffer cache undetected. For example, if a valid heap page is overwritten with zeros, an index scan will not report an error and will simply, silently return "tuple not found." Once that page is selected for an insert or update, it gets re-initialized, cementing the silent data corruption permanently into the WAL stream. To close this gap, we want to completely eliminate all-zero pages from regular relation extension so we can accurately detect when an all-zero page is the result of a bug. While a Proof of Concept (POC) for this broader change is still in progress, implementing this refactoring is an important first step. *Testing Performed* - Regression Tests: Ran make check-world to ensure relation extension and bootstrap/creation paths function exactly as expected. - Compilation: Verified a clean build with no warnings on GCC and Clang. Feedback and suggestions on both this patch and the upcoming vision are highly welcome! Best regards, Peipei Yin
0001-Use-smgrzeroextend-for-zero-filled-relation-extensio.patch
Description: Binary data
