aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2024-01-31 12:31:02 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2024-01-31 12:31:02 +0200
commit21d9c3ee4ef74e2229341d39811c97f85071c90a (patch)
tree5400cf27276fae4ffa9566f107bb27f084da119c /src/backend/storage/buffer
parent6a8ffe812d194ba6f4f26791b6388a4837d17d6c (diff)
downloadpostgresql-21d9c3ee4ef74e2229341d39811c97f85071c90a.tar.gz
postgresql-21d9c3ee4ef74e2229341d39811c97f85071c90a.zip
Give SMgrRelation pointers a well-defined lifetime.
After calling smgropen(), it was not clear how long you could continue to use the result, because various code paths including cache invalidation could call smgrclose(), which freed the memory. Guarantee that the object won't be destroyed until the end of the current transaction, or in recovery, the commit/abort record that destroys the underlying storage. smgrclose() is now just an alias for smgrrelease(). It closes files and forgets all state except the rlocator, but keeps the SMgrRelation object valid. A new smgrdestroy() function is used by rare places that know there should be no other references to the SMgrRelation. The short version: * smgrclose() is now just an alias for smgrrelease(). It releases resources, but doesn't destroy until EOX * smgrdestroy() now frees memory, and should rarely be used. Existing code should be unaffected, but it is now possible for code that has an SMgrRelation object to use it repeatedly during a transaction as long as the storage hasn't been physically dropped. Such code would normally hold a lock on the relation. This also replaces the "ownership" mechanism of SMgrRelations with a pin counter. An SMgrRelation can now be "pinned", which prevents it from being destroyed at end of transaction. There can be multiple pins on the same SMgrRelation. In practice, the pin mechanism is only used by the relcache, so there cannot be more than one pin on the same SMgrRelation. Except with swap_relation_files XXX Author: Thomas Munro, Heikki Linnakangas Reviewed-by: Robert Haas <robertmhaas@gmail.com> Discussion: https://www.postgresql.org/message-id/CA%2BhUKGJ8NTvqLHz6dqbQnt2c8XCki4r2QvXjBQcXpVwxTY_pvA@mail.gmail.com
Diffstat (limited to 'src/backend/storage/buffer')
-rw-r--r--src/backend/storage/buffer/bufmgr.c32
1 files changed, 10 insertions, 22 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7d601bef6dd..d06014bfb84 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -934,10 +934,6 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
{
LockRelationForExtension(bmr.rel, ExclusiveLock);
- /* could have been closed while waiting for lock */
- if (bmr.rel)
- bmr.smgr = RelationGetSmgr(bmr.rel);
-
/* recheck, fork might have been created concurrently */
if (!smgrexists(bmr.smgr, fork))
smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY);
@@ -1897,11 +1893,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
* we get the lock.
*/
if (!(flags & EB_SKIP_EXTENSION_LOCK))
- {
LockRelationForExtension(bmr.rel, ExclusiveLock);
- if (bmr.rel)
- bmr.smgr = RelationGetSmgr(bmr.rel);
- }
/*
* If requested, invalidate size cache, so that smgrnblocks asks the
@@ -4155,6 +4147,7 @@ FlushRelationBuffers(Relation rel)
{
int i;
BufferDesc *bufHdr;
+ SMgrRelation srel = RelationGetSmgr(rel);
if (RelationUsesLocalBuffers(rel))
{
@@ -4183,7 +4176,7 @@ FlushRelationBuffers(Relation rel)
io_start = pgstat_prepare_io_time(track_io_timing);
- smgrwrite(RelationGetSmgr(rel),
+ smgrwrite(srel,
BufTagGetForkNum(&bufHdr->tag),
bufHdr->tag.blockNum,
localpage,
@@ -4229,7 +4222,7 @@ FlushRelationBuffers(Relation rel)
{
PinBuffer_Locked(bufHdr);
LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
- FlushBuffer(bufHdr, RelationGetSmgr(rel), IOOBJECT_RELATION, IOCONTEXT_NORMAL);
+ FlushBuffer(bufHdr, srel, IOOBJECT_RELATION, IOCONTEXT_NORMAL);
LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
UnpinBuffer(bufHdr);
}
@@ -4442,13 +4435,17 @@ void
CreateAndCopyRelationData(RelFileLocator src_rlocator,
RelFileLocator dst_rlocator, bool permanent)
{
- RelFileLocatorBackend rlocator;
char relpersistence;
+ SMgrRelation src_rel;
+ SMgrRelation dst_rel;
/* Set the relpersistence. */
relpersistence = permanent ?
RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED;
+ src_rel = smgropen(src_rlocator, InvalidBackendId);
+ dst_rel = smgropen(dst_rlocator, InvalidBackendId);
+
/*
* Create and copy all forks of the relation. During create database we
* have a separate cleanup mechanism which deletes complete database
@@ -4465,9 +4462,9 @@ CreateAndCopyRelationData(RelFileLocator src_rlocator,
for (ForkNumber forkNum = MAIN_FORKNUM + 1;
forkNum <= MAX_FORKNUM; forkNum++)
{
- if (smgrexists(smgropen(src_rlocator, InvalidBackendId), forkNum))
+ if (smgrexists(src_rel, forkNum))
{
- smgrcreate(smgropen(dst_rlocator, InvalidBackendId), forkNum, false);
+ smgrcreate(dst_rel, forkNum, false);
/*
* WAL log creation if the relation is persistent, or this is the
@@ -4481,15 +4478,6 @@ CreateAndCopyRelationData(RelFileLocator src_rlocator,
permanent);
}
}
-
- /* close source and destination smgr if exists. */
- rlocator.backend = InvalidBackendId;
-
- rlocator.locator = src_rlocator;
- smgrcloserellocator(rlocator);
-
- rlocator.locator = dst_rlocator;
- smgrcloserellocator(rlocator);
}
/* ---------------------------------------------------------------------