summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2010-07-29 16:14:45 +0000
committerRobert Haas <rhaas@postgresql.org>2010-07-29 16:14:45 +0000
commit7958520d2c54abd5efbcf5f664193cb5a6a99fd7 (patch)
tree45254f564df1d4d7d149cf711953f04347e10380 /src/backend/access
parent40cacbb376a7a5ec3f4de54d8bb510527dd2b246 (diff)
Fix possible page corruption by ALTER TABLE .. SET TABLESPACE.
If a zeroed page is present in the heap, ALTER TABLE .. SET TABLESPACE will set the LSN and TLI while copying it, which is wrong, and heap_xlog_newpage() will do the same thing during replay, so the corruption propagates to any standby. Note, however, that the bug can't be demonstrated unless archiving is enabled, since in that case we skip WAL logging altogether, and the LSN/TLI are not set. Back-patch to 8.0; prior releases do not have tablespaces. Analysis and patch by Jeff Davis. Adjustments for back-branches and minor wordsmithing by me.
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/heap/heapam.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index e17b6362c31..48a387e2ecb 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.292 2010/07/06 19:18:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.292.2.1 2010/07/29 16:14:45 rhaas Exp $
*
*
* INTERFACE ROUTINES
@@ -4079,8 +4079,15 @@ log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno,
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_NEWPAGE, rdata);
- PageSetLSN(page, recptr);
- PageSetTLI(page, ThisTimeLineID);
+ /*
+ * The page may be uninitialized. If so, we can't set the LSN
+ * and TLI because that would corrupt the page.
+ */
+ if (!PageIsNew(page))
+ {
+ PageSetLSN(page, recptr);
+ PageSetTLI(page, ThisTimeLineID);
+ }
END_CRIT_SECTION();
@@ -4266,8 +4273,16 @@ heap_xlog_newpage(XLogRecPtr lsn, XLogRecord *record)
Assert(record->xl_len == SizeOfHeapNewpage + BLCKSZ);
memcpy(page, (char *) xlrec + SizeOfHeapNewpage, BLCKSZ);
- PageSetLSN(page, lsn);
- PageSetTLI(page, ThisTimeLineID);
+ /*
+ * The page may be uninitialized. If so, we can't set the LSN
+ * and TLI because that would corrupt the page.
+ */
+ if (!PageIsNew(page))
+ {
+ PageSetLSN(page, lsn);
+ PageSetTLI(page, ThisTimeLineID);
+ }
+
MarkBufferDirty(buffer);
UnlockReleaseBuffer(buffer);
}