From 83c9b3227673fe93a389c0043d42947aa219c039 Mon Sep 17 00:00:00 2001 From: Kirk Jamison Date: Wed, 7 Oct 2020 09:57:53 +0000 Subject: [PATCH v25 2/4] Add bool param in smgrnblocks() for cached blocks. --- 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 | 12 ++++++++++-- src/include/storage/smgr.h | 3 ++- 9 files changed, 26 insertions(+), 17 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 dbbd3aa..4dc2ba8 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++) { @@ -720,7 +720,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 e549fa1..ae001fe 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -739,7 +739,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) { @@ -2855,7 +2855,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..a2577cb 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -553,16 +553,24 @@ smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, * supplied relation. */ BlockNumber -smgrnblocks(SMgrRelation reln, ForkNumber forknum) +smgrnblocks(SMgrRelation reln, ForkNumber forknum, bool *accurate) { 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. 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) + { + if (accurate != NULL) + *accurate = 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..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