Fix two bugs in WAL-logging of GIN pending-list pages.
authorHeikki Linnakangas
Mon, 28 Apr 2014 13:12:45 +0000 (16:12 +0300)
committerHeikki Linnakangas
Mon, 28 Apr 2014 14:20:33 +0000 (17:20 +0300)
In writeListPage, never take a full-page image of the page, because we
have all the information required to re-initialize in the WAL record
anyway. Before this fix, a full-page image was always generated, unless
full_page_writes=off, because when the page is initialized its LSN is
always 0. In stable-branches, keep the code to restore the backup blocks
if they exist, in case that the WAL is generated with an older minor
version, but in master Assert that there are no full-page images.

In the redo routine, add missing "off++". Otherwise the tuples are added
to the page in reverse order. That happens to be harmless because we
always scan and remove all the tuples together, but it was clearly wrong.
Also, it was masked by the first bug unless full_page_writes=off, because
the page was always restored from a full-page image.

Backpatch to all supported versions.

src/backend/access/gin/ginfast.c
src/backend/access/gin/ginxlog.c

index 4f2c11810a44b5bf1b7e1e76dff1fb2b06a089f5..177a2246bc55c4635da7f1d6ceb39730c99b1cba 100644 (file)
@@ -119,8 +119,7 @@ writeListPage(Relation index, Buffer buffer,
        rdata[0].len = sizeof(ginxlogInsertListPage);
        rdata[0].next = rdata + 1;
 
-       rdata[1].buffer = buffer;
-       rdata[1].buffer_std = true;
+       rdata[1].buffer = InvalidBuffer;
        rdata[1].data = workspace;
        rdata[1].len = size;
        rdata[1].next = NULL;
index dbfbec73e574598cb80e15b3da4bf142151e444a..f487ba5c1add72dfca963de9824780b8d3dee1ba 100644 (file)
@@ -606,7 +606,11 @@ ginRedoInsertListPage(XLogRecPtr lsn, XLogRecord *record)
                tupsize;
    IndexTuple  tuples = (IndexTuple) (XLogRecGetData(record) + sizeof(ginxlogInsertListPage));
 
-   /* If we have a full-page image, restore it and we're done */
+   /*
+    * If we have a full-page image, restore it and we're done.  (As the code
+    * stands, we never create full-page images, but we used to.  Cope if
+    * we're reading WAL generated with an older minor version.)
+    */
    if (record->xl_info & XLR_BKP_BLOCK(0))
    {
        (void) RestoreBackupBlock(lsn, record, 0, false, false);
@@ -640,6 +644,7 @@ ginRedoInsertListPage(XLogRecPtr lsn, XLogRecord *record)
            elog(ERROR, "failed to add item to index page");
 
        tuples = (IndexTuple) (((char *) tuples) + tupsize);
+       off++;
    }
 
    PageSetLSN(page, lsn);