Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit956ba75

Browse files
committed
Back-patch fix to grab read lock on a buffer while it is written out.
1 parent730e2ff commit956ba75

File tree

1 file changed

+47
-33
lines changed

1 file changed

+47
-33
lines changed

‎src/backend/storage/buffer/bufmgr.c

Lines changed: 47 additions & 33 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.81 2000/05/19 03:22:28 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.81.2.1 2000/09/25 04:34:10 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -75,7 +75,6 @@ static void WaitIO(BufferDesc *buf, SPINLOCK spinlock);
7575
staticvoidStartBufferIO(BufferDesc*buf,boolforInput);
7676
staticvoidTerminateBufferIO(BufferDesc*buf);
7777
staticvoidContinueBufferIO(BufferDesc*buf,boolforInput);
78-
externvoidInitBufferIO(void);
7978
externvoidAbortBufferIO(void);
8079

8180
/*
@@ -430,17 +429,10 @@ BufferAlloc(Relation reln,
430429
inProgress= FALSE;
431430
for (buf= (BufferDesc*)NULL;buf== (BufferDesc*)NULL;)
432431
{
433-
434-
/* GetFreeBuffer will abort if it can't find a free buffer */
435432
buf=GetFreeBuffer();
436433

437-
/*
438-
* But it can return buf == NULL if we are in aborting transaction
439-
* now and so elog(ERROR,...) in GetFreeBuffer will not abort
440-
* again.
441-
*/
442-
if (buf==NULL)
443-
returnNULL;
434+
/* GetFreeBuffer will abort if it can't find a free buffer */
435+
Assert(buf);
444436

445437
/*
446438
* There should be exactly one pin on the buffer after it is
@@ -790,11 +782,21 @@ FlushBuffer(Buffer buffer, bool release)
790782
WaitIO(bufHdr,BufMgrLock);/* confirm end of IO */
791783
bufHdr->flags &= ~BM_JUST_DIRTIED;
792784
StartBufferIO(bufHdr, false);/* output IO start */
785+
793786
SpinRelease(BufMgrLock);
794787

788+
/*
789+
* Grab a read lock on the buffer to ensure that no
790+
* other backend changes its contents while we write it;
791+
* see comments in BufferSync().
792+
*/
793+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_SHARE);
794+
795795
status=smgrflush(DEFAULT_SMGR,bufrel,bufHdr->tag.blockNum,
796796
(char*)MAKE_PTR(bufHdr->data));
797797

798+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_UNLOCK);
799+
798800
/* drop relcache refcnt incremented by RelationIdCacheGetRelation */
799801
RelationDecrementReferenceCount(bufrel);
800802

@@ -1018,19 +1020,6 @@ ClearBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
10181020
*that have been dirtied by the current xact and flush them to disk.
10191021
*We do *not* flush dirty buffers that have been dirtied by other xacts.
10201022
*(This is a substantial change from pre-7.0 behavior.)
1021-
*
1022-
*OLD COMMENTS (do these still apply?)
1023-
*
1024-
*Also, we need to be sure that no other transaction is
1025-
*modifying the page as we flush it.This is only a problem for objects
1026-
*that use a non-two-phase locking protocol, like btree indices.For
1027-
*those objects, we would like to set a write lock for the duration of
1028-
*our IO. Another possibility is to code updates to btree pages
1029-
*carefully, so that writing them out out of order cannot cause
1030-
*any unrecoverable errors.
1031-
*
1032-
*I don't want to think hard about this right now, so I will try
1033-
*to come back to it later.
10341023
*/
10351024
staticvoid
10361025
BufferSync()
@@ -1113,15 +1102,28 @@ BufferSync()
11131102
bufHdr->flags &= ~BM_JUST_DIRTIED;
11141103
StartBufferIO(bufHdr, false);/* output IO start */
11151104

1105+
SpinRelease(BufMgrLock);
1106+
1107+
/*
1108+
* Grab a read lock on the buffer to ensure that no
1109+
* other backend changes its contents while we write it;
1110+
* otherwise we could write a non-self-consistent page
1111+
* image to disk, which'd be bad news if the other
1112+
* transaction aborts before writing its changes.
1113+
*
1114+
* Note that we still need the BM_JUST_DIRTIED mechanism
1115+
* in case someone dirties the buffer just before we
1116+
* grab this lock or just after we release it.
1117+
*/
1118+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),
1119+
BUFFER_LOCK_SHARE);
1120+
11161121
/*
11171122
* If we didn't have the reldesc in our local cache,
11181123
* write this page out using the 'blind write' storage
11191124
* manager routine. If we did find it, use the
11201125
* standard interface.
11211126
*/
1122-
#ifndefOPTIMIZE_SINGLE
1123-
SpinRelease(BufMgrLock);
1124-
#endif/* OPTIMIZE_SINGLE */
11251127
if (reln== (Relation)NULL)
11261128
{
11271129
status=smgrblindwrt(DEFAULT_SMGR,
@@ -1138,9 +1140,14 @@ BufferSync()
11381140
bufHdr->tag.blockNum,
11391141
(char*)MAKE_PTR(bufHdr->data));
11401142
}
1141-
#ifndefOPTIMIZE_SINGLE
1143+
1144+
/*
1145+
* Release the per-buffer readlock, reacquire BufMgrLock.
1146+
*/
1147+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),
1148+
BUFFER_LOCK_UNLOCK);
1149+
11421150
SpinAcquire(BufMgrLock);
1143-
#endif/* OPTIMIZE_SINGLE */
11441151

11451152
UnpinBuffer(bufHdr);
11461153
if (status==SM_FAIL)
@@ -1523,9 +1530,14 @@ BufferReplace(BufferDesc *bufHdr)
15231530
/* To check if block content changed while flushing. - vadim 01/17/97 */
15241531
bufHdr->flags &= ~BM_JUST_DIRTIED;
15251532

1526-
#ifndefOPTIMIZE_SINGLE
15271533
SpinRelease(BufMgrLock);
1528-
#endif/* OPTIMIZE_SINGLE */
1534+
1535+
/*
1536+
* Grab a read lock on the buffer to ensure that no
1537+
* other backend changes its contents while we write it;
1538+
* see comments in BufferSync().
1539+
*/
1540+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_SHARE);
15291541

15301542
if (reln!= (Relation)NULL)
15311543
{
@@ -1541,9 +1553,9 @@ BufferReplace(BufferDesc *bufHdr)
15411553
false);/* no fsync */
15421554
}
15431555

1544-
#ifndefOPTIMIZE_SINGLE
1556+
LockBuffer(BufferDescriptorGetBuffer(bufHdr),BUFFER_LOCK_UNLOCK);
1557+
15451558
SpinAcquire(BufMgrLock);
1546-
#endif/* OPTIMIZE_SINGLE */
15471559

15481560
/* drop relcache refcnt incremented by RelationIdCacheGetRelation */
15491561
if (reln!= (Relation)NULL)
@@ -2488,11 +2500,13 @@ ContinueBufferIO(BufferDesc *buf, bool forInput)
24882500
IsForInput=forInput;
24892501
}
24902502

2503+
#ifdefNOT_USED
24912504
void
24922505
InitBufferIO(void)
24932506
{
24942507
InProgressBuf= (BufferDesc*)0;
24952508
}
2509+
#endif
24962510

24972511
/*
24982512
*This function is called from ProcReleaseSpins().

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp