v30-0002-Add-bool-param-in-smgrnblocks-for-cached-blocks.patch
application/octet-stream
Filename: v30-0002-Add-bool-param-in-smgrnblocks-for-cached-blocks.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch v30-0002
Subject: Add bool param in smgrnblocks() for cached blocks.
| File | + | − |
|---|---|---|
| src/backend/access/gist/gistbuild.c | 1 | 1 |
| src/backend/access/heap/visibilitymap.c | 3 | 3 |
| src/backend/access/table/tableam.c | 2 | 2 |
| src/backend/access/transam/xlogutils.c | 1 | 1 |
| src/backend/catalog/storage.c | 2 | 2 |
| src/backend/storage/buffer/bufmgr.c | 2 | 2 |
| src/backend/storage/freespace/freespace.c | 3 | 3 |
| src/backend/storage/smgr/smgr.c | 18 | 3 |
| src/include/storage/smgr.h | 2 | 1 |
From 56de88968da9252c5bccf64857b738510e84a557 Mon Sep 17 00:00:00 2001
From: Kirk Jamison <k.jamison@jp.fujitsu.com>
Date: Wed, 7 Oct 2020 09:57:53 +0000
Subject: [PATCH v30 2/4] Add bool param in smgrnblocks() for cached blocks.
The flag ensures that we return a reliable value from smgrnblocks.
---
src/backend/access/gist/gistbuild.c | 2 +-
src/backend/access/heap/visibilitymap.c | 6 +++---
src/backend/access/table/tableam.c | 4 ++--
src/backend/access/transam/xlogutils.c | 2 +-
src/backend/catalog/storage.c | 4 ++--
src/backend/storage/buffer/bufmgr.c | 4 ++--
src/backend/storage/freespace/freespace.c | 6 +++---
src/backend/storage/smgr/smgr.c | 21 ++++++++++++++++++---
src/include/storage/smgr.h | 3 ++-
9 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 9d3fa9c..d4a3bff 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -860,7 +860,7 @@ gistBuildCallback(Relation index,
*/
if ((buildstate->buildMode == GIST_BUFFERING_AUTO &&
buildstate->indtuples % BUFFERING_MODE_SWITCH_CHECK_STEP == 0 &&
- effective_cache_size < smgrnblocks(index->rd_smgr, MAIN_FORKNUM)) ||
+ effective_cache_size < smgrnblocks(index->rd_smgr, MAIN_FORKNUM, NULL)) ||
(buildstate->buildMode == GIST_BUFFERING_STATS &&
buildstate->indtuples >= BUFFERING_MODE_TUPLE_SIZE_STATS_TARGET))
{
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index b107218..ef8533e 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -528,7 +528,7 @@ visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks)
else
newnblocks = truncBlock;
- if (smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM) <= newnblocks)
+ if (smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM, NULL) <= newnblocks)
{
/* nothing to do, the file was already smaller than requested size */
return InvalidBlockNumber;
@@ -564,7 +564,7 @@ vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
if (rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] == InvalidBlockNumber)
{
if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
- smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
+ smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM, NULL);
else
rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = 0;
}
@@ -647,7 +647,7 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
/* Invalidate cache so that smgrnblocks() asks the kernel. */
rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = InvalidBlockNumber;
- vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
+ vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM, NULL);
/* Now extend the file */
while (vm_nblocks_now < vm_nblocks)
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index 6438c45..75eade8 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -636,10 +636,10 @@ table_block_relation_size(Relation rel, ForkNumber forkNumber)
if (forkNumber == InvalidForkNumber)
{
for (int i = 0; i < MAX_FORKNUM; i++)
- nblocks += smgrnblocks(rel->rd_smgr, i);
+ nblocks += smgrnblocks(rel->rd_smgr, i, NULL);
}
else
- nblocks = smgrnblocks(rel->rd_smgr, forkNumber);
+ nblocks = smgrnblocks(rel->rd_smgr, forkNumber, NULL);
return nblocks * BLCKSZ;
}
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 7e915bc..46fd97d 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -460,7 +460,7 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum,
*/
smgrcreate(smgr, forknum, true);
- lastblock = smgrnblocks(smgr, forknum);
+ lastblock = smgrnblocks(smgr, forknum, NULL);
if (blkno < lastblock)
{
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index d538f257..3874ff3 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -434,7 +434,7 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst,
use_wal = XLogIsNeeded() &&
(relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
- nblocks = smgrnblocks(src, forkNum);
+ nblocks = smgrnblocks(src, forkNum, NULL);
for (blkno = 0; blkno < nblocks; blkno++)
{
@@ -721,7 +721,7 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker)
{
if (smgrexists(srel, fork))
{
- BlockNumber n = smgrnblocks(srel, fork);
+ BlockNumber n = smgrnblocks(srel, fork, NULL);
/* we shouldn't come here for unlogged relations */
Assert(fork != INIT_FORKNUM);
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index ad0d1a9..1680bf4 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -740,7 +740,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
/* Substitute proper block number if caller asked for P_NEW */
if (isExtend)
- blockNum = smgrnblocks(smgr, forkNum);
+ blockNum = smgrnblocks(smgr, forkNum, NULL);
if (isLocalBuf)
{
@@ -2857,7 +2857,7 @@ RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
/* Open it at the smgr level if not already done */
RelationOpenSmgr(relation);
- return smgrnblocks(relation->rd_smgr, forkNum);
+ return smgrnblocks(relation->rd_smgr, forkNum, NULL);
case RELKIND_RELATION:
case RELKIND_TOASTVALUE:
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index 6a96126..2ac802c 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -317,7 +317,7 @@ FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks)
else
{
new_nfsmblocks = fsm_logical_to_physical(first_removed_address);
- if (smgrnblocks(rel->rd_smgr, FSM_FORKNUM) <= new_nfsmblocks)
+ if (smgrnblocks(rel->rd_smgr, FSM_FORKNUM, NULL) <= new_nfsmblocks)
return InvalidBlockNumber; /* nothing to do; the FSM was already
* smaller */
}
@@ -547,7 +547,7 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend)
/* Invalidate the cache so smgrnblocks asks the kernel. */
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber;
if (smgrexists(rel->rd_smgr, FSM_FORKNUM))
- smgrnblocks(rel->rd_smgr, FSM_FORKNUM);
+ smgrnblocks(rel->rd_smgr, FSM_FORKNUM, NULL);
else
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = 0;
}
@@ -633,7 +633,7 @@ fsm_extend(Relation rel, BlockNumber fsm_nblocks)
/* Invalidate cache so that smgrnblocks() asks the kernel. */
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber;
- fsm_nblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM);
+ fsm_nblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM, NULL);
while (fsm_nblocks_now < fsm_nblocks)
{
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index f476b8e..e9dffd2 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -535,7 +535,6 @@ smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
buffer, skipFsync);
}
-
/*
* smgrwriteback() -- Trigger kernel writeback for the supplied range of
* blocks.
@@ -551,18 +550,34 @@ smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
/*
* smgrnblocks() -- Calculate the number of blocks in the
* supplied relation.
+ *
+ * The "cached" flag ensures that no buffers exist for blocks after the
+ * cached value is known to the process during recovery.
*/
BlockNumber
-smgrnblocks(SMgrRelation reln, ForkNumber forknum)
+smgrnblocks(SMgrRelation reln, ForkNumber forknum, bool *cached)
{
BlockNumber result;
/*
* For now, we only use cached values in recovery due to lack of a shared
- * invalidation mechanism for changes in file size.
+ * invalidation mechanism for changes in file size. In recovery, the cached
+ * value returned by the first lseek could be smaller than the actual number
+ * of existing buffers of the file, which is caused by buggy Linux kernels
+ * that might not have accounted for the recent write. However, we can still
+ * rely on the cached value even if we get a bogus value from first lseek
+ * since it is impossible to have buffer for blocks after that file size.
*/
if (InRecovery && reln->smgr_cached_nblocks[forknum] != InvalidBlockNumber)
+ {
+ if (cached != NULL)
+ *cached = true;
+
return reln->smgr_cached_nblocks[forknum];
+ }
+
+ if (cached != NULL)
+ *cached = false;
result = smgrsw[reln->smgr_which].smgr_nblocks(reln, forknum);
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index f28a842..af11b53 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -98,7 +98,8 @@ extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, char *buffer, bool skipFsync);
extern void smgrwriteback(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, BlockNumber nblocks);
-extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum);
+extern BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum,
+ bool *accurate);
extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum,
int nforks, BlockNumber *nblocks);
extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum);
--
1.8.3.1