v13-bmr-0005-Refactor-how-BufferManagerRelations-are-used.patch
text/x-patch
Filename: v13-bmr-0005-Refactor-how-BufferManagerRelations-are-used.patch
Type: text/x-patch
Part: 4
Patch
Format: format-patch
Series: patch v13-0005
Subject: Refactor how BufferManagerRelations are used
| File | + | − |
|---|---|---|
| contrib/bloom/blutils.c | 5 | 3 |
| contrib/pg_prewarm/pg_prewarm.c | 4 | 3 |
| src/backend/access/brin/brin.c | 6 | 4 |
| src/backend/access/brin/brin_revmap.c | 5 | 3 |
| src/backend/access/gin/gininsert.c | 5 | 4 |
| src/backend/access/gin/ginutil.c | 3 | 2 |
| src/backend/access/gist/gist.c | 3 | 2 |
| src/backend/access/gist/gistutil.c | 3 | 2 |
| src/backend/access/hash/hashpage.c | 5 | 4 |
| src/backend/access/heap/hio.c | 3 | 2 |
| src/backend/access/heap/visibilitymap.c | 3 | 1 |
| src/backend/access/nbtree/nbtpage.c | 5 | 2 |
| src/backend/access/spgist/spgutils.c | 5 | 3 |
| src/backend/access/transam/xlogutils.c | 5 | 5 |
| src/backend/commands/sequence.c | 4 | 2 |
| src/backend/storage/aio/read_stream.c | 9 | 23 |
| src/backend/storage/buffer/bufmgr.c | 180 | 194 |
| src/backend/storage/buffer/localbuf.c | 5 | 6 |
| src/backend/storage/freespace/freespace.c | 5 | 1 |
| src/include/storage/buf_internals.h | 1 | 2 |
| src/include/storage/bufmgr.h | 39 | 28 |
| src/include/storage/read_stream.h | 1 | 3 |
From 3da0557b06ef03b190ba1f22522b4cf56fb2a52d Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 28 Mar 2024 21:48:02 +0200
Subject: [PATCH v13-bmr 5/5] Refactor how BufferManagerRelations are used
---
contrib/bloom/blutils.c | 8 +-
contrib/pg_prewarm/pg_prewarm.c | 7 +-
src/backend/access/brin/brin.c | 10 +-
src/backend/access/brin/brin_revmap.c | 8 +-
src/backend/access/gin/gininsert.c | 9 +-
src/backend/access/gin/ginutil.c | 5 +-
src/backend/access/gist/gist.c | 5 +-
src/backend/access/gist/gistutil.c | 5 +-
src/backend/access/hash/hashpage.c | 9 +-
src/backend/access/heap/hio.c | 5 +-
src/backend/access/heap/visibilitymap.c | 4 +-
src/backend/access/nbtree/nbtpage.c | 7 +-
src/backend/access/spgist/spgutils.c | 8 +-
src/backend/access/transam/xlogutils.c | 10 +-
src/backend/commands/sequence.c | 6 +-
src/backend/storage/aio/read_stream.c | 32 +-
src/backend/storage/buffer/bufmgr.c | 374 +++++++++++-----------
src/backend/storage/buffer/localbuf.c | 11 +-
src/backend/storage/freespace/freespace.c | 6 +-
src/include/storage/buf_internals.h | 3 +-
src/include/storage/bufmgr.h | 67 ++--
src/include/storage/read_stream.h | 4 +-
22 files changed, 304 insertions(+), 299 deletions(-)
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c
index 6836129c90d..177c8698278 100644
--- a/contrib/bloom/blutils.c
+++ b/contrib/bloom/blutils.c
@@ -354,8 +354,11 @@ BloomPageAddItem(BloomState *state, Page page, BloomTuple *tuple)
Buffer
BloomNewBuffer(Relation index)
{
+ BufferManagerRelation bmr;
Buffer buffer;
+ InitBMRForRel(&bmr, index, MAIN_FORKNUM, NULL);
+
/* First, try to get a page from FSM */
for (;;)
{
@@ -364,7 +367,7 @@ BloomNewBuffer(Relation index)
if (blkno == InvalidBlockNumber)
break;
- buffer = ReadBuffer(index, blkno);
+ buffer = ReadBufferBMR(&bmr, blkno, RBM_NORMAL);
/*
* We have to guard against the possibility that someone else already
@@ -388,8 +391,7 @@ BloomNewBuffer(Relation index)
}
/* Must extend the file */
- buffer = ExtendBufferedRel(BMR_REL(index), MAIN_FORKNUM, NULL,
- EB_LOCK_FIRST);
+ buffer = ExtendBufferedRel(&bmr, EB_LOCK_FIRST);
return buffer;
}
diff --git a/contrib/pg_prewarm/pg_prewarm.c b/contrib/pg_prewarm/pg_prewarm.c
index f6269562b54..72ec9378581 100644
--- a/contrib/pg_prewarm/pg_prewarm.c
+++ b/contrib/pg_prewarm/pg_prewarm.c
@@ -205,6 +205,9 @@ pg_prewarm(PG_FUNCTION_ARGS)
{
struct pg_prewarm_read_stream_private p;
ReadStream *stream;
+ BufferManagerRelation bmr;
+
+ InitBMRForRel(&bmr, rel, forkNumber, NULL);
/*
* In buffer mode, we actually pull the data into shared_buffers.
@@ -215,9 +218,7 @@ pg_prewarm(PG_FUNCTION_ARGS)
p.last_block = last_block;
stream = read_stream_begin_relation(READ_STREAM_FULL,
- NULL,
- BMR_REL(rel),
- forkNumber,
+ &bmr,
pg_prewarm_read_stream_next_block,
&p,
0);
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 041415a40e7..32b4189314d 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -1088,6 +1088,7 @@ brinbuildCallbackParallel(Relation index,
IndexBuildResult *
brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
{
+ BufferManagerRelation bmr;
IndexBuildResult *result;
double reltuples;
double idxtuples;
@@ -1108,8 +1109,8 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
* whole relation will be rolled back.
*/
- meta = ExtendBufferedRel(BMR_REL(index), MAIN_FORKNUM, NULL,
- EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
+ InitBMRForRel(&bmr, index, MAIN_FORKNUM, NULL);
+ meta = ExtendBufferedRel(&bmr, EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
Assert(BufferGetBlockNumber(meta) == BRIN_METAPAGE_BLKNO);
brin_metapage_init(BufferGetPage(meta), BrinGetPagesPerRange(index),
@@ -1258,11 +1259,12 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
void
brinbuildempty(Relation index)
{
+ BufferManagerRelation bmr;
Buffer metabuf;
/* An empty BRIN index has a metapage only. */
- metabuf = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
- EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
+ InitBMRForRel(&bmr, index, INIT_FORKNUM, NULL);
+ metabuf = ExtendBufferedRel(&bmr, EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
/* Initialize and xlog metabuffer. */
START_CRIT_SECTION();
diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c
index 5a9ed40ab64..15746942f55 100644
--- a/src/backend/access/brin/brin_revmap.c
+++ b/src/backend/access/brin/brin_revmap.c
@@ -528,6 +528,9 @@ revmap_physical_extend(BrinRevmap *revmap)
BlockNumber mapBlk;
BlockNumber nblocks;
Relation irel = revmap->rm_irel;
+ BufferManagerRelation bmr;
+
+ InitBMRForRel(&bmr, irel, MAIN_FORKNUM, NULL);
/*
* Lock the metapage. This locks out concurrent extensions of the revmap,
@@ -553,14 +556,13 @@ revmap_physical_extend(BrinRevmap *revmap)
nblocks = RelationGetNumberOfBlocks(irel);
if (mapBlk < nblocks)
{
- buf = ReadBuffer(irel, mapBlk);
+ buf = ReadBufferBMR(&bmr, mapBlk, RBM_NORMAL);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
page = BufferGetPage(buf);
}
else
{
- buf = ExtendBufferedRel(BMR_REL(irel), MAIN_FORKNUM, NULL,
- EB_LOCK_FIRST);
+ buf = ExtendBufferedRel(&bmr, EB_LOCK_FIRST);
if (BufferGetBlockNumber(buf) != mapBlk)
{
/*
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 71f38be90c3..ccddba919f6 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -433,14 +433,15 @@ ginbuild(Relation heap, Relation index, IndexInfo *indexInfo)
void
ginbuildempty(Relation index)
{
+ BufferManagerRelation bmr;
Buffer RootBuffer,
MetaBuffer;
+ InitBMRForRel(&bmr, index, INIT_FORKNUM, NULL);
+
/* An empty GIN index has two pages. */
- MetaBuffer = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
- EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
- RootBuffer = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
- EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
+ MetaBuffer = ExtendBufferedRel(&bmr, EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
+ RootBuffer = ExtendBufferedRel(&bmr, EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
/* Initialize and xlog metabuffer and root buffer. */
START_CRIT_SECTION();
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 5747ae6a4ca..0da4a218402 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -299,6 +299,7 @@ gintuple_get_key(GinState *ginstate, IndexTuple tuple,
Buffer
GinNewBuffer(Relation index)
{
+ BufferManagerRelation bmr;
Buffer buffer;
/* First, try to get a page from FSM */
@@ -328,8 +329,8 @@ GinNewBuffer(Relation index)
}
/* Must extend the file */
- buffer = ExtendBufferedRel(BMR_REL(index), MAIN_FORKNUM, NULL,
- EB_LOCK_FIRST);
+ InitBMRForRel(&bmr, index, MAIN_FORKNUM, NULL);
+ buffer = ExtendBufferedRel(&bmr, EB_LOCK_FIRST);
return buffer;
}
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index ed4ffa63a77..d1761b73fe2 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -132,11 +132,12 @@ createTempGistContext(void)
void
gistbuildempty(Relation index)
{
+ BufferManagerRelation bmr;
Buffer buffer;
/* Initialize the root page */
- buffer = ExtendBufferedRel(BMR_REL(index), INIT_FORKNUM, NULL,
- EB_SKIP_EXTENSION_LOCK | EB_LOCK_FIRST);
+ InitBMRForRel(&bmr, index, INIT_FORKNUM, NULL);
+ buffer = ExtendBufferedRel(&bmr, EB_SKIP_EXTENSION_LOCK | EB_LOCK_FIRST);
/* Initialize and xlog buffer */
START_CRIT_SECTION();
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index d2d0b36d4ea..1d8a955b093 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -823,6 +823,7 @@ gistcheckpage(Relation rel, Buffer buf)
Buffer
gistNewBuffer(Relation r, Relation heaprel)
{
+ BufferManagerRelation bmr;
Buffer buffer;
/* First, try to get a page from FSM */
@@ -877,8 +878,8 @@ gistNewBuffer(Relation r, Relation heaprel)
}
/* Must extend the file */
- buffer = ExtendBufferedRel(BMR_REL(r), MAIN_FORKNUM, NULL,
- EB_LOCK_FIRST);
+ InitBMRForRel(&bmr, r, MAIN_FORKNUM, NULL);
+ buffer = ExtendBufferedRel(&bmr, EB_LOCK_FIRST);
return buffer;
}
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index d09c349e28f..bab6b22b0b3 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -197,6 +197,7 @@ _hash_initbuf(Buffer buf, uint32 max_bucket, uint32 num_bucket, uint32 flag,
Buffer
_hash_getnewbuf(Relation rel, BlockNumber blkno, ForkNumber forkNum)
{
+ BufferManagerRelation bmr;
BlockNumber nblocks = RelationGetNumberOfBlocksInFork(rel, forkNum);
Buffer buf;
@@ -206,19 +207,19 @@ _hash_getnewbuf(Relation rel, BlockNumber blkno, ForkNumber forkNum)
elog(ERROR, "access to noncontiguous page in hash index \"%s\"",
RelationGetRelationName(rel));
+ InitBMRForRel(&bmr, rel, forkNum, NULL);
+
/* smgr insists we explicitly extend the relation */
if (blkno == nblocks)
{
- buf = ExtendBufferedRel(BMR_REL(rel), forkNum, NULL,
- EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
+ buf = ExtendBufferedRel(&bmr, EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
if (BufferGetBlockNumber(buf) != blkno)
elog(ERROR, "unexpected hash relation size: %u, should be %u",
BufferGetBlockNumber(buf), blkno);
}
else
{
- buf = ReadBufferExtended(rel, forkNum, blkno, RBM_ZERO_AND_LOCK,
- NULL);
+ buf = ReadBufferBMR(&bmr, blkno, RBM_ZERO_AND_LOCK);
}
/* ref count and lock type are correct */
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index 7c662cdf46e..f17ffe8a64b 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -246,6 +246,7 @@ RelationAddBlocks(Relation relation, BulkInsertState bistate,
uint32 not_in_fsm_pages;
Buffer buffer;
Page page;
+ BufferManagerRelation bmr;
/*
* Determine by how many pages to try to extend by.
@@ -338,8 +339,8 @@ RelationAddBlocks(Relation relation, BulkInsertState bistate,
* [auto]vacuum trying to truncate later pages as REL_TRUNCATE_MINIMUM is
* way larger.
*/
- first_block = ExtendBufferedRelBy(BMR_REL(relation), MAIN_FORKNUM,
- bistate ? bistate->strategy : NULL,
+ InitBMRForRel(&bmr, relation, MAIN_FORKNUM, bistate ? bistate->strategy : NULL);
+ first_block = ExtendBufferedRelBy(&bmr,
EB_LOCK_FIRST,
extend_by_pages,
victim_buffers,
diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c
index 1ab6c865e3c..e04752adecd 100644
--- a/src/backend/access/heap/visibilitymap.c
+++ b/src/backend/access/heap/visibilitymap.c
@@ -626,9 +626,11 @@ vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
static Buffer
vm_extend(Relation rel, BlockNumber vm_nblocks)
{
+ BufferManagerRelation bmr;
Buffer buf;
- buf = ExtendBufferedRelTo(BMR_REL(rel), VISIBILITYMAP_FORKNUM, NULL,
+ InitBMRForRel(&bmr, rel, VISIBILITYMAP_FORKNUM, NULL);
+ buf = ExtendBufferedRelTo(&bmr,
EB_CREATE_FORK_IF_NEEDED |
EB_CLEAR_SIZE_CACHE,
vm_nblocks,
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 01bbece6bfd..6f34ed36ad3 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -868,12 +868,15 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
Buffer
_bt_allocbuf(Relation rel, Relation heaprel)
{
+ BufferManagerRelation bmr;
Buffer buf;
BlockNumber blkno;
Page page;
Assert(heaprel != NULL);
+ InitBMRForRel(&bmr, rel, MAIN_FORKNUM, NULL);
+
/*
* First see if the FSM knows of any free pages.
*
@@ -903,7 +906,7 @@ _bt_allocbuf(Relation rel, Relation heaprel)
blkno = GetFreeIndexPage(rel);
if (blkno == InvalidBlockNumber)
break;
- buf = ReadBuffer(rel, blkno);
+ buf = ReadBufferBMR(&bmr, blkno, RBM_NORMAL);
if (_bt_conditionallockbuf(rel, buf))
{
page = BufferGetPage(buf);
@@ -975,7 +978,7 @@ _bt_allocbuf(Relation rel, Relation heaprel)
* otherwise would make, as we can't use _bt_lockbuf() without introducing
* a race.
*/
- buf = ExtendBufferedRel(BMR_REL(rel), MAIN_FORKNUM, NULL, EB_LOCK_FIRST);
+ buf = ExtendBufferedRel(&bmr, EB_LOCK_FIRST);
if (!RelationUsesLocalBuffers(rel))
VALGRIND_MAKE_MEM_DEFINED(BufferGetPage(buf), BLCKSZ);
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index 3f793125f74..528bd6d3bfa 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -374,8 +374,11 @@ initSpGistState(SpGistState *state, Relation index)
Buffer
SpGistNewBuffer(Relation index)
{
+ BufferManagerRelation bmr;
Buffer buffer;
+ InitBMRForRel(&bmr, index, MAIN_FORKNUM, NULL);
+
/* First, try to get a page from FSM */
for (;;)
{
@@ -391,7 +394,7 @@ SpGistNewBuffer(Relation index)
if (SpGistBlockIsFixed(blkno))
continue;
- buffer = ReadBuffer(index, blkno);
+ buffer = ReadBufferBMR(&bmr, blkno, RBM_NORMAL);
/*
* We have to guard against the possibility that someone else already
@@ -414,8 +417,7 @@ SpGistNewBuffer(Relation index)
ReleaseBuffer(buffer);
}
- buffer = ExtendBufferedRel(BMR_REL(index), MAIN_FORKNUM, NULL,
- EB_LOCK_FIRST);
+ buffer = ExtendBufferedRel(&bmr, EB_LOCK_FIRST);
return buffer;
}
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5295b85fe07..ca055a85bb1 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -472,6 +472,7 @@ XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum,
BlockNumber blkno, ReadBufferMode mode,
Buffer recent_buffer)
{
+ BufferManagerRelation bmr;
BlockNumber lastblock;
Buffer buffer;
SMgrRelation smgr;
@@ -502,11 +503,11 @@ XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum,
lastblock = smgrnblocks(smgr, forknum);
+ InitBMRForSMgr(&bmr, smgr, RELPERSISTENCE_PERMANENT, forknum, NULL);
if (blkno < lastblock)
{
/* page exists in file */
- buffer = ReadBufferWithoutRelcache(rlocator, forknum, blkno,
- mode, NULL, true);
+ buffer = ReadBufferBMR(&bmr, blkno, mode);
}
else
{
@@ -521,9 +522,8 @@ XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum,
/* OK to extend the file */
/* we do this in recovery only - no rel-extension lock needed */
Assert(InRecovery);
- buffer = ExtendBufferedRelTo(BMR_SMGR(smgr, RELPERSISTENCE_PERMANENT),
- forknum,
- NULL,
+
+ buffer = ExtendBufferedRelTo(&bmr,
EB_PERFORMING_RECOVERY |
EB_SKIP_EXTENSION_LOCK,
blkno + 1,
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 46103561c31..ac125407932 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -362,11 +362,13 @@ fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum)
Page page;
sequence_magic *sm;
OffsetNumber offnum;
+ BufferManagerRelation bmr;
+
+ InitBMRForRel(&bmr, rel, forkNum, NULL);
/* Initialize first page of relation with special magic number */
- buf = ExtendBufferedRel(BMR_REL(rel), forkNum, NULL,
- EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
+ buf = ExtendBufferedRel(&bmr, EB_LOCK_FIRST | EB_SKIP_EXTENSION_LOCK);
Assert(BufferGetBlockNumber(buf) == 0);
page = BufferGetPage(buf);
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 6b4b97372c7..6ee81e5fee9 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -116,6 +116,8 @@ struct ReadStream
int16 distance;
bool advice_enabled;
+ BufferManagerRelation bmr;
+
/*
* Sometimes we need to be able to 'unget' a block number to resolve a
* flow control problem when I/Os are split.
@@ -375,9 +377,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
*/
ReadStream *
read_stream_begin_relation(int flags,
- BufferAccessStrategy strategy,
- BufferManagerRelation bmr,
- ForkNumber forknum,
+ BufferManagerRelation *bmr,
ReadStreamBlockNumberCB callback,
void *callback_private_data,
size_t per_buffer_data_size)
@@ -389,23 +389,16 @@ read_stream_begin_relation(int flags,
uint32 max_pinned_buffers;
Oid tablespace_id;
- /* Make sure our bmr's smgr and persistent are populated. */
- if (bmr.smgr == NULL)
- {
- bmr.smgr = RelationGetSmgr(bmr.rel);
- bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
- }
-
/*
* Decide how many I/Os we will allow to run at the same time. That
* currently means advice to the kernel to tell it that we will soon read.
* This number also affects how far we look ahead for opportunities to
* start more I/Os.
*/
- tablespace_id = bmr.smgr->smgr_rlocator.locator.spcOid;
+ tablespace_id = bmr->smgr->smgr_rlocator.locator.spcOid;
if (!OidIsValid(MyDatabaseId) ||
- (bmr.rel && IsCatalogRelation(bmr.rel)) ||
- IsCatalogRelationOid(bmr.smgr->smgr_rlocator.locator.relNumber))
+ (bmr->rel && IsCatalogRelation(bmr->rel)) ||
+ IsCatalogRelationOid(bmr->smgr->smgr_rlocator.locator.relNumber))
{
/*
* Avoid circularity while trying to look up tablespace settings or
@@ -432,7 +425,7 @@ read_stream_begin_relation(int flags,
PG_INT16_MAX - io_combine_limit - 1);
/* Don't allow this backend to pin more than its share of buffers. */
- if (SmgrIsTemp(bmr.smgr))
+ if (SmgrIsTemp(bmr->smgr))
LimitAdditionalLocalPins(&max_pinned_buffers);
else
LimitAdditionalPins(&max_pinned_buffers);
@@ -493,12 +486,6 @@ read_stream_begin_relation(int flags,
stream->per_buffer_data_size = per_buffer_data_size;
stream->max_pinned_buffers = max_pinned_buffers;
stream->queue_size = queue_size;
-
- if (!bmr.smgr)
- {
- bmr.smgr = RelationGetSmgr(bmr.rel);
- bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
- }
stream->callback = callback;
stream->callback_private_data = callback_private_data;
@@ -517,11 +504,10 @@ read_stream_begin_relation(int flags,
* initialize parts of the ReadBuffersOperation objects and leave them
* that way, to avoid wasting CPU cycles writing to them for each read.
*/
+ memcpy(&stream->bmr, bmr, sizeof(BufferManagerRelation));
for (int i = 0; i < max_ios; ++i)
{
- stream->ios[i].op.bmr = bmr;
- stream->ios[i].op.forknum = forknum;
- stream->ios[i].op.strategy = strategy;
+ stream->ios[i].op.bmr = &stream->bmr;
}
return stream;
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 7123cbbaa2a..359981b4293 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -479,20 +479,13 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
)
-static Buffer ReadBuffer_common(BufferManagerRelation bmr,
- ForkNumber forkNum, BlockNumber blockNum,
- ReadBufferMode mode, BufferAccessStrategy strategy);
-static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+static BlockNumber ExtendBufferedRelCommon(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
BlockNumber extend_upto,
Buffer *buffers,
uint32 *extended_by);
-static BlockNumber ExtendBufferedRelShared(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+static BlockNumber ExtendBufferedRelShared(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
BlockNumber extend_upto,
@@ -788,6 +781,7 @@ Buffer
ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
ReadBufferMode mode, BufferAccessStrategy strategy)
{
+ BufferManagerRelation bmr;
Buffer buf;
/*
@@ -800,8 +794,8 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary tables of other sessions")));
- buf = ReadBuffer_common(BMR_REL(reln),
- forkNum, blockNum, mode, strategy);
+ InitBMRForRel(&bmr, reln, forkNum, strategy);
+ buf = ReadBufferBMR(&bmr, blockNum, mode);
return buf;
}
@@ -822,27 +816,86 @@ ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum,
BlockNumber blockNum, ReadBufferMode mode,
BufferAccessStrategy strategy, bool permanent)
{
+ BufferManagerRelation bmr;
SMgrRelation smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
- return ReadBuffer_common(BMR_SMGR(smgr, permanent ? RELPERSISTENCE_PERMANENT :
- RELPERSISTENCE_UNLOGGED),
- forkNum, blockNum,
- mode, strategy);
+ InitBMRForSMgr(&bmr, smgr,
+ permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
+ forkNum,
+ strategy);
+
+ return ReadBufferBMR(&bmr, blockNum, mode);
+}
+
+void
+InitBMRForRel(BufferManagerRelation *bmr, Relation rel, ForkNumber forkNum, BufferAccessStrategy strategy)
+{
+ bool isLocalBuf;
+
+ bmr->rel = rel;
+ bmr->smgr = RelationGetSmgr(rel);
+ bmr->relpersistence = rel->rd_rel->relpersistence;
+ bmr->forkNum = forkNum;
+ bmr->strategy = strategy;
+
+ /*
+ * Look up some further information that's needed in ReadBufferBMR
+ * upfront.
+ */
+ isLocalBuf = bmr->relpersistence == RELPERSISTENCE_TEMP;
+ if (isLocalBuf)
+ {
+ bmr->io_context = IOCONTEXT_NORMAL;
+ bmr->io_object = IOOBJECT_TEMP_RELATION;
+ }
+ else
+ {
+ bmr->io_context = IOContextForStrategy(strategy);
+ bmr->io_object = IOOBJECT_RELATION;
+ }
+
+ if (pgstat_should_count_relation(rel))
+ bmr->pgstat_info = rel->pgstat_info;
+ else
+ bmr->pgstat_info = NULL;
+}
+
+void
+InitBMRForSMgr(BufferManagerRelation *bmr, struct SMgrRelationData *srel, char relpersistence, ForkNumber forkNum, BufferAccessStrategy strategy)
+{
+ bool isLocalBuf;
+
+ bmr->rel = NULL;
+ bmr->smgr = srel;
+ bmr->relpersistence = relpersistence;
+ bmr->forkNum = forkNum;
+ bmr->strategy = strategy;
+
+ isLocalBuf = relpersistence == RELPERSISTENCE_TEMP;
+ if (isLocalBuf)
+ {
+ bmr->io_context = IOCONTEXT_NORMAL;
+ bmr->io_object = IOOBJECT_TEMP_RELATION;
+ }
+ else
+ {
+ bmr->io_context = IOContextForStrategy(strategy);
+ bmr->io_object = IOOBJECT_RELATION;
+ }
+
+ bmr->pgstat_info = NULL;
}
/*
* Convenience wrapper around ExtendBufferedRelBy() extending by one block.
*/
Buffer
-ExtendBufferedRel(BufferManagerRelation bmr,
- ForkNumber forkNum,
- BufferAccessStrategy strategy,
- uint32 flags)
+ExtendBufferedRel(BufferManagerRelation *bmr, uint32 flags)
{
Buffer buf;
uint32 extend_by = 1;
- ExtendBufferedRelBy(bmr, forkNum, strategy, flags, extend_by,
+ ExtendBufferedRelBy(bmr, flags, extend_by,
&buf, &extend_by);
return buf;
@@ -866,25 +919,16 @@ ExtendBufferedRel(BufferManagerRelation bmr,
* be empty.
*/
BlockNumber
-ExtendBufferedRelBy(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+ExtendBufferedRelBy(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
Buffer *buffers,
uint32 *extended_by)
{
- Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
- Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
+ Assert(bmr->smgr != NULL);
Assert(extend_by > 0);
- if (bmr.smgr == NULL)
- {
- bmr.smgr = RelationGetSmgr(bmr.rel);
- bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
- }
-
- return ExtendBufferedRelCommon(bmr, fork, strategy, flags,
+ return ExtendBufferedRelCommon(bmr, flags,
extend_by, InvalidBlockNumber,
buffers, extended_by);
}
@@ -898,9 +942,7 @@ ExtendBufferedRelBy(BufferManagerRelation bmr,
* crash recovery).
*/
Buffer
-ExtendBufferedRelTo(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+ExtendBufferedRelTo(BufferManagerRelation *bmr,
uint32 flags,
BlockNumber extend_to,
ReadBufferMode mode)
@@ -910,33 +952,27 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
Buffer buffer = InvalidBuffer;
Buffer buffers[64];
- Assert((bmr.rel != NULL) != (bmr.smgr != NULL));
- Assert(bmr.smgr == NULL || bmr.relpersistence != 0);
+ Assert(bmr->smgr != NULL);
Assert(extend_to != InvalidBlockNumber && extend_to > 0);
- if (bmr.smgr == NULL)
- {
- bmr.smgr = RelationGetSmgr(bmr.rel);
- bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
- }
-
/*
* If desired, create the file if it doesn't exist. If
* smgr_cached_nblocks[fork] is positive then it must exist, no need for
* an smgrexists call.
*/
if ((flags & EB_CREATE_FORK_IF_NEEDED) &&
- (bmr.smgr->smgr_cached_nblocks[fork] == 0 ||
- bmr.smgr->smgr_cached_nblocks[fork] == InvalidBlockNumber) &&
- !smgrexists(bmr.smgr, fork))
+ (bmr->smgr->smgr_cached_nblocks[bmr->forkNum] == 0 ||
+ bmr->smgr->smgr_cached_nblocks[bmr->forkNum] == InvalidBlockNumber) &&
+ !smgrexists(bmr->smgr, bmr->forkNum))
{
- LockRelationForExtension(bmr.rel, ExclusiveLock);
+ Assert(bmr->rel);
+ LockRelationForExtension(bmr->rel, ExclusiveLock);
/* recheck, fork might have been created concurrently */
- if (!smgrexists(bmr.smgr, fork))
- smgrcreate(bmr.smgr, fork, flags & EB_PERFORMING_RECOVERY);
+ if (!smgrexists(bmr->smgr, bmr->forkNum))
+ smgrcreate(bmr->smgr, bmr->forkNum, flags & EB_PERFORMING_RECOVERY);
- UnlockRelationForExtension(bmr.rel, ExclusiveLock);
+ UnlockRelationForExtension(bmr->rel, ExclusiveLock);
}
/*
@@ -944,13 +980,13 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
* kernel.
*/
if (flags & EB_CLEAR_SIZE_CACHE)
- bmr.smgr->smgr_cached_nblocks[fork] = InvalidBlockNumber;
+ bmr->smgr->smgr_cached_nblocks[bmr->forkNum] = InvalidBlockNumber;
/*
* Estimate how many pages we'll need to extend by. This avoids acquiring
* unnecessarily many victim buffers.
*/
- current_size = smgrnblocks(bmr.smgr, fork);
+ current_size = smgrnblocks(bmr->smgr, bmr->forkNum);
/*
* Since no-one else can be looking at the page contents yet, there is no
@@ -969,7 +1005,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
if ((uint64) current_size + num_pages > extend_to)
num_pages = extend_to - current_size;
- first_block = ExtendBufferedRelCommon(bmr, fork, strategy, flags,
+ first_block = ExtendBufferedRelCommon(bmr, flags,
num_pages, extend_to,
buffers, &extended_by);
@@ -994,7 +1030,7 @@ ExtendBufferedRelTo(BufferManagerRelation bmr,
if (buffer == InvalidBuffer)
{
Assert(extended_by == 0);
- buffer = ReadBuffer_common(bmr, fork, extend_to - 1, mode, strategy);
+ buffer = ReadBufferBMR(bmr, extend_to - 1, mode);
}
return buffer;
@@ -1047,75 +1083,59 @@ ZeroBuffer(Buffer buffer, ReadBufferMode mode)
* zero it.
*/
static inline Buffer
-PinBufferForBlock(BufferManagerRelation bmr,
- ForkNumber forkNum,
+PinBufferForBlock(BufferManagerRelation *const bmr,
BlockNumber blockNum,
- BufferAccessStrategy strategy,
bool *foundPtr)
{
BufferDesc *bufHdr;
bool isLocalBuf;
- IOContext io_context;
- IOObject io_object;
Assert(blockNum != P_NEW);
+ Assert(bmr->smgr);
- Assert(bmr.smgr);
-
- isLocalBuf = bmr.relpersistence == RELPERSISTENCE_TEMP;
- if (isLocalBuf)
- {
- io_context = IOCONTEXT_NORMAL;
- io_object = IOOBJECT_TEMP_RELATION;
- }
- else
- {
- io_context = IOContextForStrategy(strategy);
- io_object = IOOBJECT_RELATION;
- }
-
- TRACE_POSTGRESQL_BUFFER_READ_START(forkNum, blockNum,
- bmr.smgr->smgr_rlocator.locator.spcOid,
- bmr.smgr->smgr_rlocator.locator.dbOid,
- bmr.smgr->smgr_rlocator.locator.relNumber,
- bmr.smgr->smgr_rlocator.backend);
+ TRACE_POSTGRESQL_BUFFER_READ_START(bmr->forkNum, blockNum,
+ bmr->smgr->smgr_rlocator.locator.spcOid,
+ bmr->smgr->smgr_rlocator.locator.dbOid,
+ bmr->smgr->smgr_rlocator.locator.relNumber,
+ bmr->smgr->smgr_rlocator.backend);
+ isLocalBuf = bmr->relpersistence == RELPERSISTENCE_TEMP;
if (isLocalBuf)
{
- bufHdr = LocalBufferAlloc(bmr.smgr, forkNum, blockNum, foundPtr);
+ bufHdr = LocalBufferAlloc(bmr->smgr, bmr->forkNum, blockNum, foundPtr);
if (*foundPtr)
pgBufferUsage.local_blks_hit++;
}
else
{
- bufHdr = BufferAlloc(bmr.smgr, bmr.relpersistence, forkNum, blockNum,
- strategy, foundPtr, io_context);
+ bufHdr = BufferAlloc(bmr->smgr, bmr->relpersistence, bmr->forkNum, blockNum,
+ bmr->strategy, foundPtr, bmr->io_context);
if (*foundPtr)
pgBufferUsage.shared_blks_hit++;
}
- if (bmr.rel)
+ if (bmr->pgstat_info)
{
/*
* While pgBufferUsage's "read" counter isn't bumped unless we reach
* WaitReadBuffers() (so, not for hits, and not for buffers that are
* zeroed instead), the per-relation stats always count them.
*/
- pgstat_count_buffer_read(bmr.rel);
+ bmr->pgstat_info->counts.blocks_fetched++;
if (*foundPtr)
- pgstat_count_buffer_hit(bmr.rel);
+ bmr->pgstat_info->counts.blocks_hit++;
}
if (*foundPtr)
{
VacuumPageHit++;
- pgstat_count_io_op(io_object, io_context, IOOP_HIT);
+ pgstat_count_io_op(bmr->io_object, bmr->io_context, IOOP_HIT);
if (VacuumCostActive)
VacuumCostBalance += VacuumCostPageHit;
- TRACE_POSTGRESQL_BUFFER_READ_DONE(forkNum, blockNum,
- bmr.smgr->smgr_rlocator.locator.spcOid,
- bmr.smgr->smgr_rlocator.locator.dbOid,
- bmr.smgr->smgr_rlocator.locator.relNumber,
- bmr.smgr->smgr_rlocator.backend,
+ TRACE_POSTGRESQL_BUFFER_READ_DONE(bmr->forkNum, blockNum,
+ bmr->smgr->smgr_rlocator.locator.spcOid,
+ bmr->smgr->smgr_rlocator.locator.dbOid,
+ bmr->smgr->smgr_rlocator.locator.relNumber,
+ bmr->smgr->smgr_rlocator.backend,
true);
}
@@ -1125,14 +1145,12 @@ PinBufferForBlock(BufferManagerRelation bmr,
/*
* ReadBuffer_common -- common logic for all ReadBuffer variants
*/
-static inline Buffer
-ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
- BlockNumber blockNum, ReadBufferMode mode,
- BufferAccessStrategy strategy)
+Buffer
+ReadBufferBMR(BufferManagerRelation *bmr,
+ BlockNumber blockNum, ReadBufferMode mode)
{
- ReadBuffersOperation operation;
Buffer buffer;
- int flags;
+ bool found;
/*
* Backward compatibility path, most code should use ExtendBufferedRel()
@@ -1151,37 +1169,32 @@ ReadBuffer_common(BufferManagerRelation bmr, ForkNumber forkNum,
if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
flags |= EB_LOCK_FIRST;
- return ExtendBufferedRel(bmr, forkNum, strategy, flags);
+ return ExtendBufferedRel(bmr, flags);
}
+ buffer = PinBufferForBlock(bmr, blockNum, &found);
if (unlikely(mode == RBM_ZERO_AND_CLEANUP_LOCK ||
mode == RBM_ZERO_AND_LOCK))
{
- bool found;
-
- if (bmr.smgr == NULL)
- {
- bmr.smgr = RelationGetSmgr(bmr.rel);
- bmr.relpersistence = bmr.rel->rd_rel->relpersistence;
- }
-
- buffer = PinBufferForBlock(bmr, forkNum, blockNum, strategy, &found);
ZeroBuffer(buffer, mode);
- return buffer;
}
+ else if (!found)
+ {
+ ReadBuffersOperation operation;
+
+ if (mode == RBM_ZERO_ON_ERROR)
+ operation.flags = READ_BUFFERS_ZERO_ON_ERROR;
+ else
+ operation.flags = 0;
+
+ operation.bmr = bmr;
+ operation.buffers = &buffer;
+ operation.blocknum = blockNum;
+ operation.nblocks = 1;
+ operation.io_buffers_len = 1;
- if (mode == RBM_ZERO_ON_ERROR)
- flags = READ_BUFFERS_ZERO_ON_ERROR;
- else
- flags = 0;
- operation.bmr = bmr;
- operation.forknum = forkNum;
- operation.strategy = strategy;
- if (StartReadBuffer(&operation,
- &buffer,
- blockNum,
- flags))
WaitReadBuffers(&operation);
+ }
return buffer;
}
@@ -1223,33 +1236,26 @@ StartReadBuffer(ReadBuffersOperation *operation,
* and the real I/O happens in WaitReadBuffers(). In future work, true I/O
* could be initiated here.
*/
-inline bool
+bool
StartReadBuffers(ReadBuffersOperation *operation,
Buffer *buffers,
BlockNumber blockNum,
int *nblocks,
int flags)
{
+ BufferManagerRelation *bmr = operation->bmr;
int actual_nblocks = *nblocks;
int io_buffers_len = 0;
Assert(*nblocks > 0);
Assert(*nblocks <= MAX_IO_COMBINE_LIMIT);
- if (!operation->bmr.smgr)
- {
- operation->bmr.smgr = RelationGetSmgr(operation->bmr.rel);
- operation->bmr.relpersistence = operation->bmr.rel->rd_rel->relpersistence;
- }
-
for (int i = 0; i < actual_nblocks; ++i)
{
bool found;
- buffers[i] = PinBufferForBlock(operation->bmr,
- operation->forknum,
+ buffers[i] = PinBufferForBlock(bmr,
blockNum + i,
- operation->strategy,
&found);
if (found)
@@ -1294,8 +1300,8 @@ StartReadBuffers(ReadBuffersOperation *operation,
* true asynchronous version we might choose to process only one
* real I/O at a time in that case.
*/
- smgrprefetch(operation->bmr.smgr,
- operation->forknum,
+ smgrprefetch(bmr->smgr,
+ bmr->forkNum,
blockNum,
operation->io_buffers_len);
}
@@ -1328,10 +1334,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
Buffer *buffers;
int nblocks;
BlockNumber blocknum;
- ForkNumber forknum;
bool isLocalBuf;
- IOContext io_context;
- IOObject io_object;
/*
* Currently operations are only allowed to include a read of some range,
@@ -1348,19 +1351,6 @@ WaitReadBuffers(ReadBuffersOperation *operation)
buffers = &operation->buffers[0];
blocknum = operation->blocknum;
- forknum = operation->forknum;
-
- isLocalBuf = operation->bmr.relpersistence == RELPERSISTENCE_TEMP;
- if (isLocalBuf)
- {
- io_context = IOCONTEXT_NORMAL;
- io_object = IOOBJECT_TEMP_RELATION;
- }
- else
- {
- io_context = IOContextForStrategy(operation->strategy);
- io_object = IOOBJECT_RELATION;
- }
/*
* We count all these blocks as read by this backend. This is traditional
@@ -1370,6 +1360,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
* count this as a "hit", and we don't have a separate counter for "miss,
* but another backend completed the read".
*/
+ isLocalBuf = operation->bmr->relpersistence == RELPERSISTENCE_TEMP;
if (isLocalBuf)
pgBufferUsage.local_blks_read += nblocks;
else
@@ -1395,11 +1386,11 @@ WaitReadBuffers(ReadBuffersOperation *operation)
* Report this as a 'hit' for this backend, even though it must
* have started out as a miss in PinBufferForBlock().
*/
- TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, blocknum + i,
- operation->bmr.smgr->smgr_rlocator.locator.spcOid,
- operation->bmr.smgr->smgr_rlocator.locator.dbOid,
- operation->bmr.smgr->smgr_rlocator.locator.relNumber,
- operation->bmr.smgr->smgr_rlocator.backend,
+ TRACE_POSTGRESQL_BUFFER_READ_DONE(operation->bmr->forkNum, blocknum + i,
+ operation->bmr->smgr->smgr_rlocator.locator.spcOid,
+ operation->bmr->smgr->smgr_rlocator.locator.dbOid,
+ operation->bmr->smgr->smgr_rlocator.locator.relNumber,
+ operation->bmr->smgr->smgr_rlocator.backend,
true);
continue;
}
@@ -1429,9 +1420,9 @@ WaitReadBuffers(ReadBuffersOperation *operation)
}
io_start = pgstat_prepare_io_time(track_io_timing);
- smgrreadv(operation->bmr.smgr, forknum, io_first_block, io_pages, io_buffers_len);
- pgstat_count_io_op_time(io_object, io_context, IOOP_READ, io_start,
- io_buffers_len);
+ smgrreadv(operation->bmr->smgr, operation->bmr->forkNum, io_first_block, io_pages, io_buffers_len);
+ pgstat_count_io_op_time(operation->bmr->io_object, operation->bmr->io_context,
+ IOOP_READ, io_start, io_buffers_len);
/* Verify each block we read, and terminate the I/O. */
for (int j = 0; j < io_buffers_len; ++j)
@@ -1460,7 +1451,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s; zeroing out page",
io_first_block + j,
- relpath(operation->bmr.smgr->smgr_rlocator, forknum))));
+ relpath(operation->bmr->smgr->smgr_rlocator, operation->bmr->forkNum))));
memset(bufBlock, 0, BLCKSZ);
}
else
@@ -1468,7 +1459,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s",
io_first_block + j,
- relpath(operation->bmr.smgr->smgr_rlocator, forknum))));
+ relpath(operation->bmr->smgr->smgr_rlocator, operation->bmr->forkNum))));
}
/* Terminate I/O and set BM_VALID. */
@@ -1486,11 +1477,11 @@ WaitReadBuffers(ReadBuffersOperation *operation)
}
/* Report I/Os as completing individually. */
- TRACE_POSTGRESQL_BUFFER_READ_DONE(forknum, io_first_block + j,
- operation->bmr.smgr->smgr_rlocator.locator.spcOid,
- operation->bmr.smgr->smgr_rlocator.locator.dbOid,
- operation->bmr.smgr->smgr_rlocator.locator.relNumber,
- operation->bmr.smgr->smgr_rlocator.backend,
+ TRACE_POSTGRESQL_BUFFER_READ_DONE(operation->bmr->forkNum, io_first_block + j,
+ operation->bmr->smgr->smgr_rlocator.locator.spcOid,
+ operation->bmr->smgr->smgr_rlocator.locator.dbOid,
+ operation->bmr->smgr->smgr_rlocator.locator.relNumber,
+ operation->bmr->smgr->smgr_rlocator.backend,
false);
}
@@ -2061,9 +2052,7 @@ LimitAdditionalPins(uint32 *additional_pins)
* avoid duplicating the tracing and relpersistence related logic.
*/
static BlockNumber
-ExtendBufferedRelCommon(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+ExtendBufferedRelCommon(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
BlockNumber extend_upto,
@@ -2072,28 +2061,28 @@ ExtendBufferedRelCommon(BufferManagerRelation bmr,
{
BlockNumber first_block;
- TRACE_POSTGRESQL_BUFFER_EXTEND_START(fork,
- bmr.smgr->smgr_rlocator.locator.spcOid,
- bmr.smgr->smgr_rlocator.locator.dbOid,
- bmr.smgr->smgr_rlocator.locator.relNumber,
- bmr.smgr->smgr_rlocator.backend,
+ TRACE_POSTGRESQL_BUFFER_EXTEND_START(bmr->forkNum,
+ bmr->smgr->smgr_rlocator.locator.spcOid,
+ bmr->smgr->smgr_rlocator.locator.dbOid,
+ bmr->smgr->smgr_rlocator.locator.relNumber,
+ bmr->smgr->smgr_rlocator.backend,
extend_by);
- if (bmr.relpersistence == RELPERSISTENCE_TEMP)
- first_block = ExtendBufferedRelLocal(bmr, fork, flags,
+ if (bmr->relpersistence == RELPERSISTENCE_TEMP)
+ first_block = ExtendBufferedRelLocal(bmr, flags,
extend_by, extend_upto,
buffers, &extend_by);
else
- first_block = ExtendBufferedRelShared(bmr, fork, strategy, flags,
+ first_block = ExtendBufferedRelShared(bmr, flags,
extend_by, extend_upto,
buffers, &extend_by);
*extended_by = extend_by;
- TRACE_POSTGRESQL_BUFFER_EXTEND_DONE(fork,
- bmr.smgr->smgr_rlocator.locator.spcOid,
- bmr.smgr->smgr_rlocator.locator.dbOid,
- bmr.smgr->smgr_rlocator.locator.relNumber,
- bmr.smgr->smgr_rlocator.backend,
+ TRACE_POSTGRESQL_BUFFER_EXTEND_DONE(bmr->forkNum,
+ bmr->smgr->smgr_rlocator.locator.spcOid,
+ bmr->smgr->smgr_rlocator.locator.dbOid,
+ bmr->smgr->smgr_rlocator.locator.relNumber,
+ bmr->smgr->smgr_rlocator.backend,
*extended_by,
first_block);
@@ -2105,9 +2094,7 @@ ExtendBufferedRelCommon(BufferManagerRelation bmr,
* shared buffers.
*/
static BlockNumber
-ExtendBufferedRelShared(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+ExtendBufferedRelShared(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
BlockNumber extend_upto,
@@ -2115,7 +2102,6 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
uint32 *extended_by)
{
BlockNumber first_block;
- IOContext io_context = IOContextForStrategy(strategy);
instr_time io_start;
LimitAdditionalPins(&extend_by);
@@ -2134,7 +2120,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
{
Block buf_block;
- buffers[i] = GetVictimBuffer(strategy, io_context);
+ buffers[i] = GetVictimBuffer(bmr->strategy, bmr->io_context);
buf_block = BufHdrGetBlock(GetBufferDescriptor(buffers[i] - 1));
/* new buffers are zero-filled */
@@ -2152,16 +2138,16 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
* we get the lock.
*/
if (!(flags & EB_SKIP_EXTENSION_LOCK))
- LockRelationForExtension(bmr.rel, ExclusiveLock);
+ LockRelationForExtension(bmr->rel, ExclusiveLock);
/*
* If requested, invalidate size cache, so that smgrnblocks asks the
* kernel.
*/
if (flags & EB_CLEAR_SIZE_CACHE)
- bmr.smgr->smgr_cached_nblocks[fork] = InvalidBlockNumber;
+ bmr->smgr->smgr_cached_nblocks[bmr->forkNum] = InvalidBlockNumber;
- first_block = smgrnblocks(bmr.smgr, fork);
+ first_block = smgrnblocks(bmr->smgr, bmr->forkNum);
/*
* Now that we have the accurate relation size, check if the caller wants
@@ -2193,7 +2179,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
if (extend_by == 0)
{
if (!(flags & EB_SKIP_EXTENSION_LOCK))
- UnlockRelationForExtension(bmr.rel, ExclusiveLock);
+ UnlockRelationForExtension(bmr->rel, ExclusiveLock);
*extended_by = extend_by;
return first_block;
}
@@ -2204,7 +2190,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend relation %s beyond %u blocks",
- relpath(bmr.smgr->smgr_rlocator, fork),
+ relpath(bmr->smgr->smgr_rlocator, bmr->forkNum),
MaxBlockNumber)));
/*
@@ -2226,7 +2212,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
ResourceOwnerEnlarge(CurrentResourceOwner);
ReservePrivateRefCountEntry();
- InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i);
+ InitBufferTag(&tag, &bmr->smgr->smgr_rlocator.locator, bmr->forkNum, first_block + i);
hash = BufTableHashCode(&tag);
partition_lock = BufMappingPartitionLock(hash);
@@ -2258,7 +2244,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
* Pin the existing buffer before releasing the partition lock,
* preventing it from being evicted.
*/
- valid = PinBuffer(existing_hdr, strategy);
+ valid = PinBuffer(existing_hdr, bmr->strategy);
LWLockRelease(partition_lock);
@@ -2275,7 +2261,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
if (valid && !PageIsNew((Page) buf_block))
ereport(ERROR,
(errmsg("unexpected data beyond EOF in block %u of relation %s",
- existing_hdr->tag.blockNum, relpath(bmr.smgr->smgr_rlocator, fork)),
+ existing_hdr->tag.blockNum, relpath(bmr->smgr->smgr_rlocator, bmr->forkNum)),
errhint("This has been seen to occur with buggy kernels; consider updating your system.")));
/*
@@ -2309,7 +2295,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
victim_buf_hdr->tag = tag;
buf_state |= BM_TAG_VALID | BUF_USAGECOUNT_ONE;
- if (bmr.relpersistence == RELPERSISTENCE_PERMANENT || fork == INIT_FORKNUM)
+ if (bmr->relpersistence == RELPERSISTENCE_PERMANENT || bmr->forkNum == INIT_FORKNUM)
buf_state |= BM_PERMANENT;
UnlockBufHdr(victim_buf_hdr, buf_state);
@@ -2333,7 +2319,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
*
* We don't need to set checksum for all-zero pages.
*/
- smgrzeroextend(bmr.smgr, fork, first_block, extend_by, false);
+ smgrzeroextend(bmr->smgr, bmr->forkNum, first_block, extend_by, false);
/*
* Release the file-extension lock; it's now OK for someone else to extend
@@ -2343,9 +2329,9 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
* take noticeable time.
*/
if (!(flags & EB_SKIP_EXTENSION_LOCK))
- UnlockRelationForExtension(bmr.rel, ExclusiveLock);
+ UnlockRelationForExtension(bmr->rel, ExclusiveLock);
- pgstat_count_io_op_time(IOOBJECT_RELATION, io_context, IOOP_EXTEND,
+ pgstat_count_io_op_time(IOOBJECT_RELATION, bmr->io_context, IOOP_EXTEND,
io_start, extend_by);
/* Set BM_VALID, terminate IO, and wake up any waiters */
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 985a2c7049c..414109c69fd 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -310,8 +310,7 @@ LimitAdditionalLocalPins(uint32 *additional_pins)
* temporary buffers.
*/
BlockNumber
-ExtendBufferedRelLocal(BufferManagerRelation bmr,
- ForkNumber fork,
+ExtendBufferedRelLocal(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
BlockNumber extend_upto,
@@ -340,7 +339,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
MemSet((char *) buf_block, 0, BLCKSZ);
}
- first_block = smgrnblocks(bmr.smgr, fork);
+ first_block = smgrnblocks(bmr->smgr, bmr->forkNum);
if (extend_upto != InvalidBlockNumber)
{
@@ -359,7 +358,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend relation %s beyond %u blocks",
- relpath(bmr.smgr->smgr_rlocator, fork),
+ relpath(bmr->smgr->smgr_rlocator, bmr->forkNum),
MaxBlockNumber)));
for (uint32 i = 0; i < extend_by; i++)
@@ -376,7 +375,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
/* in case we need to pin an existing buffer below */
ResourceOwnerEnlarge(CurrentResourceOwner);
- InitBufferTag(&tag, &bmr.smgr->smgr_rlocator.locator, fork, first_block + i);
+ InitBufferTag(&tag, &bmr->smgr->smgr_rlocator.locator, bmr->forkNum, first_block + i);
hresult = (LocalBufferLookupEnt *)
hash_search(LocalBufHash, (void *) &tag, HASH_ENTER, &found);
@@ -416,7 +415,7 @@ ExtendBufferedRelLocal(BufferManagerRelation bmr,
io_start = pgstat_prepare_io_time(track_io_timing);
/* actually extend relation */
- smgrzeroextend(bmr.smgr, fork, first_block, extend_by, false);
+ smgrzeroextend(bmr->smgr, bmr->forkNum, first_block, extend_by, false);
pgstat_count_io_op_time(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EXTEND,
io_start, extend_by);
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index bcdb1821938..5dd584217ac 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -605,7 +605,11 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend)
static Buffer
fsm_extend(Relation rel, BlockNumber fsm_nblocks)
{
- return ExtendBufferedRelTo(BMR_REL(rel), FSM_FORKNUM, NULL,
+ BufferManagerRelation bmr;
+
+ InitBMRForRel(&bmr, rel, FSM_FORKNUM, NULL);
+
+ return ExtendBufferedRelTo(&bmr,
EB_CREATE_FORK_IF_NEEDED |
EB_CLEAR_SIZE_CACHE,
fsm_nblocks,
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index f190e6e5e46..88c91c4867c 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -451,8 +451,7 @@ extern PrefetchBufferResult PrefetchLocalBuffer(SMgrRelation smgr,
BlockNumber blockNum);
extern BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum, bool *foundPtr);
-extern BlockNumber ExtendBufferedRelLocal(BufferManagerRelation bmr,
- ForkNumber fork,
+extern BlockNumber ExtendBufferedRelLocal(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
BlockNumber extend_upto,
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 241f68c45e1..1c7748019db 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -14,6 +14,7 @@
#ifndef BUFMGR_H
#define BUFMGR_H
+#include "pgstat.h"
#include "port/pg_iovec.h"
#include "storage/block.h"
#include "storage/buf.h"
@@ -92,22 +93,6 @@ typedef enum ExtendBufferedFlags
EB_LOCK_TARGET = (1 << 5),
} ExtendBufferedFlags;
-/*
- * Some functions identify relations either by relation or smgr +
- * relpersistence. Used via the BMR_REL()/BMR_SMGR() macros below. This
- * allows us to use the same function for both recovery and normal operation.
- */
-typedef struct BufferManagerRelation
-{
- Relation rel;
- struct SMgrRelationData *smgr;
- char relpersistence;
-} BufferManagerRelation;
-
-#define BMR_REL(p_rel) ((BufferManagerRelation){.rel = p_rel})
-#define BMR_SMGR(p_smgr, p_relpersistence) ((BufferManagerRelation){.smgr = p_smgr, .relpersistence = p_relpersistence})
-
-
/* forward declared, to avoid having to expose buf_internals.h here */
struct WritebackContext;
@@ -163,9 +148,36 @@ extern PGDLLIMPORT int32 *LocalRefCount;
#define BUFFER_LOCK_SHARE 1
#define BUFFER_LOCK_EXCLUSIVE 2
+/*
+ * BufferManagerRelation encapsulates what the buffer manager functions like
+ * ReadBuffer() need to know about a relation.
+ *
+ * Initialize with InitBMRForRel() if you have access to the relcache, or
+ * InitBMRForSMgr() for raw access to the underlying smgr. This allows us to
+ * use the same functions for both recovery and normal operation.
+ */
+typedef struct BufferManagerRelation
+{
+ Relation rel;
+ struct SMgrRelationData *smgr;
+ char relpersistence;
+ ForkNumber forkNum;
+ /* admittedly 'strategy' isn't really a property of the relation */
+ BufferAccessStrategy strategy;
+
+ /* private data initialized by InitBMR functions */
+ struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
+ IOContext io_context;
+ IOObject io_object;
+} BufferManagerRelation;
+
+extern void InitBMRForRel(BufferManagerRelation *bmr, Relation rel, ForkNumber forkNum, BufferAccessStrategy strategy);
+extern void InitBMRForSMgr(BufferManagerRelation *bmr, struct SMgrRelationData *srel, char relpersistence, ForkNumber forkNum, BufferAccessStrategy strategy);
+
/*
* prototypes for functions in bufmgr.c
*/
+
extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,
ForkNumber forkNum,
BlockNumber blockNum);
@@ -173,6 +185,13 @@ extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum,
BlockNumber blockNum);
extern bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum,
BlockNumber blockNum, Buffer recent_buffer);
+
+extern Buffer ReadBufferBMR(BufferManagerRelation *bmr, BlockNumber blockNum, ReadBufferMode mode);
+
+/*
+ * compatibility and convenience wrappers which call InitBMRForRel or
+ * InitBMRForSmgr, followed by ReadBufferBMR.
+ */
extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum,
BlockNumber blockNum, ReadBufferMode mode,
@@ -188,9 +207,7 @@ extern Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator,
struct ReadBuffersOperation
{
/* The following members should be set by the caller. */
- BufferManagerRelation bmr;
- ForkNumber forknum;
- BufferAccessStrategy strategy;
+ BufferManagerRelation *bmr;
/* The following private members should not be accessed directly. */
Buffer *buffers;
@@ -223,20 +240,14 @@ extern void CheckBufferIsPinnedOnce(Buffer buffer);
extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation,
BlockNumber blockNum);
-extern Buffer ExtendBufferedRel(BufferManagerRelation bmr,
- ForkNumber forkNum,
- BufferAccessStrategy strategy,
+extern Buffer ExtendBufferedRel(BufferManagerRelation *bmr,
uint32 flags);
-extern BlockNumber ExtendBufferedRelBy(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+extern BlockNumber ExtendBufferedRelBy(BufferManagerRelation *bmr,
uint32 flags,
uint32 extend_by,
Buffer *buffers,
uint32 *extended_by);
-extern Buffer ExtendBufferedRelTo(BufferManagerRelation bmr,
- ForkNumber fork,
- BufferAccessStrategy strategy,
+extern Buffer ExtendBufferedRelTo(BufferManagerRelation *bmr,
uint32 flags,
BlockNumber extend_to,
ReadBufferMode mode);
diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h
index f5dbc087b0b..db962699c15 100644
--- a/src/include/storage/read_stream.h
+++ b/src/include/storage/read_stream.h
@@ -50,9 +50,7 @@ typedef BlockNumber (*ReadStreamBlockNumberCB) (ReadStream *stream,
void *per_buffer_data);
extern ReadStream *read_stream_begin_relation(int flags,
- BufferAccessStrategy strategy,
- BufferManagerRelation bmr,
- ForkNumber forknum,
+ BufferManagerRelation *bmr,
ReadStreamBlockNumberCB callback,
void *callback_private_data,
size_t per_buffer_data_size);
--
2.39.2