summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2003-05-10 19:04:30 +0000
committerTom Lane2003-05-10 19:04:30 +0000
commita4e775a263317a23607eb1a6ea8205a185385a4b (patch)
tree17f89b658d7223dc67d77ccf571be2c95dae5973
parentecc8c3652e80e7f444e7abb71206b7381cd1b606 (diff)
Make use of new error context stack mechanism to allow random errors
detected during buffer dump to be labeled with the buffer location. For example, if a page LSN is clobbered, we now produce something like ERROR: XLogFlush: request 2C000000/8468EC8 is not satisfied --- flushed only to 0/8468EF0 CONTEXT: writing block 0 of relation 428946/566240 whereas before there was no convenient way to find out which page had been trashed.
-rw-r--r--src/backend/storage/buffer/bufmgr.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 119cfe92b0d..89087f0fb87 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.135 2003/03/28 20:17:13 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.136 2003/05/10 19:04:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -68,6 +68,7 @@ static void WaitIO(BufferDesc *buf);
static void StartBufferIO(BufferDesc *buf, bool forInput);
static void TerminateBufferIO(BufferDesc *buf);
static void ContinueBufferIO(BufferDesc *buf, bool forInput);
+static void buffer_write_error_callback(void *arg);
/*
* Macro : BUFFER_IS_BROKEN
@@ -699,14 +700,24 @@ BufferSync(void)
{
int i;
BufferDesc *bufHdr;
- Buffer buffer;
- int status;
- RelFileNode rnode;
- XLogRecPtr recptr;
- Relation reln = NULL;
+ ErrorContextCallback errcontext;
+
+ /* Setup error traceback support for ereport() */
+ errcontext.callback = buffer_write_error_callback;
+ errcontext.arg = NULL;
+ errcontext.previous = error_context_stack;
+ error_context_stack = &errcontext;
for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++)
{
+ Buffer buffer;
+ int status;
+ RelFileNode rnode;
+ XLogRecPtr recptr;
+ Relation reln;
+
+ errcontext.arg = bufHdr;
+
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
if (!(bufHdr->flags & BM_VALID))
@@ -834,6 +845,8 @@ BufferSync(void)
RelationDecrementReferenceCount(reln);
}
+ /* Pop the error context stack */
+ error_context_stack = errcontext.previous;
}
/*
@@ -1011,12 +1024,19 @@ BufferReplace(BufferDesc *bufHdr)
Relation reln;
XLogRecPtr recptr;
int status;
+ ErrorContextCallback errcontext;
/* To check if block content changed while flushing. - vadim 01/17/97 */
bufHdr->flags &= ~BM_JUST_DIRTIED;
LWLockRelease(BufMgrLock);
+ /* Setup error traceback support for ereport() */
+ errcontext.callback = buffer_write_error_callback;
+ errcontext.arg = bufHdr;
+ errcontext.previous = error_context_stack;
+ error_context_stack = &errcontext;
+
/*
* No need to lock buffer context - no one should be able to end
* ReadBuffer
@@ -1043,6 +1063,9 @@ BufferReplace(BufferDesc *bufHdr)
if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln);
+ /* Pop the error context stack */
+ error_context_stack = errcontext.previous;
+
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
if (status == SM_FAIL)
@@ -1380,12 +1403,20 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
BufferDesc *bufHdr;
XLogRecPtr recptr;
int status;
+ ErrorContextCallback errcontext;
+
+ /* Setup error traceback support for ereport() */
+ errcontext.callback = buffer_write_error_callback;
+ errcontext.arg = NULL;
+ errcontext.previous = error_context_stack;
+ error_context_stack = &errcontext;
if (rel->rd_istemp)
{
for (i = 0; i < NLocBuffer; i++)
{
bufHdr = &LocalBufferDescriptors[i];
+ errcontext.arg = bufHdr;
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
{
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
@@ -1395,6 +1426,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
(char *) MAKE_PTR(bufHdr->data));
if (status == SM_FAIL)
{
+ error_context_stack = errcontext.previous;
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
RelationGetRelationName(rel), firstDelBlock,
bufHdr->tag.blockNum);
@@ -1405,6 +1437,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
}
if (LocalRefCount[i] > 0)
{
+ error_context_stack = errcontext.previous;
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
RelationGetRelationName(rel), firstDelBlock,
bufHdr->tag.blockNum, LocalRefCount[i]);
@@ -1414,6 +1447,10 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
bufHdr->tag.rnode.relNode = InvalidOid;
}
}
+
+ /* Pop the error context stack */
+ error_context_stack = errcontext.previous;
+
return 0;
}
@@ -1422,6 +1459,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
for (i = 0; i < NBuffers; i++)
{
bufHdr = &BufferDescriptors[i];
+ errcontext.arg = bufHdr;
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
{
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
@@ -1483,6 +1521,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
if (!(bufHdr->flags & BM_FREE))
{
LWLockRelease(BufMgrLock);
+ error_context_stack = errcontext.previous;
elog(WARNING, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
RelationGetRelationName(rel), firstDelBlock,
bufHdr->tag.blockNum,
@@ -1493,7 +1532,12 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
BufTableDelete(bufHdr);
}
}
+
LWLockRelease(BufMgrLock);
+
+ /* Pop the error context stack */
+ error_context_stack = errcontext.previous;
+
return 0;
}
@@ -2083,3 +2127,17 @@ BufferGetFileNode(Buffer buffer)
return (bufHdr->tag.rnode);
}
+
+/*
+ * Error context callback for errors occurring during buffer writes.
+ */
+static void
+buffer_write_error_callback(void *arg)
+{
+ BufferDesc *bufHdr = (BufferDesc *) arg;
+
+ if (bufHdr != NULL)
+ errcontext("writing block %u of relation %u/%u",
+ bufHdr->tag.blockNum,
+ bufHdr->tag.rnode.tblNode, bufHdr->tag.rnode.relNode);
+}