aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/pg_visibility/pg_visibility.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 1a1a4ff7be7..adeb9512a70 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -380,6 +380,7 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
Relation rel;
ForkNumber fork;
BlockNumber block;
+ BlockNumber old_block;
rel = relation_open(relid, AccessExclusiveLock);
@@ -389,15 +390,22 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
/* Forcibly reset cached file size */
RelationGetSmgr(rel)->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = InvalidBlockNumber;
+ /* Compute new and old size before entering critical section. */
+ fork = VISIBILITYMAP_FORKNUM;
block = visibilitymap_prepare_truncate(rel, 0);
- if (BlockNumberIsValid(block))
- {
- fork = VISIBILITYMAP_FORKNUM;
- smgrtruncate(RelationGetSmgr(rel), &fork, 1, &block);
- }
+ old_block = BlockNumberIsValid(block) ? smgrnblocks(RelationGetSmgr(rel), fork) : 0;
+
+ /*
+ * WAL-logging, buffer dropping, file truncation must be atomic and all on
+ * one side of a checkpoint. See RelationTruncate() for discussion.
+ */
+ Assert((MyProc->delayChkptFlags & (DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE)) == 0);
+ MyProc->delayChkptFlags |= DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE;
+ START_CRIT_SECTION();
if (RelationNeedsWAL(rel))
{
+ XLogRecPtr lsn;
xl_smgr_truncate xlrec;
xlrec.blkno = 0;
@@ -407,9 +415,17 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
XLogBeginInsert();
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
- XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
+ lsn = XLogInsert(RM_SMGR_ID,
+ XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
+ XLogFlush(lsn);
}
+ if (BlockNumberIsValid(block))
+ smgrtruncate(RelationGetSmgr(rel), &fork, 1, &old_block, &block);
+
+ END_CRIT_SECTION();
+ MyProc->delayChkptFlags &= ~(DELAY_CHKPT_START | DELAY_CHKPT_COMPLETE);
+
/*
* Release the lock right away, not at commit time.
*