Skip to content

Commit a4e775a

Browse files
committed
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.
1 parent ecc8c36 commit a4e775a

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.135 2003/03/28 20:17:13 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.136 2003/05/10 19:04:30 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -68,6 +68,7 @@ static void WaitIO(BufferDesc *buf);
6868
static void StartBufferIO(BufferDesc *buf, bool forInput);
6969
static void TerminateBufferIO(BufferDesc *buf);
7070
static void ContinueBufferIO(BufferDesc *buf, bool forInput);
71+
static void buffer_write_error_callback(void *arg);
7172

7273
/*
7374
* Macro : BUFFER_IS_BROKEN
@@ -699,14 +700,24 @@ BufferSync(void)
699700
{
700701
int i;
701702
BufferDesc *bufHdr;
702-
Buffer buffer;
703-
int status;
704-
RelFileNode rnode;
705-
XLogRecPtr recptr;
706-
Relation reln = NULL;
703+
ErrorContextCallback errcontext;
704+
705+
/* Setup error traceback support for ereport() */
706+
errcontext.callback = buffer_write_error_callback;
707+
errcontext.arg = NULL;
708+
errcontext.previous = error_context_stack;
709+
error_context_stack = &errcontext;
707710

708711
for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++)
709712
{
713+
Buffer buffer;
714+
int status;
715+
RelFileNode rnode;
716+
XLogRecPtr recptr;
717+
Relation reln;
718+
719+
errcontext.arg = bufHdr;
720+
710721
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
711722

712723
if (!(bufHdr->flags & BM_VALID))
@@ -834,6 +845,8 @@ BufferSync(void)
834845
RelationDecrementReferenceCount(reln);
835846
}
836847

848+
/* Pop the error context stack */
849+
error_context_stack = errcontext.previous;
837850
}
838851

839852
/*
@@ -1011,12 +1024,19 @@ BufferReplace(BufferDesc *bufHdr)
10111024
Relation reln;
10121025
XLogRecPtr recptr;
10131026
int status;
1027+
ErrorContextCallback errcontext;
10141028

10151029
/* To check if block content changed while flushing. - vadim 01/17/97 */
10161030
bufHdr->flags &= ~BM_JUST_DIRTIED;
10171031

10181032
LWLockRelease(BufMgrLock);
10191033

1034+
/* Setup error traceback support for ereport() */
1035+
errcontext.callback = buffer_write_error_callback;
1036+
errcontext.arg = bufHdr;
1037+
errcontext.previous = error_context_stack;
1038+
error_context_stack = &errcontext;
1039+
10201040
/*
10211041
* No need to lock buffer context - no one should be able to end
10221042
* ReadBuffer
@@ -1043,6 +1063,9 @@ BufferReplace(BufferDesc *bufHdr)
10431063
if (reln != (Relation) NULL)
10441064
RelationDecrementReferenceCount(reln);
10451065

1066+
/* Pop the error context stack */
1067+
error_context_stack = errcontext.previous;
1068+
10461069
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
10471070

10481071
if (status == SM_FAIL)
@@ -1380,12 +1403,20 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
13801403
BufferDesc *bufHdr;
13811404
XLogRecPtr recptr;
13821405
int status;
1406+
ErrorContextCallback errcontext;
1407+
1408+
/* Setup error traceback support for ereport() */
1409+
errcontext.callback = buffer_write_error_callback;
1410+
errcontext.arg = NULL;
1411+
errcontext.previous = error_context_stack;
1412+
error_context_stack = &errcontext;
13831413

13841414
if (rel->rd_istemp)
13851415
{
13861416
for (i = 0; i < NLocBuffer; i++)
13871417
{
13881418
bufHdr = &LocalBufferDescriptors[i];
1419+
errcontext.arg = bufHdr;
13891420
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
13901421
{
13911422
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
@@ -1395,6 +1426,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
13951426
(char *) MAKE_PTR(bufHdr->data));
13961427
if (status == SM_FAIL)
13971428
{
1429+
error_context_stack = errcontext.previous;
13981430
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
13991431
RelationGetRelationName(rel), firstDelBlock,
14001432
bufHdr->tag.blockNum);
@@ -1405,6 +1437,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
14051437
}
14061438
if (LocalRefCount[i] > 0)
14071439
{
1440+
error_context_stack = errcontext.previous;
14081441
elog(WARNING, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
14091442
RelationGetRelationName(rel), firstDelBlock,
14101443
bufHdr->tag.blockNum, LocalRefCount[i]);
@@ -1414,6 +1447,10 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
14141447
bufHdr->tag.rnode.relNode = InvalidOid;
14151448
}
14161449
}
1450+
1451+
/* Pop the error context stack */
1452+
error_context_stack = errcontext.previous;
1453+
14171454
return 0;
14181455
}
14191456

@@ -1422,6 +1459,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
14221459
for (i = 0; i < NBuffers; i++)
14231460
{
14241461
bufHdr = &BufferDescriptors[i];
1462+
errcontext.arg = bufHdr;
14251463
if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
14261464
{
14271465
if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
@@ -1483,6 +1521,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
14831521
if (!(bufHdr->flags & BM_FREE))
14841522
{
14851523
LWLockRelease(BufMgrLock);
1524+
error_context_stack = errcontext.previous;
14861525
elog(WARNING, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
14871526
RelationGetRelationName(rel), firstDelBlock,
14881527
bufHdr->tag.blockNum,
@@ -1493,7 +1532,12 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
14931532
BufTableDelete(bufHdr);
14941533
}
14951534
}
1535+
14961536
LWLockRelease(BufMgrLock);
1537+
1538+
/* Pop the error context stack */
1539+
error_context_stack = errcontext.previous;
1540+
14971541
return 0;
14981542
}
14991543

@@ -2083,3 +2127,17 @@ BufferGetFileNode(Buffer buffer)
20832127

20842128
return (bufHdr->tag.rnode);
20852129
}
2130+
2131+
/*
2132+
* Error context callback for errors occurring during buffer writes.
2133+
*/
2134+
static void
2135+
buffer_write_error_callback(void *arg)
2136+
{
2137+
BufferDesc *bufHdr = (BufferDesc *) arg;
2138+
2139+
if (bufHdr != NULL)
2140+
errcontext("writing block %u of relation %u/%u",
2141+
bufHdr->tag.blockNum,
2142+
bufHdr->tag.rnode.tblNode, bufHdr->tag.rnode.relNode);
2143+
}

0 commit comments

Comments
 (0)