@@ -289,35 +289,16 @@ static XLogRecPtr RedoStartLSN = {0, 0};
289289 * These structs are identical but are declared separately to indicate their
290290 * slightly different functions.
291291 *
292- * We do a lot of pushups to minimize the amount of access to lockable
293- * shared memory values. There are actually three shared-memory copies of
294- * LogwrtResult, plus one unshared copy in each backend. Here's how it works:
295- *XLogCtl->LogwrtResult is protected by info_lck
296- *XLogCtl->Write.LogwrtResult is protected by WALWriteLock
297- *XLogCtl->Insert.LogwrtResult is protected by WALInsertLock
298- * One must hold the associated lock to read or write any of these, but
299- * of course no lock is needed to read/write the unshared LogwrtResult.
300- *
301- * XLogCtl->LogwrtResult and XLogCtl->Write.LogwrtResult are both "always
302- * right", since both are updated by a write or flush operation before
303- * it releases WALWriteLock. The point of keeping XLogCtl->Write.LogwrtResult
304- * is that it can be examined/modified by code that already holds WALWriteLock
305- * without needing to grab info_lck as well.
306- *
307- * XLogCtl->Insert.LogwrtResult may lag behind the reality of the other two,
308- * but is updated when convenient.Again, it exists for the convenience of
309- * code that is already holding WALInsertLock but not the other locks.
310- *
311- * The unshared LogwrtResult may lag behind any or all of these, and again
312- * is updated when convenient.
292+ * To read XLogCtl->LogwrtResult, you must hold either info_lck or
293+ * WALWriteLock. To update it, you need to hold both locks. The point of
294+ * this arrangement is that the value can be examined by code that already
295+ * holds WALWriteLock without needing to grab info_lck as well. In addition
296+ * to the shared variable, each backend has a private copy of LogwrtResult,
297+ * which is updated when convenient.
313298 *
314299 * The request bookkeeping is simpler: there is a shared XLogCtl->LogwrtRqst
315300 * (protected by info_lck), but we don't need to cache any copies of it.
316301 *
317- * Note that this all works because the request and result positions can only
318- * advance forward, never back up, and so we can easily determine which of two
319- * values is "more up to date".
320- *
321302 * info_lck is only held long enough to read/update the protected variables,
322303 * so it's a plain spinlock. The other locks are held longer (potentially
323304 * over I/O operations), so we use LWLocks for them. These locks are:
@@ -354,7 +335,6 @@ typedef struct XLogwrtResult
354335 */
355336typedef struct XLogCtlInsert
356337{
357- XLogwrtResult LogwrtResult ;/* a recent value of LogwrtResult */
358338XLogRecPtr PrevRecord ;/* start of previously-inserted record */
359339int curridx ;/* current block index in cache */
360340XLogPageHeader currpage ;/* points to header of block in cache */
@@ -388,7 +368,6 @@ typedef struct XLogCtlInsert
388368 */
389369typedef struct XLogCtlWrite
390370{
391- XLogwrtResult LogwrtResult ;/* current value of LogwrtResult */
392371int curridx ;/* cache index of next block to write */
393372pg_time_t lastSegSwitchTime ;/* time of last xlog segment switch */
394373}XLogCtlWrite ;
@@ -403,7 +382,6 @@ typedef struct XLogCtlData
403382
404383/* Protected by info_lck: */
405384XLogwrtRqst LogwrtRqst ;
406- XLogwrtResult LogwrtResult ;
407385uint32 ckptXidEpoch ;/* nextXID & epoch of latest checkpoint */
408386TransactionId ckptXid ;
409387XLogRecPtr asyncXactLSN ;/* LSN of newest async commit/abort */
@@ -413,6 +391,12 @@ typedef struct XLogCtlData
413391/* Protected by WALWriteLock: */
414392XLogCtlWrite Write ;
415393
394+ /*
395+ * Protected by info_lck and WALWriteLock (you must hold either lock to
396+ * read it, but both to update)
397+ */
398+ XLogwrtResult LogwrtResult ;
399+
416400/*
417401 * These values do not change after startup, although the pointed-to pages
418402 * and xlblocks values certainly do. Permission to read/write the pages
@@ -1015,7 +999,7 @@ begin:;
1015999}
10161000
10171001LWLockAcquire (WALWriteLock ,LW_EXCLUSIVE );
1018- LogwrtResult = XLogCtl -> Write . LogwrtResult ;
1002+ LogwrtResult = XLogCtl -> LogwrtResult ;
10191003if (!XLByteLE (RecPtr ,LogwrtResult .Flush ))
10201004{
10211005XLogwrtRqst FlushRqst ;
@@ -1188,8 +1172,6 @@ begin:;
11881172SpinLockRelease (& xlogctl -> info_lck );
11891173}
11901174
1191- Write -> LogwrtResult = LogwrtResult ;
1192-
11931175LWLockRelease (WALWriteLock );
11941176
11951177updrqst = false;/* done already */
@@ -1477,18 +1459,13 @@ static bool
14771459AdvanceXLInsertBuffer (bool new_segment )
14781460{
14791461XLogCtlInsert * Insert = & XLogCtl -> Insert ;
1480- XLogCtlWrite * Write = & XLogCtl -> Write ;
14811462int nextidx = NextBufIdx (Insert -> curridx );
14821463bool update_needed = true;
14831464XLogRecPtr OldPageRqstPtr ;
14841465XLogwrtRqst WriteRqst ;
14851466XLogRecPtr NewPageEndPtr ;
14861467XLogPageHeader NewPage ;
14871468
1488- /* Use Insert->LogwrtResult copy if it's more fresh */
1489- if (XLByteLT (LogwrtResult .Write ,Insert -> LogwrtResult .Write ))
1490- LogwrtResult = Insert -> LogwrtResult ;
1491-
14921469/*
14931470 * Get ending-offset of the buffer page we need to replace (this may be
14941471 * zero if the buffer hasn't been used yet). Fall through if it's already
@@ -1516,21 +1493,19 @@ AdvanceXLInsertBuffer(bool new_segment)
15161493
15171494update_needed = false;/* Did the shared-request update */
15181495
1519- if (XLByteLE (OldPageRqstPtr ,LogwrtResult .Write ))
1520- {
1521- /* OK, someone wrote it already */
1522- Insert -> LogwrtResult = LogwrtResult ;
1523- }
1524- else
1496+ /*
1497+ * Now that we have an up-to-date LogwrtResult value, see if we still
1498+ * need to write it or if someone else already did.
1499+ */
1500+ if (!XLByteLE (OldPageRqstPtr ,LogwrtResult .Write ))
15251501{
15261502/* Must acquire write lock */
15271503LWLockAcquire (WALWriteLock ,LW_EXCLUSIVE );
1528- LogwrtResult = Write -> LogwrtResult ;
1504+ LogwrtResult = XLogCtl -> LogwrtResult ;
15291505if (XLByteLE (OldPageRqstPtr ,LogwrtResult .Write ))
15301506{
15311507/* OK, someone wrote it already */
15321508LWLockRelease (WALWriteLock );
1533- Insert -> LogwrtResult = LogwrtResult ;
15341509}
15351510else
15361511{
@@ -1544,7 +1519,6 @@ AdvanceXLInsertBuffer(bool new_segment)
15441519WriteRqst .Flush .xrecoff = 0 ;
15451520XLogWrite (WriteRqst , false, false);
15461521LWLockRelease (WALWriteLock );
1547- Insert -> LogwrtResult = LogwrtResult ;
15481522TRACE_POSTGRESQL_WAL_BUFFER_WRITE_DIRTY_DONE ();
15491523}
15501524}
@@ -1697,7 +1671,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
16971671/*
16981672 * Update local LogwrtResult (caller probably did this already, but...)
16991673 */
1700- LogwrtResult = Write -> LogwrtResult ;
1674+ LogwrtResult = XLogCtl -> LogwrtResult ;
17011675
17021676/*
17031677 * Since successive pages in the xlog cache are consecutively allocated,
@@ -1931,8 +1905,6 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
19311905xlogctl -> LogwrtRqst .Flush = LogwrtResult .Flush ;
19321906SpinLockRelease (& xlogctl -> info_lck );
19331907}
1934-
1935- Write -> LogwrtResult = LogwrtResult ;
19361908}
19371909
19381910/*
@@ -2126,7 +2098,7 @@ XLogFlush(XLogRecPtr record)
21262098continue ;
21272099}
21282100/* Got the lock */
2129- LogwrtResult = XLogCtl -> Write . LogwrtResult ;
2101+ LogwrtResult = XLogCtl -> LogwrtResult ;
21302102if (!XLByteLE (record ,LogwrtResult .Flush ))
21312103{
21322104/* try to write/flush later additions to XLOG as well */
@@ -2268,7 +2240,7 @@ XLogBackgroundFlush(void)
22682240
22692241/* now wait for the write lock */
22702242LWLockAcquire (WALWriteLock ,LW_EXCLUSIVE );
2271- LogwrtResult = XLogCtl -> Write . LogwrtResult ;
2243+ LogwrtResult = XLogCtl -> LogwrtResult ;
22722244if (!XLByteLE (WriteRqstPtr ,LogwrtResult .Flush ))
22732245{
22742246XLogwrtRqst WriteRqst ;
@@ -6831,8 +6803,6 @@ StartupXLOG(void)
68316803
68326804LogwrtResult .Write = LogwrtResult .Flush = EndOfLog ;
68336805
6834- XLogCtl -> Write .LogwrtResult = LogwrtResult ;
6835- Insert -> LogwrtResult = LogwrtResult ;
68366806XLogCtl -> LogwrtResult = LogwrtResult ;
68376807
68386808XLogCtl -> LogwrtRqst .Write = EndOfLog ;