diff --git a/src/backend/storage/freespace/README b/src/backend/storage/freespace/README index dc2a63a137b..d68bd4c2aab 100644 --- a/src/backend/storage/freespace/README +++ b/src/backend/storage/freespace/README @@ -189,9 +189,25 @@ to propagate the new free-space info into the upper pages of the FSM tree. As a result when we write to the FSM we treat that as a hint and thus use MarkBufferDirtyHint() rather than MarkBufferDirty(). Every read here uses RBM_ZERO_ON_ERROR to bypass checksum mismatches and other verification -failures. We'd operate correctly without the full page images that -MarkBufferDirtyHint() provides, but they do decrease the chance of losing slot -knowledge to RBM_ZERO_ON_ERROR. +failures. + +That RBM_ZERO_ON_ERROR is a property of this directory, not of the FSM fork +itself. The files themselves are ordinary relation files, and plenty of code +outside freespace.c reads them and does verify checksums: +RelationCopyStorage(), which ALTER TABLE ... SET TABLESPACE runs over every +fork; the read stream in RelationCopyStorageUsingBuffer(), used by +CREATE DATABASE ... STRATEGY = wal_log; and the checksum verification in base +backups and in pg_checksums. The alternative would be all such code skipping +checksum validation of *_fsm files, and that may be the right call someday. +Today they do verify, so what we write here has to be valid. + +So the full page images MarkBufferDirtyHint() writes are not just an +optimization that reduces how often RBM_ZERO_ON_ERROR loses knowledge. +When checksums or wal_log_hints are enabled they are what keeps an FSM page +that reaches disk either checksum-valid or repairable by a later FPI. Do not +replace MarkBufferDirtyHint() with MarkBufferDirty() here on the grounds that +the FSM survives torn pages; it does, but the rest of the system is not +promised the same. Relation extension is not WAL-logged. Hence, after WAL replay, an on-disk FSM slot may indicate free space in PageIsNew() blocks that never reached disk.