aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/heap/visibilitymap.c16
-rw-r--r--src/backend/storage/freespace/freespace.c21
2 files changed, 36 insertions, 1 deletions
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index f0436859957..5988486ecb7 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -473,6 +473,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));
@@ -488,7 +491,20 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
*/
map[truncByte] &= (1 << truncBit) - 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) && DataChecksumsEnabled())
+ log_newpage_buffer(mapBuffer);
+
+ END_CRIT_SECTION();
+
UnlockReleaseBuffer(mapBuffer);
}
else
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index 4845f93a598..f68d004b146 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -23,6 +23,7 @@
*/
#include "postgres.h"
+#include "access/heapam_xlog.h"
#include "access/htup_details.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
@@ -285,8 +286,26 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
if (!BufferIsValid(buf))
return; /* nothing to do; the FSM was already smaller */
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
+
+ /* NO EREPORT(ERROR) from here till changes are logged */
+ START_CRIT_SECTION();
+
fsm_truncate_avail(BufferGetPage(buf), first_removed_slot);
- MarkBufferDirtyHint(buf, false);
+
+ /*
+ * 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(buf);
+ if (!InRecovery && RelationNeedsWAL(rel) && DataChecksumsEnabled())
+ log_newpage_buffer(buf);
+
+ END_CRIT_SECTION();
+
UnlockReleaseBuffer(buf);
new_nfsmblocks = fsm_logical_to_physical(first_removed_address) + 1;