Commit 9ff69034 authored by Vadim B. Mikheev's avatar Vadim B. Mikheev

Fixing possible losing data changes:

1. New flag - BM_JUST_DIRTIED - added for BufferDesc;
2. All data "dirtiers" (WriteBuffer and WriteNoReleaseBuffer)
   set this flag (and BM_DIRTY too);
3. All data "flushers" (FlushBuffer, BufferSync and BufferReplace)
   turn this flag off just before calling smgr[blind]write/smgrflush
   and check this flag after flushing buffer: if it turned ON then
   BM_DIRTY will stay ON.
parent deef313f
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.8 1997/01/16 08:11:41 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.9 1997/01/20 04:36:48 vadim Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -474,7 +474,19 @@ BufferAlloc(Relation reln, ...@@ -474,7 +474,19 @@ BufferAlloc(Relation reln,
else else
{ {
BufferFlushCount++; BufferFlushCount++;
buf->flags &= ~BM_DIRTY; /*
* BM_JUST_DIRTIED cleared by BufferReplace and shouldn't
* be setted by anyone. - vadim 01/17/97
*/
if ( buf->flags & BM_JUST_DIRTIED )
{
elog (FATAL, "BufferAlloc: content of block %u (%s) changed while flushing",
buf->tag.blockNum, buf->sb_relname);
}
else
{
buf->flags &= ~BM_DIRTY;
}
} }
/* /*
...@@ -488,7 +500,8 @@ BufferAlloc(Relation reln, ...@@ -488,7 +500,8 @@ 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 && 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
...@@ -643,7 +656,7 @@ WriteBuffer(Buffer buffer) ...@@ -643,7 +656,7 @@ WriteBuffer(Buffer buffer)
SpinAcquire(BufMgrLock); SpinAcquire(BufMgrLock);
Assert(bufHdr->refcount > 0); Assert(bufHdr->refcount > 0);
bufHdr->flags |= BM_DIRTY; bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED);
UnpinBuffer(bufHdr); UnpinBuffer(bufHdr);
SpinRelease(BufMgrLock); SpinRelease(BufMgrLock);
} }
...@@ -733,19 +746,36 @@ FlushBuffer(Buffer buffer, bool release) ...@@ -733,19 +746,36 @@ FlushBuffer(Buffer buffer, bool release)
bufrel = RelationIdCacheGetRelation (bufHdr->tag.relId.relId); bufrel = RelationIdCacheGetRelation (bufHdr->tag.relId.relId);
Assert (bufrel != (Relation) NULL); Assert (bufrel != (Relation) NULL);
/* To check if block content changed while flushing. - vadim 01/17/97 */
SpinAcquire(BufMgrLock);
bufHdr->flags &= ~BM_JUST_DIRTIED;
SpinRelease(BufMgrLock);
status = smgrflush(bufHdr->bufsmgr, bufrel, bufHdr->tag.blockNum, status = smgrflush(bufHdr->bufsmgr, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data)); (char *) MAKE_PTR(bufHdr->data));
if (status == SM_FAIL) if (status == SM_FAIL)
{ {
elog(WARN, "FlushBuffer: cannot flush block %u of the relation %.*s", elog(WARN, "FlushBuffer: cannot flush block %u of the relation %s",
bufHdr->tag.blockNum, bufHdr->tag.blockNum, bufHdr->sb_relname);
NAMEDATALEN, bufrel->rd_rel->relname.data);
return (STATUS_ERROR); return (STATUS_ERROR);
} }
SpinAcquire(BufMgrLock); SpinAcquire(BufMgrLock);
bufHdr->flags &= ~BM_DIRTY; /*
* If this buffer was marked by someone as DIRTY while
* we were flushing it out we must not clear DIRTY flag
* - vadim 01/17/97
*/
if ( bufHdr->flags & BM_JUST_DIRTIED )
{
elog (NOTICE, "FlusfBuffer: content of block %u (%s) changed while flushing",
bufHdr->tag.blockNum, bufHdr->sb_relname);
}
else
{
bufHdr->flags &= ~BM_DIRTY;
}
if ( release ) if ( release )
UnpinBuffer(bufHdr); UnpinBuffer(bufHdr);
SpinRelease(BufMgrLock); SpinRelease(BufMgrLock);
...@@ -779,7 +809,7 @@ WriteNoReleaseBuffer(Buffer buffer) ...@@ -779,7 +809,7 @@ WriteNoReleaseBuffer(Buffer buffer)
bufHdr = &BufferDescriptors[buffer-1]; bufHdr = &BufferDescriptors[buffer-1];
SpinAcquire(BufMgrLock); SpinAcquire(BufMgrLock);
bufHdr->flags |= BM_DIRTY; bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED);
SpinRelease(BufMgrLock); SpinRelease(BufMgrLock);
} }
return(STATUS_OK); return(STATUS_OK);
...@@ -878,13 +908,19 @@ BufferSync() ...@@ -878,13 +908,19 @@ BufferSync()
UnpinBuffer(bufHdr); UnpinBuffer(bufHdr);
if (bufHdr->flags & BM_IO_ERROR) if (bufHdr->flags & BM_IO_ERROR)
{ {
elog(WARN, "cannot write %u for %s", elog(WARN, "BufferSync: write error %u for %s",
bufHdr->tag.blockNum, bufHdr->sb_relname); bufHdr->tag.blockNum, bufHdr->sb_relname);
} }
if (reln != (Relation)NULL) if (reln != (Relation)NULL)
RelationDecrementReferenceCount(reln); RelationDecrementReferenceCount(reln);
continue; continue;
} }
/*
* To check if block content changed while flushing
* (see below). - vadim 01/17/97
*/
bufHdr->flags &= ~BM_JUST_DIRTIED;
/* /*
* 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
...@@ -912,15 +948,23 @@ BufferSync() ...@@ -912,15 +948,23 @@ BufferSync()
UnpinBuffer(bufHdr); UnpinBuffer(bufHdr);
if (status == SM_FAIL) { if (status == SM_FAIL) {
bufHdr->flags |= BM_IO_ERROR; bufHdr->flags |= BM_IO_ERROR;
elog(WARN, "cannot write %u for %s", elog(WARN, "BufferSync: cannot write %u for %s",
bufHdr->tag.blockNum, bufHdr->sb_relname); bufHdr->tag.blockNum, bufHdr->sb_relname);
} }
/* /*
* What if someone has marked this buffer as DIRTY after * If this buffer was marked by someone as DIRTY while
* smgr[blind]write but before SpinAcquire(BufMgrLock) * we were flushing it out we must not clear DIRTY flag
* ??? - vadim 01/16/97 * - vadim 01/17/97
*/ */
bufHdr->flags &= ~BM_DIRTY; if ( bufHdr->flags & BM_JUST_DIRTIED )
{
elog (NOTICE, "BufferSync: content of block %u (%s) changed while flushing",
bufHdr->tag.blockNum, bufHdr->sb_relname);
}
else
{
bufHdr->flags &= ~BM_DIRTY;
}
if (reln != (Relation)NULL) if (reln != (Relation)NULL)
RelationDecrementReferenceCount(reln); RelationDecrementReferenceCount(reln);
} }
...@@ -1189,6 +1233,9 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld) ...@@ -1189,6 +1233,9 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld)
reln = RelationIdCacheGetRelation(bufrel); reln = RelationIdCacheGetRelation(bufrel);
else else
reln = (Relation) NULL; reln = (Relation) NULL;
/* To check if block content changed while flushing. - vadim 01/17/97 */
bufHdr->flags &= ~BM_JUST_DIRTIED;
SpinRelease(BufMgrLock); SpinRelease(BufMgrLock);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment