From 5b5bccc7cb6cd7b55a5c244d9ab1e73c746a8cca Mon Sep 17 00:00:00 2001 From: Kirk Jamison Date: Wed, 7 Oct 2020 09:57:53 +0000 Subject: [PATCH 2/3] Add bool param in smgrnblocks() for cached blocks. --- src/backend/access/gist/gistbuild.c | 4 +++- src/backend/access/heap/visibilitymap.c | 9 ++++++--- src/backend/access/table/tableam.c | 5 +++-- src/backend/access/transam/xlogutils.c | 3 ++- src/backend/catalog/storage.c | 6 ++++-- src/backend/storage/buffer/bufmgr.c | 12 ++++++++---- src/backend/storage/freespace/freespace.c | 9 ++++++--- src/backend/storage/smgr/smgr.c | 13 +++++++++++-- src/include/storage/smgr.h | 3 ++- 9 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index 28bc585..d599655 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -808,6 +808,7 @@ gistBuildCallback(Relation index, GISTBuildState *buildstate = (GISTBuildState *) state; IndexTuple itup; MemoryContext oldCtx; + bool isCached; oldCtx = MemoryContextSwitchTo(buildstate->giststate->tempCxt); @@ -856,7 +857,8 @@ 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, + &isCached)) || (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..6d2be35 100644 --- a/src/backend/access/heap/visibilitymap.c +++ b/src/backend/access/heap/visibilitymap.c @@ -445,6 +445,7 @@ BlockNumber visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks) { BlockNumber newnblocks; + bool cached; /* last remaining block, byte, and bit */ BlockNumber truncBlock = HEAPBLK_TO_MAPBLOCK(nheapblocks); @@ -528,7 +529,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, &cached) <= newnblocks) { /* nothing to do, the file was already smaller than requested size */ return InvalidBlockNumber; @@ -547,6 +548,7 @@ static Buffer vm_readbuf(Relation rel, BlockNumber blkno, bool extend) { Buffer buf; + bool cached; /* * We might not have opened the relation at the smgr level yet, or we @@ -564,7 +566,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, &cached); else rel->rd_smgr->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = 0; } @@ -618,6 +620,7 @@ vm_extend(Relation rel, BlockNumber vm_nblocks) { BlockNumber vm_nblocks_now; PGAlignedBlock pg; + bool cached; PageInit((Page) pg.data, BLCKSZ, 0); @@ -647,7 +650,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, &cached); /* 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..e64451f 100644 --- a/src/backend/access/table/tableam.c +++ b/src/backend/access/table/tableam.c @@ -628,6 +628,7 @@ uint64 table_block_relation_size(Relation rel, ForkNumber forkNumber) { uint64 nblocks = 0; + bool cached; /* Open it at the smgr level if not already done */ RelationOpenSmgr(rel); @@ -636,10 +637,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, &cached); } else - nblocks = smgrnblocks(rel->rd_smgr, forkNumber); + nblocks = smgrnblocks(rel->rd_smgr, forkNumber, &cached); return nblocks * BLCKSZ; } diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 7e915bc..20eda81 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -444,6 +444,7 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, BlockNumber lastblock; Buffer buffer; SMgrRelation smgr; + bool cached; Assert(blkno != P_NEW); @@ -460,7 +461,7 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, */ smgrcreate(smgr, forknum, true); - lastblock = smgrnblocks(smgr, forknum); + lastblock = smgrnblocks(smgr, forknum, &cached); if (blkno < lastblock) { diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index dbbd3aa..057e53b 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -410,6 +410,7 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst, { PGAlignedBlock buf; Page page; + bool cached; bool use_wal; bool copying_initfork; BlockNumber nblocks; @@ -434,7 +435,7 @@ RelationCopyStorage(SMgrRelation src, SMgrRelation dst, use_wal = XLogIsNeeded() && (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork); - nblocks = smgrnblocks(src, forkNum); + nblocks = smgrnblocks(src, forkNum, &cached); for (blkno = 0; blkno < nblocks; blkno++) { @@ -703,6 +704,7 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker) BlockNumber nblocks[MAX_FORKNUM + 1]; BlockNumber total_blocks = 0; SMgrRelation srel; + bool cached; srel = smgropen(pendingsync->rnode, InvalidBackendId); @@ -720,7 +722,7 @@ smgrDoPendingSyncs(bool isCommit, bool isParallelWorker) { if (smgrexists(srel, fork)) { - BlockNumber n = smgrnblocks(srel, fork); + BlockNumber n = smgrnblocks(srel, fork, &cached); /* 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 e549fa1..45897a3 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -720,6 +720,7 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, BufferDesc *bufHdr; Block bufBlock; bool found; + bool isCached; bool isExtend; bool isLocalBuf = SmgrIsTemp(smgr); @@ -739,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, &isCached); if (isLocalBuf) { @@ -2852,11 +2853,14 @@ RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum) case RELKIND_SEQUENCE: case RELKIND_INDEX: case RELKIND_PARTITIONED_INDEX: - /* Open it at the smgr level if not already done */ - RelationOpenSmgr(relation); + { + bool isCached; - return smgrnblocks(relation->rd_smgr, forkNum); + /* Open it at the smgr level if not already done */ + RelationOpenSmgr(relation); + return smgrnblocks(relation->rd_smgr, forkNum, &isCached); + } case RELKIND_RELATION: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 6a96126..f631878 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -264,6 +264,7 @@ FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks) FSMAddress first_removed_address; uint16 first_removed_slot; Buffer buf; + bool cached; RelationOpenSmgr(rel); @@ -317,7 +318,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, &cached) <= new_nfsmblocks) return InvalidBlockNumber; /* nothing to do; the FSM was already * smaller */ } @@ -532,6 +533,7 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend) { BlockNumber blkno = fsm_logical_to_physical(addr); Buffer buf; + bool cached; RelationOpenSmgr(rel); @@ -547,7 +549,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, &cached); else rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = 0; } @@ -603,6 +605,7 @@ fsm_extend(Relation rel, BlockNumber fsm_nblocks) { BlockNumber fsm_nblocks_now; PGAlignedBlock pg; + bool cached; PageInit((Page) pg.data, BLCKSZ, 0); @@ -633,7 +636,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, &cached); while (fsm_nblocks_now < fsm_nblocks) { diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index f476b8e..d7d61ea 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -553,16 +553,25 @@ smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, * supplied relation. */ BlockNumber -smgrnblocks(SMgrRelation reln, ForkNumber forknum) +smgrnblocks(SMgrRelation reln, ForkNumber forknum, bool *isCached) { BlockNumber result; + *isCached = false; + /* * 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. The cached values + * could be smaller than the actual number of existing buffers of the file. + * This is caused by lseek of buggy Linux kernels that might not have + * accounted for the recent write. */ if (InRecovery && reln->smgr_cached_nblocks[forknum] != InvalidBlockNumber) + { + *isCached = true; + return reln->smgr_cached_nblocks[forknum]; + } 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..e247cce 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 *isCached); extern void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks); extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum); -- 1.8.3.1