From 57030c4cc7ca6d2af8581c04a4307a46b383f01b Mon Sep 17 00:00:00 2001 From: Dilip Kumar Date: Fri, 24 Sep 2021 18:23:39 +0530 Subject: [PATCH v5 4/7] Extend bufmgr interfaces Extend ReadBufferWithoutRelcache interface to take relpersistence as and input and extend DropDatabaseBuffers to take tablespace oid as input. --- src/backend/access/transam/xlogutils.c | 9 ++++++--- src/backend/commands/dbcommands.c | 9 +++------ src/backend/storage/buffer/bufmgr.c | 24 +++++++++++------------- src/include/storage/bufmgr.h | 5 +++-- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 88a1bfd939..e734a91bf7 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -484,7 +484,8 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, { /* page exists in file */ buffer = ReadBufferWithoutRelcache(rnode, forknum, blkno, - mode, NULL); + mode, NULL, + RELPERSISTENCE_PERMANENT); } else { @@ -509,7 +510,8 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, ReleaseBuffer(buffer); } buffer = ReadBufferWithoutRelcache(rnode, forknum, - P_NEW, mode, NULL); + P_NEW, mode, NULL, + RELPERSISTENCE_PERMANENT); } while (BufferGetBlockNumber(buffer) < blkno); /* Handle the corner case that P_NEW returns non-consecutive pages */ @@ -519,7 +521,8 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, LockBuffer(buffer, BUFFER_LOCK_UNLOCK); ReleaseBuffer(buffer); buffer = ReadBufferWithoutRelcache(rnode, forknum, blkno, - mode, NULL); + mode, NULL, + RELPERSISTENCE_PERMANENT); } } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 029fab48df..1d963d8428 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -938,7 +938,7 @@ dropdb(const char *dbname, bool missing_ok, bool force) * is important to ensure that no remaining backend tries to write out a * dirty buffer to the dead database later... */ - DropDatabaseBuffers(db_id); + DropDatabaseBuffers(db_id, InvalidOid); /* * Tell the stats collector to forget it immediately, too. @@ -1220,11 +1220,8 @@ movedb(const char *dbname, const char *tblspcname) * contain valid data again --- but they'd be missing any changes made in * the database while it was in the new tablespace. In any case, freeing * buffers that should never be used again seems worth the cycles. - * - * Note: it'd be sufficient to get rid of buffers matching db_id and - * src_tblspcoid, but bufmgr.c presently provides no API for that. */ - DropDatabaseBuffers(db_id); + DropDatabaseBuffers(db_id, src_tblspcoid); /* * Check for existence of files in the target directory, i.e., objects of @@ -2201,7 +2198,7 @@ dbase_redo(XLogReaderState *record) ReplicationSlotsDropDBSlots(xlrec->db_id); /* Drop pages for this database that are in the shared buffer cache */ - DropDatabaseBuffers(xlrec->db_id); + DropDatabaseBuffers(xlrec->db_id, InvalidOid); /* Also, clean out any fsync requests that might be pending in md.c */ ForgetDatabaseSyncRequests(xlrec->db_id); diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index e88e4e918b..ed54c34031 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -770,24 +770,17 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, /* * ReadBufferWithoutRelcache -- like ReadBufferExtended, but doesn't require * a relcache entry for the relation. - * - * NB: At present, this function may only be used on permanent relations, which - * is OK, because we only use it during XLOG replay. If in the future we - * want to use it on temporary or unlogged relations, we could pass additional - * parameters. */ Buffer ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, - BufferAccessStrategy strategy) + BufferAccessStrategy strategy, char relpersistence) { bool hit; SMgrRelation smgr = smgropen(rnode, InvalidBackendId); - Assert(InRecovery); - - return ReadBuffer_common(smgr, RELPERSISTENCE_PERMANENT, forkNum, blockNum, + return ReadBuffer_common(smgr, relpersistence, forkNum, blockNum, mode, strategy, &hit); } @@ -797,7 +790,7 @@ ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum, * * *hit is set to true if the request was satisfied from shared buffer cache. */ -static Buffer +Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool *hit) @@ -3402,10 +3395,13 @@ FindAndDropRelFileNodeBuffers(RelFileNode rnode, ForkNumber forkNum, * database, to avoid trying to flush data to disk when the directory * tree no longer exists. Implementation is pretty similar to * DropRelFileNodeBuffers() which is for destroying just one relation. + * + * If a valid tablespace oid is passed then it will compare the tablespace + * oid as well otherwise just the db oid. * -------------------------------------------------------------------- */ void -DropDatabaseBuffers(Oid dbid) +DropDatabaseBuffers(Oid dbid, Oid tbsid) { int i; @@ -3423,11 +3419,13 @@ DropDatabaseBuffers(Oid dbid) * As in DropRelFileNodeBuffers, an unlocked precheck should be safe * and saves some cycles. */ - if (bufHdr->tag.rnode.dbNode != dbid) + if (bufHdr->tag.rnode.dbNode != dbid || + (OidIsValid(tbsid) && bufHdr->tag.rnode.spcNode != tbsid)) continue; buf_state = LockBufHdr(bufHdr); - if (bufHdr->tag.rnode.dbNode == dbid) + if (bufHdr->tag.rnode.dbNode == dbid && + (!OidIsValid(tbsid) || bufHdr->tag.rnode.spcNode == tbsid)) InvalidateBuffer(bufHdr); /* releases spinlock */ else UnlockBufHdr(bufHdr, buf_state); diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index cfce23ecbc..237c6a9078 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -184,7 +184,8 @@ extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BufferAccessStrategy strategy); extern Buffer ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, - ReadBufferMode mode, BufferAccessStrategy strategy); + ReadBufferMode mode, BufferAccessStrategy strategy, + char relpersistence); extern void ReleaseBuffer(Buffer buffer); extern void UnlockReleaseBuffer(Buffer buffer); extern void MarkBufferDirty(Buffer buffer); @@ -207,7 +208,7 @@ extern void FlushDatabaseBuffers(Oid dbid); extern void DropRelFileNodeBuffers(struct SMgrRelationData *smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock); extern void DropRelFileNodesAllBuffers(struct SMgrRelationData **smgr_reln, int nnodes); -extern void DropDatabaseBuffers(Oid dbid); +extern void DropDatabaseBuffers(Oid dbid, Oid tbsid); #define RelationGetNumberOfBlocks(reln) \ RelationGetNumberOfBlocksInFork(reln, MAIN_FORKNUM) -- 2.23.0