aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Korotkov <akorotkov@postgresql.org>2019-03-24 15:26:45 +0300
committerAlexander Korotkov <akorotkov@postgresql.org>2019-03-24 15:44:56 +0300
commitcda5f6575306e50136a5f8ce3f76d9b2d772b738 (patch)
tree66042c67dd67becf6bc54591d88e923b35d8b757 /src
parent06c320c8af6adce28a6634faaf46e320085ebfcd (diff)
downloadpostgresql-cda5f6575306e50136a5f8ce3f76d9b2d772b738.tar.gz
postgresql-cda5f6575306e50136a5f8ce3f76d9b2d772b738.zip
Fix WAL format incompatibility introduced by backpatching of 52ac6cd2d0
52ac6cd2d0 added new field to ginxlogDeletePage and was backpatched to 9.4. That led to problems when patched postgres instance applies WAL records generated by non-patched one. WAL records generated by non-patched instance don't contain new field, which patched one is expecting to see. Thankfully, we can distinguish patched and non-patched WAL records by their data size. If we see that WAL record is generated by non-patched instance, we skip processing of new field. This commit comes with some assertions. In particular, if it appears that on some platform struct data size didn't change then static assertion will trigger. Reported-by: Simon Riggs Discussion: https://postgr.es/m/CANP8%2Bj%2BK4whxf7ET7%2BgO%2BG-baC3-WxqqH%3DnV4X2CgfEPA3Yu3g%40mail.gmail.com Author: Alexander Korotkov Reviewed-by: Simon Riggs, Alvaro Herrera Backpatch-through: 9.4
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gin/ginxlog.c19
-rw-r--r--src/include/access/gin_private.h10
2 files changed, 28 insertions, 1 deletions
diff --git a/src/backend/access/gin/ginxlog.c b/src/backend/access/gin/ginxlog.c
index e80daf31a9c..8902602fc75 100644
--- a/src/backend/access/gin/ginxlog.c
+++ b/src/backend/access/gin/ginxlog.c
@@ -529,7 +529,24 @@ ginRedoDeletePage(XLogReaderState *record)
page = BufferGetPage(dbuffer);
Assert(GinPageIsData(page));
GinPageGetOpaque(page)->flags = GIN_DELETED;
- GinPageSetDeleteXid(page, data->deleteXid);
+
+ /*
+ * deleteXid field of ginxlogDeletePage was added during backpatching.
+ * But, non-backpatched instances will continue generate WAL without
+ * this field. We should be able to correctly apply that. We can
+ * distinguish new WAL records by size their data, because
+ * ginxlogDeletePage changes its size on both 32-bit and 64-bit
+ * platforms.
+ */
+ StaticAssertStmt(sizeof(ginxlogDeletePage) !=
+ sizeof(ginxlogDeletePageOld),
+ "ginxlogDeletePage size should be changed "
+ "with addition of deleteXid field");
+ Assert(XLogRecGetDataLen(record) == sizeof(ginxlogDeletePage) ||
+ XLogRecGetDataLen(record) == sizeof(ginxlogDeletePageOld));
+ if (XLogRecGetDataLen(record) == sizeof(ginxlogDeletePage))
+ GinPageSetDeleteXid(page, data->deleteXid);
+
PageSetLSN(page, lsn);
MarkBufferDirty(dbuffer);
}
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 4ff7c3755c7..46fbe9e1161 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -554,6 +554,16 @@ typedef struct ginxlogDeletePage
TransactionId deleteXid; /* last Xid which could see this page in scan */
} ginxlogDeletePage;
+/*
+ * Previous version of ginxlogDeletePage struct, which didn't have deleteXid
+ * field. Used for size comparison (see ginRedoDeletePage()).
+ */
+typedef struct ginxlogDeletePageOld
+{
+ OffsetNumber parentOffset;
+ BlockNumber rightLink;
+} ginxlogDeletePageOld;
+
#define XLOG_GIN_UPDATE_META_PAGE 0x60
/*