v2-0001-Speedup-truncates-of-relation-forks.patch
application/octet-stream
Filename: v2-0001-Speedup-truncates-of-relation-forks.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: Speedup truncates of relation forks
| File | + | − |
|---|---|---|
| contrib/pg_visibility/pg_visibility.c | 16 | 1 |
| src/backend/access/heap/visibilitymap.c | 12 | 19 |
| src/backend/catalog/storage.c | 110 | 16 |
| src/backend/storage/buffer/bufmgr.c | 35 | 10 |
| src/backend/storage/freespace/freespace.c | 12 | 26 |
| src/backend/storage/smgr/smgr.c | 14 | 10 |
| src/include/access/visibilitymap.h | 1 | 1 |
| src/include/storage/bufmgr.h | 2 | 2 |
| src/include/storage/freespace.h | 1 | 1 |
| src/include/storage/smgr.h | 4 | 3 |
From c058bba2bfc47490f231d6f067bb470cdefccbc0 Mon Sep 17 00:00:00 2001
From: Kirk Jamison <k.jamison@jp.fujitsu.com>
Date: Tue, 11 Jun 2019 01:41:43 +0000
Subject: [PATCH] Speedup truncates of relation forks
Whenever we truncate relations, it involves several scans of the
shared buffers for every call of smgrtruncate() for each fork which
is time-consuming. This patch reduces the scan for all forks into one
instead of three, and improves the relation truncates by initially
marking the pages-to-be-truncated of relation forks, then
simultaneously truncating them, resulting to an improved performance
in VACUUM, autovacuum operations and their recovery performance.
---
contrib/pg_visibility/pg_visibility.c | 17 +++-
src/backend/access/heap/visibilitymap.c | 31 +++-----
src/backend/catalog/storage.c | 126 ++++++++++++++++++++++++++----
src/backend/storage/buffer/bufmgr.c | 45 ++++++++---
src/backend/storage/freespace/freespace.c | 38 +++------
src/backend/storage/smgr/smgr.c | 24 +++---
src/include/access/visibilitymap.h | 2 +-
src/include/storage/bufmgr.h | 4 +-
src/include/storage/freespace.h | 2 +-
src/include/storage/smgr.h | 7 +-
10 files changed, 207 insertions(+), 89 deletions(-)
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 1372bb6..2499415 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -383,6 +383,10 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);
Relation rel;
+ ForkNumber forks[MAX_FORKNUM];
+ BlockNumber blocks[MAX_FORKNUM];
+ BlockNumber newnblocks = InvalidBlockNumber;
+ int nforks = 0;
rel = relation_open(relid, AccessExclusiveLock);
@@ -392,7 +396,18 @@ pg_truncate_visibility_map(PG_FUNCTION_ARGS)
RelationOpenSmgr(rel);
rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
- visibilitymap_truncate(rel, 0);
+ blocks[nforks] = visibilitymap_mark_truncate(rel, 0);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = VISIBILITYMAP_FORKNUM;
+ newnblocks = blocks[nforks];
+ nforks++;
+ }
+ smgrtruncate(rel->rd_smgr, forks, blocks, nforks);
+
+ /* Update the local smgr_vm_nblocks setting */
+ if (rel->rd_smgr)
+ rel->rd_smgr->smgr_vm_nblocks = newnblocks;
if (RelationNeedsWAL(rel))
{
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index 64dfe06..2f1379c 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -17,7 +17,7 @@
* visibilitymap_set - set a bit in a previously pinned page
* visibilitymap_get_status - get status of bits
* visibilitymap_count - count number of bits set in visibility map
- * visibilitymap_truncate - truncate the visibility map
+ * visibilitymap_mark_truncate - mark the about-to-be-truncated VM
*
* NOTES
*
@@ -430,7 +430,10 @@ visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_fro
}
/*
- * visibilitymap_truncate - truncate the visibility map
+ * visibilitymap_mark_truncate - mark the about-to-be-truncated VM
+ *
+ * Formerly, this function truncates VM relation forks. Instead, this just
+ * marks the dirty buffers.
*
* The caller must hold AccessExclusiveLock on the relation, to ensure that
* other backends receive the smgr invalidation event that this function sends
@@ -438,8 +441,8 @@ visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_fro
*
* nheapblocks is the new size of the heap.
*/
-void
-visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
+BlockNumber
+visibilitymap_mark_truncate(Relation rel, BlockNumber nheapblocks)
{
BlockNumber newnblocks;
@@ -459,7 +462,7 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
* nothing to truncate.
*/
if (!smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
- return;
+ return InvalidBlockNumber;
/*
* Unless the new size is exactly at a visibility map page boundary, the
@@ -480,7 +483,7 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
if (!BufferIsValid(mapBuffer))
{
/* nothing to do, the file was already smaller */
- return;
+ return InvalidBlockNumber;
}
page = BufferGetPage(mapBuffer);
@@ -528,20 +531,10 @@ visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
if (smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM) <= newnblocks)
{
/* nothing to do, the file was already smaller than requested size */
- return;
+ return InvalidBlockNumber;
}
-
- /* Truncate the unused VM pages, and send smgr inval message */
- smgrtruncate(rel->rd_smgr, VISIBILITYMAP_FORKNUM, newnblocks);
-
- /*
- * We might as well update the local smgr_vm_nblocks setting. smgrtruncate
- * sent an smgr cache inval message, which will cause other backends to
- * invalidate their copy of smgr_vm_nblocks, and this one too at the next
- * command boundary. But this ensures it isn't outright wrong until then.
- */
- if (rel->rd_smgr)
- rel->rd_smgr->smgr_vm_nblocks = newnblocks;
+ else
+ return newnblocks;
}
/*
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index 3cc886f..3151632 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -231,6 +231,11 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
{
bool fsm;
bool vm;
+ ForkNumber forks[MAX_FORKNUM];
+ BlockNumber blocks[MAX_FORKNUM];
+ BlockNumber new_nfsmblocks = InvalidBlockNumber; /* FSM blocks */
+ BlockNumber newnblocks = InvalidBlockNumber; /* VM blocks */
+ int nforks = 0;
/* Open it at the smgr level if not already done */
RelationOpenSmgr(rel);
@@ -242,15 +247,34 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
rel->rd_smgr->smgr_fsm_nblocks = InvalidBlockNumber;
rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
- /* Truncate the FSM first if it exists */
+ /*
+ * We used to truncate FSM and VM forks here. Now we only mark the
+ * dirty buffers of all forks about-to-be-truncated if they exist.
+ */
+
fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
if (fsm)
- FreeSpaceMapTruncateRel(rel, nblocks);
+ {
+ blocks[nforks] = MarkFreeSpaceMapTruncateRel(rel, nblocks);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = FSM_FORKNUM;
+ new_nfsmblocks= blocks[nforks]; /* FSM blocks */
+ nforks++;
+ }
+ }
- /* Truncate the visibility map too if it exists. */
vm = smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
if (vm)
- visibilitymap_truncate(rel, nblocks);
+ {
+ blocks[nforks] = visibilitymap_mark_truncate(rel, nblocks);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = VISIBILITYMAP_FORKNUM;
+ newnblocks = blocks[nforks]; /* VM blocks */
+ nforks++;
+ }
+ }
/*
* We WAL-log the truncation before actually truncating, which means
@@ -263,9 +287,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
*/
if (RelationNeedsWAL(rel))
{
- /*
- * Make an XLOG entry reporting the file truncation.
- */
+ /* Make an XLOG entry reporting the file truncation */
XLogRecPtr lsn;
xl_smgr_truncate xlrec;
@@ -290,8 +312,33 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
XLogFlush(lsn);
}
- /* Do the real work */
- smgrtruncate(rel->rd_smgr, MAIN_FORKNUM, nblocks);
+ /* Mark the MAIN fork */
+ forks[nforks] = MAIN_FORKNUM;
+ blocks[nforks] = nblocks;
+ nforks++;
+
+ /* Truncate relation forks simultaneously */
+ smgrtruncate(rel->rd_smgr, forks, blocks, nforks);
+
+ /*
+ * We might as well update the local smgr_fsm_nblocks and smgr_vm_nblocks
+ * setting. smgrtruncate sent an smgr cache inval message, which will cause
+ * other backends to invalidate their copy of smgr_fsm_nblocks and
+ * smgr_vm_nblocks, and this one too at the next command boundary. But this
+ * ensures it isn't outright wrong until then.
+ */
+ if (rel->rd_smgr)
+ {
+ rel->rd_smgr->smgr_fsm_nblocks = new_nfsmblocks;
+ rel->rd_smgr->smgr_vm_nblocks = newnblocks;
+ }
+
+ /*
+ * Update upper-level FSM pages to account for the truncation. This is
+ * important because the just-truncated pages were likely marked as
+ * all-free, and would be preferentially selected.
+ */
+ FreeSpaceMapVacuumRange(rel, new_nfsmblocks, InvalidBlockNumber);
}
/*
@@ -588,6 +635,14 @@ smgr_redo(XLogReaderState *record)
xl_smgr_truncate *xlrec = (xl_smgr_truncate *) XLogRecGetData(record);
SMgrRelation reln;
Relation rel;
+ ForkNumber forks[MAX_FORKNUM];
+ BlockNumber blocks[MAX_FORKNUM];
+ BlockNumber new_nfsmblocks = InvalidBlockNumber;
+ BlockNumber newnblocks = InvalidBlockNumber;
+ int nforks = 0;
+ bool fsm_fork = false;
+ bool main_fork = false;
+ bool vm_fork = false;
reln = smgropen(xlrec->rnode, InvalidBackendId);
@@ -616,23 +671,62 @@ smgr_redo(XLogReaderState *record)
*/
XLogFlush(lsn);
+ /*
+ * To speedup recovery, we mark the about-to-be-truncated blocks of
+ * relation forks first, then truncate those simultaneously later.
+ */
if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0)
{
- smgrtruncate(reln, MAIN_FORKNUM, xlrec->blkno);
-
- /* Also tell xlogutils.c about it */
- XLogTruncateRelation(xlrec->rnode, MAIN_FORKNUM, xlrec->blkno);
+ forks[nforks] = MAIN_FORKNUM;
+ blocks[nforks] = xlrec->blkno;
+ nforks++;
+ main_fork = true;
}
- /* Truncate FSM and VM too */
rel = CreateFakeRelcacheEntry(xlrec->rnode);
if ((xlrec->flags & SMGR_TRUNCATE_FSM) != 0 &&
smgrexists(reln, FSM_FORKNUM))
- FreeSpaceMapTruncateRel(rel, xlrec->blkno);
+ {
+ blocks[nforks] = MarkFreeSpaceMapTruncateRel(rel, xlrec->blkno);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = FSM_FORKNUM;
+ new_nfsmblocks= blocks[nforks];
+ nforks++;
+ fsm_fork = true;
+ }
+ }
if ((xlrec->flags & SMGR_TRUNCATE_VM) != 0 &&
smgrexists(reln, VISIBILITYMAP_FORKNUM))
- visibilitymap_truncate(rel, xlrec->blkno);
+ {
+ blocks[nforks] = visibilitymap_mark_truncate(rel, xlrec->blkno);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = VISIBILITYMAP_FORKNUM;
+ newnblocks = blocks[nforks];
+ nforks++;
+ vm_fork = true;
+ }
+ }
+
+ /* Truncate relation forks simultaneously */
+ if (main_fork || fsm_fork || vm_fork)
+ smgrtruncate(reln, forks, blocks, nforks);
+
+ /* Also tell xlogutils.c about it */
+ if (main_fork)
+ XLogTruncateRelation(xlrec->rnode, MAIN_FORKNUM, xlrec->blkno);
+
+ /* Update the local smgr_fsm_nblocks and smgr_vm_nblocks setting */
+ if (rel->rd_smgr)
+ {
+ rel->rd_smgr->smgr_fsm_nblocks = new_nfsmblocks;
+ rel->rd_smgr->smgr_vm_nblocks = newnblocks;
+ }
+
+ /* Update upper-level FSM pages to account for the truncation */
+ FreeSpaceMapVacuumRange(rel, new_nfsmblocks, InvalidBlockNumber);
FreeFakeRelcacheEntry(rel);
}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7332e6b..dad8158 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -2899,8 +2899,8 @@ BufferGetLSNAtomic(Buffer buffer)
/* ---------------------------------------------------------------------
* DropRelFileNodeBuffers
*
- * This function removes from the buffer pool all the pages of the
- * specified relation fork that have block numbers >= firstDelBlock.
+ * This function simultaneously removes from the buffer pool all the
+ * pages of the relation forks that have block numbers >= firstDelBlock.
* (In particular, with firstDelBlock = 0, all pages are removed.)
* Dirty pages are simply dropped, without bothering to write them
* out first. Therefore, this is NOT rollback-able, and so should be
@@ -2923,23 +2923,37 @@ BufferGetLSNAtomic(Buffer buffer)
* --------------------------------------------------------------------
*/
void
-DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber forkNum,
- BlockNumber firstDelBlock)
+DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber *forkNum,
+ BlockNumber *firstDelBlock, int nforks)
{
int i;
+ BlockNumber minBlock = InvalidBlockNumber;
/* If it's a local relation, it's localbuf.c's problem. */
if (RelFileNodeBackendIsTemp(rnode))
{
if (rnode.backend == MyBackendId)
- DropRelFileNodeLocalBuffers(rnode.node, forkNum, firstDelBlock);
+ {
+ for (int j = 0; j < nforks; j++)
+ DropRelFileNodeLocalBuffers(rnode.node, forkNum[j],
+ firstDelBlock[j]);
+ }
return;
}
+ /* Get the lower bound of target block number we're interested in */
+ for (i = 0; i < nforks; i++)
+ {
+ if (!BlockNumberIsValid(minBlock) ||
+ minBlock > firstDelBlock[i])
+ minBlock = firstDelBlock[i];
+ }
+
for (i = 0; i < NBuffers; i++)
{
BufferDesc *bufHdr = GetBufferDescriptor(i);
uint32 buf_state;
+ int k = 0;
/*
* We can make this a tad faster by prechecking the buffer tag before
@@ -2960,12 +2974,23 @@ DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber forkNum,
if (!RelFileNodeEquals(bufHdr->tag.rnode, rnode.node))
continue;
+ /* Check with the lower bound block number and skip the loop */
+ if (bufHdr->tag.blockNum < minBlock)
+ continue; /* skip checking the buffer pool scan */
+
buf_state = LockBufHdr(bufHdr);
- if (RelFileNodeEquals(bufHdr->tag.rnode, rnode.node) &&
- bufHdr->tag.forkNum == forkNum &&
- bufHdr->tag.blockNum >= firstDelBlock)
- InvalidateBuffer(bufHdr); /* releases spinlock */
- else
+
+ for (k = 0; k < nforks; k++)
+ {
+ if (RelFileNodeEquals(bufHdr->tag.rnode, rnode.node) &&
+ bufHdr->tag.forkNum == forkNum[k] &&
+ bufHdr->tag.blockNum >= firstDelBlock[k])
+ {
+ InvalidateBuffer(bufHdr); /* releases spinlock */
+ break;
+ }
+ }
+ if (k >= nforks)
UnlockBufHdr(bufHdr, buf_state);
}
}
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index c17b3f4..708c7cb 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -247,7 +247,10 @@ GetRecordedFreeSpace(Relation rel, BlockNumber heapBlk)
}
/*
- * FreeSpaceMapTruncateRel - adjust for truncation of a relation.
+ * MarkFreeSpaceMapTruncateRel - adjust for truncation of a relation.
+ *
+ * Formerly, this function truncates FSM relation forks. Instead, this just
+ * marks the dirty buffers and returns a block number.
*
* The caller must hold AccessExclusiveLock on the relation, to ensure that
* other backends receive the smgr invalidation event that this function sends
@@ -255,8 +258,8 @@ GetRecordedFreeSpace(Relation rel, BlockNumber heapBlk)
*
* nblocks is the new size of the heap.
*/
-void
-FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
+BlockNumber
+MarkFreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
{
BlockNumber new_nfsmblocks;
FSMAddress first_removed_address;
@@ -270,7 +273,7 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
* truncate.
*/
if (!smgrexists(rel->rd_smgr, FSM_FORKNUM))
- return;
+ return InvalidBlockNumber;
/* Get the location in the FSM of the first removed heap block */
first_removed_address = fsm_get_location(nblocks, &first_removed_slot);
@@ -285,7 +288,7 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
{
buf = fsm_readbuf(rel, first_removed_address, false);
if (!BufferIsValid(buf))
- return; /* nothing to do; the FSM was already smaller */
+ return InvalidBlockNumber; /* nothing to do; the FSM was already smaller */
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
/* NO EREPORT(ERROR) from here till changes are logged */
@@ -310,33 +313,16 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
UnlockReleaseBuffer(buf);
new_nfsmblocks = fsm_logical_to_physical(first_removed_address) + 1;
+ return new_nfsmblocks;
}
else
{
new_nfsmblocks = fsm_logical_to_physical(first_removed_address);
if (smgrnblocks(rel->rd_smgr, FSM_FORKNUM) <= new_nfsmblocks)
- return; /* nothing to do; the FSM was already smaller */
+ return InvalidBlockNumber; /* nothing to do; the FSM was already smaller */
+ else
+ return new_nfsmblocks;
}
-
- /* Truncate the unused FSM pages, and send smgr inval message */
- smgrtruncate(rel->rd_smgr, FSM_FORKNUM, new_nfsmblocks);
-
- /*
- * We might as well update the local smgr_fsm_nblocks setting.
- * smgrtruncate sent an smgr cache inval message, which will cause other
- * backends to invalidate their copy of smgr_fsm_nblocks, and this one too
- * at the next command boundary. But this ensures it isn't outright wrong
- * until then.
- */
- if (rel->rd_smgr)
- rel->rd_smgr->smgr_fsm_nblocks = new_nfsmblocks;
-
- /*
- * Update upper-level FSM pages to account for the truncation. This is
- * important because the just-truncated pages were likely marked as
- * all-free, and would be preferentially selected.
- */
- FreeSpaceMapVacuumRange(rel, nblocks, InvalidBlockNumber);
}
/*
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index dba8c39..b37560e 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -508,19 +508,21 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
* already.
*/
void
-smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo)
+smgrdounlinkfork(SMgrRelation reln, ForkNumber *forknum, bool isRedo, int nforks)
{
RelFileNodeBackend rnode = reln->smgr_rnode;
int which = reln->smgr_which;
+ int i;
/* Close the fork at smgr level */
- smgrsw[which].smgr_close(reln, forknum);
+ for (i = 0; i < nforks; i++)
+ smgrsw[which].smgr_close(reln, forknum[i]);
/*
* Get rid of any remaining buffers for the fork. bufmgr will just drop
* them without bothering to write the contents.
*/
- DropRelFileNodeBuffers(rnode, forknum, 0);
+ DropRelFileNodeBuffers(rnode, forknum, 0, nforks);
/*
* It'd be nice to tell the stats collector to forget it immediately, too.
@@ -546,7 +548,8 @@ smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo)
* ERROR, because we've already decided to commit or abort the current
* xact.
*/
- smgrsw[which].smgr_unlink(rnode, forknum, isRedo);
+ for (i = 0; i < nforks; i++)
+ smgrsw[which].smgr_unlink(rnode, forknum[i], isRedo);
}
/*
@@ -643,13 +646,15 @@ smgrnblocks(SMgrRelation reln, ForkNumber forknum)
* The truncation is done immediately, so this can't be rolled back.
*/
void
-smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
+smgrtruncate(SMgrRelation reln, ForkNumber *forknum, BlockNumber *nblocks, int nforks)
{
+ int i;
+
/*
* Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
* just drop them without bothering to write the contents.
*/
- DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);
+ DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks, nforks);
/*
* Send a shared-inval message to force other backends to close any smgr
@@ -663,10 +668,9 @@ smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
*/
CacheInvalidateSmgr(reln->smgr_rnode);
- /*
- * Do the truncation.
- */
- smgrsw[reln->smgr_which].smgr_truncate(reln, forknum, nblocks);
+ /* Do the truncation */
+ for (i = 0; i < nforks; i++)
+ smgrsw[reln->smgr_which].smgr_truncate(reln, forknum[i], nblocks[i]);
}
/*
diff --git a/src/include/access/visibilitymap.h b/src/include/access/visibilitymap.h
index 2d88043..4735d5f 100644
--- a/src/include/access/visibilitymap.h
+++ b/src/include/access/visibilitymap.h
@@ -44,6 +44,6 @@ extern void visibilitymap_set(Relation rel, BlockNumber heapBlk, Buffer heapBuf,
uint8 flags);
extern uint8 visibilitymap_get_status(Relation rel, BlockNumber heapBlk, Buffer *vmbuf);
extern void visibilitymap_count(Relation rel, BlockNumber *all_visible, BlockNumber *all_frozen);
-extern void visibilitymap_truncate(Relation rel, BlockNumber nheapblocks);
+extern BlockNumber visibilitymap_mark_truncate(Relation rel, BlockNumber nheapblocks);
#endif /* VISIBILITYMAP_H */
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 509f4b7..5be6c0d 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -190,8 +190,8 @@ extern BlockNumber RelationGetNumberOfBlocksInFork(Relation relation,
extern void FlushOneBuffer(Buffer buffer);
extern void FlushRelationBuffers(Relation rel);
extern void FlushDatabaseBuffers(Oid dbid);
-extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode,
- ForkNumber forkNum, BlockNumber firstDelBlock);
+extern void DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber *forkNum,
+ BlockNumber *firstDelBlock, int nforks);
extern void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes);
extern void DropDatabaseBuffers(Oid dbid);
diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h
index 8d8c465..bf19a67 100644
--- a/src/include/storage/freespace.h
+++ b/src/include/storage/freespace.h
@@ -30,7 +30,7 @@ extern void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk,
extern void XLogRecordPageWithFreeSpace(RelFileNode rnode, BlockNumber heapBlk,
Size spaceAvail);
-extern void FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks);
+extern BlockNumber MarkFreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks);
extern void FreeSpaceMapVacuum(Relation rel);
extern void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start,
BlockNumber end);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index d286c8c..ff70b09 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -90,7 +90,8 @@ extern void smgrclosenode(RelFileNodeBackend rnode);
extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
extern void smgrdounlink(SMgrRelation reln, bool isRedo);
extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo);
-extern void smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo);
+extern void smgrdounlinkfork(SMgrRelation reln, ForkNumber *forknum,
+ bool isRedo, int nforks);
extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, char *buffer, bool skipFsync);
extern void smgrprefetch(SMgrRelation reln, ForkNumber forknum,
@@ -102,8 +103,8 @@ extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,
extern void smgrwriteback(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, BlockNumber nblocks);
extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum);
-extern void smgrtruncate(SMgrRelation reln, ForkNumber forknum,
- BlockNumber nblocks);
+extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum,
+ BlockNumber *nblocks, int nforks);
extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum);
extern void AtEOXact_SMgr(void);
--
1.8.3.1