]> granicus.if.org Git - postgresql/commitdiff
Fix possible page corruption by ALTER TABLE .. SET TABLESPACE.
authorRobert Haas <rhaas@postgresql.org>
Thu, 29 Jul 2010 16:15:33 +0000 (16:15 +0000)
committerRobert Haas <rhaas@postgresql.org>
Thu, 29 Jul 2010 16:15:33 +0000 (16:15 +0000)
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.

src/backend/access/heap/heapam.c
src/backend/commands/tablecmds.c

index 35ad3d88ac3c5a87351248501d6a3fdb4e680c87..8a9e13902e1eba5cc2a9c20f035c409a03f54bf2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.200.2.3 2006/11/17 18:00:25 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.200.2.4 2010/07/29 16:15:33 rhaas Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -2740,8 +2740,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);
+       }
+
        LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
        WriteBuffer(buffer);
 }
index 59c99fc3e1b96b9a356917e92aa64966538aeb36..8f8d28e825c9ecca3e7576f4a7d1b988ce7cf20e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.174.2.10 2010/07/01 14:11:03 rhaas Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.174.2.11 2010/07/29 16:15:33 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -5893,8 +5893,15 @@ copy_relation_data(Relation rel, SMgrRelation dst)
 
                        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();
                }