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.
This commit is contained in:
parent
ecc8c3652e
commit
a4e775a263
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 StartBufferIO(BufferDesc *buf, bool forInput);
|
||||||
static void TerminateBufferIO(BufferDesc *buf);
|
static void TerminateBufferIO(BufferDesc *buf);
|
||||||
static void ContinueBufferIO(BufferDesc *buf, bool forInput);
|
static void ContinueBufferIO(BufferDesc *buf, bool forInput);
|
||||||
|
static void buffer_write_error_callback(void *arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macro : BUFFER_IS_BROKEN
|
* Macro : BUFFER_IS_BROKEN
|
||||||
@ -699,14 +700,24 @@ BufferSync(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
BufferDesc *bufHdr;
|
BufferDesc *bufHdr;
|
||||||
Buffer buffer;
|
ErrorContextCallback errcontext;
|
||||||
int status;
|
|
||||||
RelFileNode rnode;
|
/* Setup error traceback support for ereport() */
|
||||||
XLogRecPtr recptr;
|
errcontext.callback = buffer_write_error_callback;
|
||||||
Relation reln = NULL;
|
errcontext.arg = NULL;
|
||||||
|
errcontext.previous = error_context_stack;
|
||||||
|
error_context_stack = &errcontext;
|
||||||
|
|
||||||
for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++)
|
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);
|
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
if (!(bufHdr->flags & BM_VALID))
|
if (!(bufHdr->flags & BM_VALID))
|
||||||
@ -834,6 +845,8 @@ BufferSync(void)
|
|||||||
RelationDecrementReferenceCount(reln);
|
RelationDecrementReferenceCount(reln);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pop the error context stack */
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1011,12 +1024,19 @@ BufferReplace(BufferDesc *bufHdr)
|
|||||||
Relation reln;
|
Relation reln;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
int status;
|
int status;
|
||||||
|
ErrorContextCallback errcontext;
|
||||||
|
|
||||||
/* To check if block content changed while flushing. - vadim 01/17/97 */
|
/* To check if block content changed while flushing. - vadim 01/17/97 */
|
||||||
bufHdr->flags &= ~BM_JUST_DIRTIED;
|
bufHdr->flags &= ~BM_JUST_DIRTIED;
|
||||||
|
|
||||||
LWLockRelease(BufMgrLock);
|
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
|
* No need to lock buffer context - no one should be able to end
|
||||||
* ReadBuffer
|
* ReadBuffer
|
||||||
@ -1043,6 +1063,9 @@ BufferReplace(BufferDesc *bufHdr)
|
|||||||
if (reln != (Relation) NULL)
|
if (reln != (Relation) NULL)
|
||||||
RelationDecrementReferenceCount(reln);
|
RelationDecrementReferenceCount(reln);
|
||||||
|
|
||||||
|
/* Pop the error context stack */
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
|
|
||||||
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
|
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
if (status == SM_FAIL)
|
if (status == SM_FAIL)
|
||||||
@ -1380,12 +1403,20 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
BufferDesc *bufHdr;
|
BufferDesc *bufHdr;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
int status;
|
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)
|
if (rel->rd_istemp)
|
||||||
{
|
{
|
||||||
for (i = 0; i < NLocBuffer; i++)
|
for (i = 0; i < NLocBuffer; i++)
|
||||||
{
|
{
|
||||||
bufHdr = &LocalBufferDescriptors[i];
|
bufHdr = &LocalBufferDescriptors[i];
|
||||||
|
errcontext.arg = bufHdr;
|
||||||
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
|
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
|
||||||
{
|
{
|
||||||
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
|
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
|
||||||
@ -1395,6 +1426,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
(char *) MAKE_PTR(bufHdr->data));
|
(char *) MAKE_PTR(bufHdr->data));
|
||||||
if (status == SM_FAIL)
|
if (status == SM_FAIL)
|
||||||
{
|
{
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
|
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
|
||||||
RelationGetRelationName(rel), firstDelBlock,
|
RelationGetRelationName(rel), firstDelBlock,
|
||||||
bufHdr->tag.blockNum);
|
bufHdr->tag.blockNum);
|
||||||
@ -1405,6 +1437,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
}
|
}
|
||||||
if (LocalRefCount[i] > 0)
|
if (LocalRefCount[i] > 0)
|
||||||
{
|
{
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
|
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
|
||||||
RelationGetRelationName(rel), firstDelBlock,
|
RelationGetRelationName(rel), firstDelBlock,
|
||||||
bufHdr->tag.blockNum, LocalRefCount[i]);
|
bufHdr->tag.blockNum, LocalRefCount[i]);
|
||||||
@ -1414,6 +1447,10 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
bufHdr->tag.rnode.relNode = InvalidOid;
|
bufHdr->tag.rnode.relNode = InvalidOid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pop the error context stack */
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1422,6 +1459,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
for (i = 0; i < NBuffers; i++)
|
for (i = 0; i < NBuffers; i++)
|
||||||
{
|
{
|
||||||
bufHdr = &BufferDescriptors[i];
|
bufHdr = &BufferDescriptors[i];
|
||||||
|
errcontext.arg = bufHdr;
|
||||||
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
|
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
|
||||||
{
|
{
|
||||||
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
|
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
|
||||||
@ -1483,6 +1521,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
if (!(bufHdr->flags & BM_FREE))
|
if (!(bufHdr->flags & BM_FREE))
|
||||||
{
|
{
|
||||||
LWLockRelease(BufMgrLock);
|
LWLockRelease(BufMgrLock);
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
elog(WARNING, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
|
elog(WARNING, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
|
||||||
RelationGetRelationName(rel), firstDelBlock,
|
RelationGetRelationName(rel), firstDelBlock,
|
||||||
bufHdr->tag.blockNum,
|
bufHdr->tag.blockNum,
|
||||||
@ -1493,7 +1532,12 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
|
|||||||
BufTableDelete(bufHdr);
|
BufTableDelete(bufHdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LWLockRelease(BufMgrLock);
|
LWLockRelease(BufMgrLock);
|
||||||
|
|
||||||
|
/* Pop the error context stack */
|
||||||
|
error_context_stack = errcontext.previous;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2083,3 +2127,17 @@ BufferGetFileNode(Buffer buffer)
|
|||||||
|
|
||||||
return (bufHdr->tag.rnode);
|
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);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user