88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.82 2000/06/08 22:37:20 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.83 2000/09/25 04:11:09 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -429,17 +429,10 @@ BufferAlloc(Relation reln,
429429inProgress = FALSE;
430430for (buf = (BufferDesc * )NULL ;buf == (BufferDesc * )NULL ;)
431431{
432-
433- /* GetFreeBuffer will abort if it can't find a free buffer */
434432buf = GetFreeBuffer ();
435433
436- /*
437- * But it can return buf == NULL if we are in aborting transaction
438- * now and so elog(ERROR,...) in GetFreeBuffer will not abort
439- * again.
440- */
441- if (buf == NULL )
442- return NULL ;
434+ /* GetFreeBuffer will abort if it can't find a free buffer */
435+ Assert (buf );
443436
444437/*
445438 * There should be exactly one pin on the buffer after it is
@@ -789,11 +782,21 @@ FlushBuffer(Buffer buffer, bool release)
789782WaitIO (bufHdr ,BufMgrLock );/* confirm end of IO */
790783bufHdr -> flags &= ~BM_JUST_DIRTIED ;
791784StartBufferIO (bufHdr , false);/* output IO start */
785+
792786SpinRelease (BufMgrLock );
793787
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+
794795status = smgrflush (DEFAULT_SMGR ,bufrel ,bufHdr -> tag .blockNum ,
795796 (char * )MAKE_PTR (bufHdr -> data ));
796797
798+ LockBuffer (BufferDescriptorGetBuffer (bufHdr ),BUFFER_LOCK_UNLOCK );
799+
797800/* drop relcache refcnt incremented by RelationIdCacheGetRelation */
798801RelationDecrementReferenceCount (bufrel );
799802
@@ -1017,19 +1020,6 @@ ClearBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
10171020 *that have been dirtied by the current xact and flush them to disk.
10181021 *We do *not* flush dirty buffers that have been dirtied by other xacts.
10191022 *(This is a substantial change from pre-7.0 behavior.)
1020- *
1021- *OLD COMMENTS (do these still apply?)
1022- *
1023- *Also, we need to be sure that no other transaction is
1024- *modifying the page as we flush it.This is only a problem for objects
1025- *that use a non-two-phase locking protocol, like btree indices.For
1026- *those objects, we would like to set a write lock for the duration of
1027- *our IO. Another possibility is to code updates to btree pages
1028- *carefully, so that writing them out out of order cannot cause
1029- *any unrecoverable errors.
1030- *
1031- *I don't want to think hard about this right now, so I will try
1032- *to come back to it later.
10331023 */
10341024static void
10351025BufferSync ()
@@ -1112,15 +1102,28 @@ BufferSync()
11121102bufHdr -> flags &= ~BM_JUST_DIRTIED ;
11131103StartBufferIO (bufHdr , false);/* output IO start */
11141104
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+
11151121/*
11161122 * If we didn't have the reldesc in our local cache,
11171123 * write this page out using the 'blind write' storage
11181124 * manager routine. If we did find it, use the
11191125 * standard interface.
11201126 */
1121- #ifndef OPTIMIZE_SINGLE
1122- SpinRelease (BufMgrLock );
1123- #endif /* OPTIMIZE_SINGLE */
11241127if (reln == (Relation )NULL )
11251128{
11261129status = smgrblindwrt (DEFAULT_SMGR ,
@@ -1137,9 +1140,14 @@ BufferSync()
11371140bufHdr -> tag .blockNum ,
11381141(char * )MAKE_PTR (bufHdr -> data ));
11391142}
1140- #ifndef OPTIMIZE_SINGLE
1143+
1144+ /*
1145+ * Release the per-buffer readlock, reacquire BufMgrLock.
1146+ */
1147+ LockBuffer (BufferDescriptorGetBuffer (bufHdr ),
1148+ BUFFER_LOCK_UNLOCK );
1149+
11411150SpinAcquire (BufMgrLock );
1142- #endif /* OPTIMIZE_SINGLE */
11431151
11441152UnpinBuffer (bufHdr );
11451153if (status == SM_FAIL )
@@ -1522,9 +1530,14 @@ BufferReplace(BufferDesc *bufHdr)
15221530/* To check if block content changed while flushing. - vadim 01/17/97 */
15231531bufHdr -> flags &= ~BM_JUST_DIRTIED ;
15241532
1525- #ifndef OPTIMIZE_SINGLE
15261533SpinRelease (BufMgrLock );
1527- #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 );
15281541
15291542if (reln != (Relation )NULL )
15301543{
@@ -1540,9 +1553,9 @@ BufferReplace(BufferDesc *bufHdr)
15401553 false);/* no fsync */
15411554}
15421555
1543- #ifndef OPTIMIZE_SINGLE
1556+ LockBuffer (BufferDescriptorGetBuffer (bufHdr ),BUFFER_LOCK_UNLOCK );
1557+
15441558SpinAcquire (BufMgrLock );
1545- #endif /* OPTIMIZE_SINGLE */
15461559
15471560/* drop relcache refcnt incremented by RelationIdCacheGetRelation */
15481561if (reln != (Relation )NULL )