mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
DropRelFileNodeBuffers failed to fix the state of the lookup hash table
that was added to localbuf.c in 8.1; therefore, applying it to a temp table left corrupt lookup state in memory. The only case where this had a significant chance of causing problems was an ON COMMIT DELETE ROWS temp table; the other possible paths left bogus state that was unlikely to be used again. Per report from Csaba Nagy.
This commit is contained in:
parent
84bb3876bc
commit
c859308aba
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.198 2005/10/27 17:07:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.199 2005/11/17 17:42:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1384,34 +1384,17 @@ DropRelFileNodeBuffers(RelFileNode rnode, bool istemp,
|
|||||||
BlockNumber firstDelBlock)
|
BlockNumber firstDelBlock)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
volatile BufferDesc *bufHdr;
|
|
||||||
|
|
||||||
if (istemp)
|
if (istemp)
|
||||||
{
|
{
|
||||||
for (i = 0; i < NLocBuffer; i++)
|
DropRelFileNodeLocalBuffers(rnode, firstDelBlock);
|
||||||
{
|
|
||||||
bufHdr = &LocalBufferDescriptors[i];
|
|
||||||
if (RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
|
|
||||||
bufHdr->tag.blockNum >= firstDelBlock)
|
|
||||||
{
|
|
||||||
if (LocalRefCount[i] != 0)
|
|
||||||
elog(ERROR, "block %u of %u/%u/%u is still referenced (local %u)",
|
|
||||||
bufHdr->tag.blockNum,
|
|
||||||
bufHdr->tag.rnode.spcNode,
|
|
||||||
bufHdr->tag.rnode.dbNode,
|
|
||||||
bufHdr->tag.rnode.relNode,
|
|
||||||
LocalRefCount[i]);
|
|
||||||
CLEAR_BUFFERTAG(bufHdr->tag);
|
|
||||||
bufHdr->flags = 0;
|
|
||||||
bufHdr->usage_count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NBuffers; i++)
|
for (i = 0; i < NBuffers; i++)
|
||||||
{
|
{
|
||||||
bufHdr = &BufferDescriptors[i];
|
volatile BufferDesc *bufHdr = &BufferDescriptors[i];
|
||||||
|
|
||||||
LockBufHdr(bufHdr);
|
LockBufHdr(bufHdr);
|
||||||
if (RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
|
if (RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
|
||||||
bufHdr->tag.blockNum >= firstDelBlock)
|
bufHdr->tag.blockNum >= firstDelBlock)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.70 2005/10/15 02:49:25 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.71 2005/11/17 17:42:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -241,6 +241,52 @@ WriteLocalBuffer(Buffer buffer, bool release)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DropRelFileNodeLocalBuffers
|
||||||
|
* This function removes from the buffer pool all the pages of the
|
||||||
|
* specified relation that have block numbers >= firstDelBlock.
|
||||||
|
* (In particular, with firstDelBlock = 0, all pages are removed.)
|
||||||
|
* Dirty pages are simply dropped, without bothering to write them
|
||||||
|
* out first. Therefore, this is NOT rollback-able, and so should be
|
||||||
|
* used only with extreme caution!
|
||||||
|
*
|
||||||
|
* See DropRelFileNodeBuffers in bufmgr.c for more notes.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
DropRelFileNodeLocalBuffers(RelFileNode rnode, BlockNumber firstDelBlock)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NLocBuffer; i++)
|
||||||
|
{
|
||||||
|
BufferDesc *bufHdr = &LocalBufferDescriptors[i];
|
||||||
|
LocalBufferLookupEnt *hresult;
|
||||||
|
|
||||||
|
if ((bufHdr->flags & BM_TAG_VALID) &&
|
||||||
|
RelFileNodeEquals(bufHdr->tag.rnode, rnode) &&
|
||||||
|
bufHdr->tag.blockNum >= firstDelBlock)
|
||||||
|
{
|
||||||
|
if (LocalRefCount[i] != 0)
|
||||||
|
elog(ERROR, "block %u of %u/%u/%u is still referenced (local %u)",
|
||||||
|
bufHdr->tag.blockNum,
|
||||||
|
bufHdr->tag.rnode.spcNode,
|
||||||
|
bufHdr->tag.rnode.dbNode,
|
||||||
|
bufHdr->tag.rnode.relNode,
|
||||||
|
LocalRefCount[i]);
|
||||||
|
/* Remove entry from hashtable */
|
||||||
|
hresult = (LocalBufferLookupEnt *)
|
||||||
|
hash_search(LocalBufHash, (void *) &bufHdr->tag,
|
||||||
|
HASH_REMOVE, NULL);
|
||||||
|
if (!hresult) /* shouldn't happen */
|
||||||
|
elog(ERROR, "local buffer hash table corrupted");
|
||||||
|
/* Mark buffer invalid */
|
||||||
|
CLEAR_BUFFERTAG(bufHdr->tag);
|
||||||
|
bufHdr->flags = 0;
|
||||||
|
bufHdr->usage_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* InitLocalBuffers -
|
* InitLocalBuffers -
|
||||||
* init the local buffer cache. Since most queries (esp. multi-user ones)
|
* init the local buffer cache. Since most queries (esp. multi-user ones)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/storage/buf_internals.h,v 1.81 2005/10/15 02:49:46 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/storage/buf_internals.h,v 1.82 2005/11/17 17:42:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -198,6 +198,8 @@ extern void BufTableDelete(BufferTag *tagPtr);
|
|||||||
extern BufferDesc *LocalBufferAlloc(Relation reln, BlockNumber blockNum,
|
extern BufferDesc *LocalBufferAlloc(Relation reln, BlockNumber blockNum,
|
||||||
bool *foundPtr);
|
bool *foundPtr);
|
||||||
extern void WriteLocalBuffer(Buffer buffer, bool release);
|
extern void WriteLocalBuffer(Buffer buffer, bool release);
|
||||||
|
extern void DropRelFileNodeLocalBuffers(RelFileNode rnode,
|
||||||
|
BlockNumber firstDelBlock);
|
||||||
extern void AtEOXact_LocalBuffers(bool isCommit);
|
extern void AtEOXact_LocalBuffers(bool isCommit);
|
||||||
|
|
||||||
#endif /* BUFMGR_INTERNALS_H */
|
#endif /* BUFMGR_INTERNALS_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user