mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Fix for pg_log bug
Submitted by: "Vadim B. Mikheev" <vadim@sable.krasnoyarsk.su>
This commit is contained in:
parent
0318f227ac
commit
aceac3a927
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.2 1996/07/23 05:44:10 scrappy Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.3 1996/09/19 19:50:48 scrappy Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -280,7 +280,7 @@ ReadBufferWithBufferLock(Relation reln,
|
|||||||
* the buffer can tell that the contents are invalid.
|
* the buffer can tell that the contents are invalid.
|
||||||
*/
|
*/
|
||||||
bufHdr->flags |= BM_IO_ERROR;
|
bufHdr->flags |= BM_IO_ERROR;
|
||||||
|
bufHdr->flags &= ~BM_IO_IN_PROGRESS;
|
||||||
} else {
|
} else {
|
||||||
/* IO Succeeded. clear the flags, finish buffer update */
|
/* IO Succeeded. clear the flags, finish buffer update */
|
||||||
|
|
||||||
@ -297,6 +297,9 @@ ReadBufferWithBufferLock(Relation reln,
|
|||||||
|
|
||||||
SpinRelease(BufMgrLock);
|
SpinRelease(BufMgrLock);
|
||||||
|
|
||||||
|
if (status == SM_FAIL)
|
||||||
|
return(InvalidBuffer);
|
||||||
|
|
||||||
return(BufferDescriptorGetBuffer(bufHdr));
|
return(BufferDescriptorGetBuffer(bufHdr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +390,14 @@ BufferAlloc(Relation reln,
|
|||||||
/* GetFreeBuffer will abort if it can't find a free buffer */
|
/* GetFreeBuffer will abort if it can't find a free buffer */
|
||||||
buf = GetFreeBuffer();
|
buf = GetFreeBuffer();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* But it can return buf == NULL if we are in aborting
|
||||||
|
* transaction now and so elog(WARN,...) in GetFreeBuffer
|
||||||
|
* will not abort again.
|
||||||
|
*/
|
||||||
|
if ( buf == NULL )
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There should be exactly one pin on the buffer after
|
* There should be exactly one pin on the buffer after
|
||||||
* it is allocated -- ours. If it had a pin it wouldn't
|
* it is allocated -- ours. If it had a pin it wouldn't
|
||||||
@ -399,6 +410,7 @@ BufferAlloc(Relation reln,
|
|||||||
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 1;
|
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 1;
|
||||||
|
|
||||||
if (buf->flags & BM_DIRTY) {
|
if (buf->flags & BM_DIRTY) {
|
||||||
|
bool smok;
|
||||||
/*
|
/*
|
||||||
* Set BM_IO_IN_PROGRESS to keep anyone from doing anything
|
* Set BM_IO_IN_PROGRESS to keep anyone from doing anything
|
||||||
* with the contents of the buffer while we write it out.
|
* with the contents of the buffer while we write it out.
|
||||||
@ -428,11 +440,38 @@ BufferAlloc(Relation reln,
|
|||||||
* you on machines that don't have spinlocks. If you don't
|
* you on machines that don't have spinlocks. If you don't
|
||||||
* operate with much concurrency, well...
|
* operate with much concurrency, well...
|
||||||
*/
|
*/
|
||||||
(void) BufferReplace(buf, true);
|
smok = BufferReplace(buf, true);
|
||||||
BufferFlushCount++;
|
|
||||||
#ifndef OPTIMIZE_SINGLE
|
#ifndef OPTIMIZE_SINGLE
|
||||||
SpinAcquire(BufMgrLock);
|
SpinAcquire(BufMgrLock);
|
||||||
#endif /* OPTIMIZE_SINGLE */
|
#endif /* OPTIMIZE_SINGLE */
|
||||||
|
|
||||||
|
if ( smok == FALSE )
|
||||||
|
{
|
||||||
|
elog(NOTICE, "BufferAlloc: cannot write block %u for %s/%s",
|
||||||
|
buf->tag.blockNum, buf->sb_dbname, buf->sb_relname);
|
||||||
|
inProgress = FALSE;
|
||||||
|
buf->flags |= BM_IO_ERROR;
|
||||||
|
buf->flags &= ~BM_IO_IN_PROGRESS;
|
||||||
|
#ifdef HAS_TEST_AND_SET
|
||||||
|
S_UNLOCK(&(buf->io_in_progress_lock));
|
||||||
|
#else /* !HAS_TEST_AND_SET */
|
||||||
|
if (buf->refcount > 1)
|
||||||
|
SignalIO(buf);
|
||||||
|
#endif /* !HAS_TEST_AND_SET */
|
||||||
|
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
|
||||||
|
buf->refcount--;
|
||||||
|
if ( buf->refcount == 0 )
|
||||||
|
{
|
||||||
|
AddBufferToFreelist(buf);
|
||||||
|
buf->flags |= BM_FREE;
|
||||||
|
}
|
||||||
|
buf = (BufferDesc *) NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BufferFlushCount++;
|
||||||
|
buf->flags &= ~BM_DIRTY;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Somebody could have pinned the buffer while we were
|
* Somebody could have pinned the buffer while we were
|
||||||
@ -445,7 +484,7 @@ BufferAlloc(Relation reln,
|
|||||||
* no reason to think that we have an immediate disaster on
|
* no reason to think that we have an immediate disaster on
|
||||||
* our hands.
|
* our hands.
|
||||||
*/
|
*/
|
||||||
if (buf->refcount > 1) {
|
if (buf && buf->refcount > 1) {
|
||||||
inProgress = FALSE;
|
inProgress = FALSE;
|
||||||
buf->flags &= ~BM_IO_IN_PROGRESS;
|
buf->flags &= ~BM_IO_IN_PROGRESS;
|
||||||
#ifdef HAS_TEST_AND_SET
|
#ifdef HAS_TEST_AND_SET
|
||||||
@ -473,18 +512,6 @@ BufferAlloc(Relation reln,
|
|||||||
* to do. We'll just handle this as if it were found in
|
* to do. We'll just handle this as if it were found in
|
||||||
* the buffer pool in the first place.
|
* the buffer pool in the first place.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PinBuffer(buf2);
|
|
||||||
inProgress = (buf2->flags & BM_IO_IN_PROGRESS);
|
|
||||||
|
|
||||||
*foundPtr = TRUE;
|
|
||||||
if (inProgress) {
|
|
||||||
WaitIO(buf2, BufMgrLock);
|
|
||||||
if (buf2->flags & BM_IO_ERROR) {
|
|
||||||
*foundPtr = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( buf != NULL )
|
if ( buf != NULL )
|
||||||
{
|
{
|
||||||
#ifdef HAS_TEST_AND_SET
|
#ifdef HAS_TEST_AND_SET
|
||||||
@ -499,9 +526,19 @@ BufferAlloc(Relation reln,
|
|||||||
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
|
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
|
||||||
AddBufferToFreelist(buf);
|
AddBufferToFreelist(buf);
|
||||||
buf->flags |= BM_FREE;
|
buf->flags |= BM_FREE;
|
||||||
buf->flags &= ~BM_DIRTY;
|
|
||||||
buf->flags &= ~BM_IO_IN_PROGRESS;
|
buf->flags &= ~BM_IO_IN_PROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PinBuffer(buf2);
|
||||||
|
inProgress = (buf2->flags & BM_IO_IN_PROGRESS);
|
||||||
|
|
||||||
|
*foundPtr = TRUE;
|
||||||
|
if (inProgress) {
|
||||||
|
WaitIO(buf2, BufMgrLock);
|
||||||
|
if (buf2->flags & BM_IO_ERROR) {
|
||||||
|
*foundPtr = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SpinRelease(BufMgrLock);
|
SpinRelease(BufMgrLock);
|
||||||
|
|
||||||
@ -532,13 +569,6 @@ BufferAlloc(Relation reln,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf->flags & BM_DIRTY) {
|
|
||||||
/* must clear flag first because of wierd race
|
|
||||||
* condition described below.
|
|
||||||
*/
|
|
||||||
buf->flags &= ~BM_DIRTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* record the database name and relation name for this buffer */
|
/* record the database name and relation name for this buffer */
|
||||||
strcpy (buf->sb_relname, reln->rd_rel->relname.data);
|
strcpy (buf->sb_relname, reln->rd_rel->relname.data);
|
||||||
strcpy (buf->sb_dbname, GetDatabaseName());
|
strcpy (buf->sb_dbname, GetDatabaseName());
|
||||||
@ -813,6 +843,30 @@ BufferSync()
|
|||||||
if (bufdb == MyDatabaseId || bufdb == (Oid) 0) {
|
if (bufdb == MyDatabaseId || bufdb == (Oid) 0) {
|
||||||
reln = RelationIdCacheGetRelation(bufrel);
|
reln = RelationIdCacheGetRelation(bufrel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have to pin buffer to keep anyone from stealing it
|
||||||
|
* from the buffer pool while we are flushing it or
|
||||||
|
* waiting in WaitIO. It's bad for GetFreeBuffer in
|
||||||
|
* BufferAlloc, but there is no other way to prevent
|
||||||
|
* writing into disk block data from some other buffer,
|
||||||
|
* getting smgr status of some other block and
|
||||||
|
* clearing BM_DIRTY of ... - VAdim 09/16/96
|
||||||
|
*/
|
||||||
|
PinBuffer(bufHdr);
|
||||||
|
if (bufHdr->flags & BM_IO_IN_PROGRESS)
|
||||||
|
{
|
||||||
|
WaitIO(bufHdr, BufMgrLock);
|
||||||
|
UnpinBuffer(bufHdr);
|
||||||
|
if (bufHdr->flags & BM_IO_ERROR)
|
||||||
|
{
|
||||||
|
elog(WARN, "cannot write %u for %s",
|
||||||
|
bufHdr->tag.blockNum, bufHdr->sb_relname);
|
||||||
|
}
|
||||||
|
if (reln != (Relation)NULL)
|
||||||
|
RelationDecrementReferenceCount(reln);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we didn't have the reldesc in our local cache, flush this
|
* If we didn't have the reldesc in our local cache, flush this
|
||||||
* page out using the 'blind write' storage manager routine. If
|
* page out using the 'blind write' storage manager routine. If
|
||||||
@ -836,8 +890,10 @@ BufferSync()
|
|||||||
SpinAcquire(BufMgrLock);
|
SpinAcquire(BufMgrLock);
|
||||||
#endif /* OPTIMIZE_SINGLE */
|
#endif /* OPTIMIZE_SINGLE */
|
||||||
|
|
||||||
|
UnpinBuffer(bufHdr);
|
||||||
if (status == SM_FAIL) {
|
if (status == SM_FAIL) {
|
||||||
elog(WARN, "cannot write %d for %16s",
|
bufHdr->flags |= BM_IO_ERROR;
|
||||||
|
elog(WARN, "cannot write %u for %s",
|
||||||
bufHdr->tag.blockNum, bufHdr->sb_relname);
|
bufHdr->tag.blockNum, bufHdr->sb_relname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user