aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/bufmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r--src/backend/storage/buffer/bufmgr.c104
1 files changed, 64 insertions, 40 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 456dc423360..281d23136dd 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.236 2008/08/05 15:09:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.237 2008/08/11 11:05:11 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -78,9 +78,10 @@ static bool IsForInput;
static volatile BufferDesc *PinCountWaitBuf = NULL;
-static Buffer ReadBuffer_relcache(Relation reln, BlockNumber blockNum,
- bool zeroPage, BufferAccessStrategy strategy);
-static Buffer ReadBuffer_common(SMgrRelation reln, bool isLocalBuf, BlockNumber blockNum,
+static Buffer ReadBuffer_relcache(Relation reln, ForkNumber forkNum,
+ BlockNumber blockNum, bool zeroPage, BufferAccessStrategy strategy);
+static Buffer ReadBuffer_common(SMgrRelation reln, bool isLocalBuf,
+ ForkNumber forkNum, BlockNumber blockNum,
bool zeroPage, BufferAccessStrategy strategy, bool *hit);
static bool PinBuffer(volatile BufferDesc *buf, BufferAccessStrategy strategy);
static void PinBuffer_Locked(volatile BufferDesc *buf);
@@ -92,7 +93,8 @@ static bool StartBufferIO(volatile BufferDesc *buf, bool forInput);
static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty,
int set_flag_bits);
static void buffer_write_error_callback(void *arg);
-static volatile BufferDesc *BufferAlloc(SMgrRelation smgr, BlockNumber blockNum,
+static volatile BufferDesc *BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
+ BlockNumber blockNum,
BufferAccessStrategy strategy,
bool *foundPtr);
static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln);
@@ -117,7 +119,17 @@ static void AtProcExit_Buffers(int code, Datum arg);
Buffer
ReadBuffer(Relation reln, BlockNumber blockNum)
{
- return ReadBuffer_relcache(reln, blockNum, false, NULL);
+ return ReadBuffer_relcache(reln, MAIN_FORKNUM, blockNum, false, NULL);
+}
+
+/*
+ * ReadBufferWithFork -- same as ReadBuffer, but for accessing relation
+ * forks other than MAIN_FORKNUM.
+ */
+Buffer
+ReadBufferWithFork(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
+{
+ return ReadBuffer_relcache(reln, forkNum, blockNum, false, NULL);
}
/*
@@ -128,7 +140,7 @@ Buffer
ReadBufferWithStrategy(Relation reln, BlockNumber blockNum,
BufferAccessStrategy strategy)
{
- return ReadBuffer_relcache(reln, blockNum, false, strategy);
+ return ReadBuffer_relcache(reln, MAIN_FORKNUM, blockNum, false, strategy);
}
/*
@@ -143,32 +155,32 @@ ReadBufferWithStrategy(Relation reln, BlockNumber blockNum,
* the page is modified and written out. P_NEW is OK, though.
*/
Buffer
-ReadOrZeroBuffer(Relation reln, BlockNumber blockNum)
+ReadOrZeroBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
{
- return ReadBuffer_relcache(reln, blockNum, true, NULL);
+ return ReadBuffer_relcache(reln, forkNum, blockNum, true, NULL);
}
/*
- * ReadBufferWithoutRelcache -- like ReadBuffer, but doesn't require a
+ * ReadBufferWithoutRelcache -- like ReadBuffer, but doesn't require a
* relcache entry for the relation. If zeroPage is true, this behaves
* like ReadOrZeroBuffer rather than ReadBuffer.
*/
Buffer
-ReadBufferWithoutRelcache(RelFileNode rnode, bool isTemp,
- BlockNumber blockNum, bool zeroPage)
+ReadBufferWithoutRelcache(RelFileNode rnode, bool isTemp,
+ ForkNumber forkNum, BlockNumber blockNum, bool zeroPage)
{
bool hit;
SMgrRelation smgr = smgropen(rnode);
- return ReadBuffer_common(smgr, isTemp, blockNum, zeroPage, NULL, &hit);
+ return ReadBuffer_common(smgr, isTemp, forkNum, blockNum, zeroPage, NULL, &hit);
}
/*
- * ReadBuffer_relcache -- common logic for ReadBuffer-variants that
+ * ReadBuffer_relcache -- common logic for ReadBuffer-variants that
* operate on a Relation.
*/
static Buffer
-ReadBuffer_relcache(Relation reln, BlockNumber blockNum,
+ReadBuffer_relcache(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
bool zeroPage, BufferAccessStrategy strategy)
{
bool hit;
@@ -182,7 +194,7 @@ ReadBuffer_relcache(Relation reln, BlockNumber blockNum,
* hit or miss.
*/
pgstat_count_buffer_read(reln);
- buf = ReadBuffer_common(reln->rd_smgr, reln->rd_istemp, blockNum,
+ buf = ReadBuffer_common(reln->rd_smgr, reln->rd_istemp, forkNum, blockNum,
zeroPage, strategy, &hit);
if (hit)
pgstat_count_buffer_hit(reln);
@@ -195,8 +207,9 @@ ReadBuffer_relcache(Relation reln, BlockNumber blockNum,
* *hit is set to true if the request was satisfied from shared buffer cache.
*/
static Buffer
-ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
- bool zeroPage, BufferAccessStrategy strategy, bool *hit)
+ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, ForkNumber forkNum,
+ BlockNumber blockNum, bool zeroPage,
+ BufferAccessStrategy strategy, bool *hit)
{
volatile BufferDesc *bufHdr;
Block bufBlock;
@@ -212,7 +225,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
/* Substitute proper block number if caller asked for P_NEW */
if (isExtend)
- blockNum = smgrnblocks(smgr);
+ blockNum = smgrnblocks(smgr, forkNum);
TRACE_POSTGRESQL_BUFFER_READ_START(blockNum, smgr->smgr_rnode.spcNode,
smgr->smgr_rnode.dbNode, smgr->smgr_rnode.relNode, isLocalBuf);
@@ -220,7 +233,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
if (isLocalBuf)
{
ReadLocalBufferCount++;
- bufHdr = LocalBufferAlloc(smgr, blockNum, &found);
+ bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
if (found)
{
LocalBufferHitCount++;
@@ -239,7 +252,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
* lookup the buffer. IO_IN_PROGRESS is set if the requested block is
* not currently in memory.
*/
- bufHdr = BufferAlloc(smgr, blockNum, strategy, &found);
+ bufHdr = BufferAlloc(smgr, forkNum, blockNum, strategy, &found);
if (found)
{
BufferHitCount++;
@@ -341,7 +354,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
{
/* new buffers are zero-filled */
MemSet((char *) bufBlock, 0, BLCKSZ);
- smgrextend(smgr, blockNum, (char *) bufBlock, isLocalBuf);
+ smgrextend(smgr, forkNum, blockNum, (char *) bufBlock, isLocalBuf);
}
else
{
@@ -353,7 +366,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
MemSet((char *) bufBlock, 0, BLCKSZ);
else
{
- smgrread(smgr, blockNum, (char *) bufBlock);
+ smgrread(smgr, forkNum, blockNum, (char *) bufBlock);
/* check for garbage data */
if (!PageHeaderIsValid((PageHeader) bufBlock))
@@ -363,7 +376,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
ereport(WARNING,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page header in block %u of relation %u/%u/%u; zeroing out page",
- blockNum,
+ blockNum,
smgr->smgr_rnode.spcNode,
smgr->smgr_rnode.dbNode,
smgr->smgr_rnode.relNode)));
@@ -421,7 +434,7 @@ ReadBuffer_common(SMgrRelation smgr, bool isLocalBuf, BlockNumber blockNum,
* No locks are held either at entry or exit.
*/
static volatile BufferDesc *
-BufferAlloc(SMgrRelation smgr,
+BufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum,
BufferAccessStrategy strategy,
bool *foundPtr)
@@ -438,7 +451,7 @@ BufferAlloc(SMgrRelation smgr,
bool valid;
/* create a tag so we can lookup the buffer */
- INIT_BUFFERTAG(newTag, smgr->smgr_rnode, blockNum);
+ INIT_BUFFERTAG(newTag, smgr->smgr_rnode, forkNum, blockNum);
/* determine its hash code and partition lock ID */
newHash = BufTableHashCode(&newTag);
@@ -903,6 +916,7 @@ ReleaseAndReadBuffer(Buffer buffer,
Relation relation,
BlockNumber blockNum)
{
+ ForkNumber forkNum = MAIN_FORKNUM;
volatile BufferDesc *bufHdr;
if (BufferIsValid(buffer))
@@ -912,7 +926,8 @@ ReleaseAndReadBuffer(Buffer buffer,
Assert(LocalRefCount[-buffer - 1] > 0);
bufHdr = &LocalBufferDescriptors[-buffer - 1];
if (bufHdr->tag.blockNum == blockNum &&
- RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node))
+ RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
+ bufHdr->tag.forkNum == forkNum)
return buffer;
ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
LocalRefCount[-buffer - 1]--;
@@ -923,7 +938,8 @@ ReleaseAndReadBuffer(Buffer buffer,
bufHdr = &BufferDescriptors[buffer - 1];
/* we have pin, so it's ok to examine tag without spinlock */
if (bufHdr->tag.blockNum == blockNum &&
- RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node))
+ RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node) &&
+ bufHdr->tag.forkNum == forkNum)
return buffer;
UnpinBuffer(bufHdr, true);
}
@@ -1734,23 +1750,28 @@ BufferGetBlockNumber(Buffer buffer)
}
/*
- * BufferGetFileNode
- * Returns the relation ID (RelFileNode) associated with a buffer.
- *
- * This should make the same checks as BufferGetBlockNumber, but since the
- * two are generally called together, we don't bother.
+ * BufferGetTag
+ * Returns the relfilenode, fork number and block number associated with
+ * a buffer.
*/
-RelFileNode
-BufferGetFileNode(Buffer buffer)
+void
+BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum,
+ BlockNumber *blknum)
{
volatile BufferDesc *bufHdr;
+ /* Do the same checks as BufferGetBlockNumber. */
+ Assert(BufferIsPinned(buffer));
+
if (BufferIsLocal(buffer))
bufHdr = &(LocalBufferDescriptors[-buffer - 1]);
else
bufHdr = &BufferDescriptors[buffer - 1];
- return bufHdr->tag.rnode;
+ /* pinned, so OK to read tag without spinlock */
+ *rnode = bufHdr->tag.rnode;
+ *forknum = bufHdr->tag.forkNum;
+ *blknum = bufHdr->tag.blockNum;
}
/*
@@ -1820,6 +1841,7 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
UnlockBufHdr(buf);
smgrwrite(reln,
+ buf->tag.forkNum,
buf->tag.blockNum,
(char *) BufHdrGetBlock(buf),
false);
@@ -1849,7 +1871,7 @@ RelationGetNumberOfBlocks(Relation relation)
/* Open it at the smgr level if not already done */
RelationOpenSmgr(relation);
- return smgrnblocks(relation->rd_smgr);
+ return smgrnblocks(relation->rd_smgr, MAIN_FORKNUM);
}
/*
@@ -1869,7 +1891,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
rel->rd_targblock = InvalidBlockNumber;
/* Do the real work */
- smgrtruncate(rel->rd_smgr, nblocks, rel->rd_istemp);
+ smgrtruncate(rel->rd_smgr, MAIN_FORKNUM, nblocks, rel->rd_istemp);
}
/* ---------------------------------------------------------------------
@@ -1899,14 +1921,14 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
* --------------------------------------------------------------------
*/
void
-DropRelFileNodeBuffers(RelFileNode rnode, bool istemp,
+DropRelFileNodeBuffers(RelFileNode rnode, ForkNumber forkNum, bool istemp,
BlockNumber firstDelBlock)
{
int i;
if (istemp)
{
- DropRelFileNodeLocalBuffers(rnode, firstDelBlock);
+ DropRelFileNodeLocalBuffers(rnode, forkNum, firstDelBlock);
return;
}
@@ -1916,6 +1938,7 @@ DropRelFileNodeBuffers(RelFileNode rnode, bool istemp,
LockBufHdr(bufHdr);
if (RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
+ bufHdr->tag.forkNum == forkNum &&
bufHdr->tag.blockNum >= firstDelBlock)
InvalidateBuffer(bufHdr); /* releases spinlock */
else
@@ -2055,6 +2078,7 @@ FlushRelationBuffers(Relation rel)
error_context_stack = &errcontext;
smgrwrite(rel->rd_smgr,
+ bufHdr->tag.forkNum,
bufHdr->tag.blockNum,
(char *) LocalBufHdrGetBlock(bufHdr),
true);