]> granicus.if.org Git - postgresql/blobdiff - src/backend/access/heap/visibilitymap.c
Fix WAL-logging of FSM and VM truncation.
[postgresql] / src / backend / access / heap / visibilitymap.c
index 3ad4a9f5870ddf68120eb1566ec00fa400d1b2be..f020737f800f8f07b2c7663d624b165581bec32d 100644 (file)
@@ -508,6 +508,9 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
 
                LockBuffer(mapBuffer, BUFFER_LOCK_EXCLUSIVE);
 
+               /* NO EREPORT(ERROR) from here till changes are logged */
+               START_CRIT_SECTION();
+
                /* Clear out the unwanted bytes. */
                MemSet(&map[truncByte + 1], 0, MAPSIZE - (truncByte + 1));
 
@@ -523,7 +526,20 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
                 */
                map[truncByte] &= (1 << truncOffset) - 1;
 
+               /*
+                * Truncation of a relation is WAL-logged at a higher-level, and we
+                * will be called at WAL replay. But if checksums are enabled, we need
+                * to still write a WAL record to protect against a torn page, if the
+                * page is flushed to disk before the truncation WAL record. We cannot
+                * use MarkBufferDirtyHint here, because that will not dirty the page
+                * during recovery.
+                */
                MarkBufferDirty(mapBuffer);
+               if (!InRecovery && RelationNeedsWAL(rel) && XLogHintBitIsNeeded())
+                       log_newpage_buffer(mapBuffer, false);
+
+               END_CRIT_SECTION();
+
                UnlockReleaseBuffer(mapBuffer);
        }
        else