]> granicus.if.org Git - postgresql/commitdiff
Work around gcc 4.6.0 bug that breaks WAL replay.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 10 Jun 2011 21:03:11 +0000 (17:03 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 10 Jun 2011 21:03:11 +0000 (17:03 -0400)
ReadRecord's habit of using both direct references to tmpRecPtr and
references to *RecPtr (which is pointing at tmpRecPtr) triggers an
optimization bug in gcc 4.6.0, which apparently has forgotten about
aliasing rules.  Avoid the compiler bug, and make the code more readable
to boot, by getting rid of the direct references.  Improve the comments
while at it.

Back-patch to all supported versions, in case they get built with 4.6.0.

Tom Lane, with some cosmetic suggestions from Alex Hunsaker

src/backend/access/transam/xlog.c
src/include/access/xlog_internal.h

index bf8075d2ec37e103ffc75fd0b9bb17f74b5a5033..6c18db4050fd3744324b9479f059cbfb9ffdd7d3 100644 (file)
@@ -3676,23 +3676,32 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
                RecPtr = &tmpRecPtr;
 
                /*
-                * Align recptr to next page if no more records can fit on the current
-                * page.
+                * RecPtr is pointing to end+1 of the previous WAL record.  We must
+                * advance it if necessary to where the next record starts.  First,
+                * align to next page if no more records can fit on the current page.
                 */
                if (XLOG_BLCKSZ - (RecPtr->xrecoff % XLOG_BLCKSZ) < SizeOfXLogRecord)
-               {
-                       NextLogPage(tmpRecPtr);
-                       /* We will account for page header size below */
-               }
+                       NextLogPage(*RecPtr);
 
-               if (tmpRecPtr.xrecoff >= XLogFileSize)
+               /* Check for crossing of xlog segment boundary */
+               if (RecPtr->xrecoff >= XLogFileSize)
                {
-                       (tmpRecPtr.xlogid)++;
-                       tmpRecPtr.xrecoff = 0;
+                       (RecPtr->xlogid)++;
+                       RecPtr->xrecoff = 0;
                }
+
+               /*
+                * If at page start, we must skip over the page header.  But we can't
+                * do that until we've read in the page, since the header size is
+                * variable.
+                */
        }
        else
        {
+               /*
+                * In this case, the passed-in record pointer should already be
+                * pointing to a valid record starting position.
+                */
                if (!XRecOffIsValid(RecPtr->xrecoff))
                        ereport(PANIC,
                                        (errmsg("invalid record offset at %X/%X",
@@ -3721,11 +3730,13 @@ retry:
        if (targetRecOff == 0)
        {
                /*
-                * Can only get here in the continuing-from-prev-page case, because
-                * XRecOffIsValid eliminated the zero-page-offset case otherwise. Need
-                * to skip over the new page's header.
+                * At page start, so skip over page header.  The Assert checks that
+                * we're not scribbling on caller's record pointer; it's OK because we
+                * can only get here in the continuing-from-prev-record case, since
+                * XRecOffIsValid rejected the zero-page-offset case otherwise.
                 */
-               tmpRecPtr.xrecoff += pageHeaderSize;
+               Assert(RecPtr == &tmpRecPtr);
+               RecPtr->xrecoff += pageHeaderSize;
                targetRecOff = pageHeaderSize;
        }
        else if (targetRecOff < pageHeaderSize)
index 3f0930f3951eee844fce4f91c0fb57036c0bd058..367de374ead97667a05f36a4fc3b605c4dd71232 100644 (file)
@@ -154,13 +154,13 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
 /* Align a record pointer to next page */
 #define NextLogPage(recptr) \
        do {    \
-               if (recptr.xrecoff % XLOG_BLCKSZ != 0)  \
-                       recptr.xrecoff +=       \
-                               (XLOG_BLCKSZ - recptr.xrecoff % XLOG_BLCKSZ);   \
-               if (recptr.xrecoff >= XLogFileSize) \
+               if ((recptr).xrecoff % XLOG_BLCKSZ != 0)        \
+                       (recptr).xrecoff +=     \
+                               (XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ); \
+               if ((recptr).xrecoff >= XLogFileSize) \
                {       \
-                       (recptr.xlogid)++;      \
-                       recptr.xrecoff = 0; \
+                       ((recptr).xlogid)++;    \
+                       (recptr).xrecoff = 0; \
                }       \
        } while (0)