postgres.git / summary / log / commit / refs

commit    3137b496985b4e2242220bdabd4de86cf5c2d36e
Author:   Robert Haas <rhaas@postgresql.org>
Date:     Thu Jul 29 16:15:47 2010 +0000
First released in: 9.1.0, 8.0.26, 8.1.22, 8.2.18, 8.3.12, 8.4.5, 9.0.0

    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.


src/backend/access/heap/heapam.c | 14 +++++++++++--- src/backend/commands/tablecmds.c | 13 ++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 075e4f54205..c44bbed3683 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.182.4.1 2005/08/25 19:44:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.182.4.2 2010/07/29 16:15:47 rhaas Exp $ * * * INTERFACE ROUTINES @@ -2304,8 +2304,16 @@ heap_xlog_newpage(bool redo, 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); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b6d9d94e0d2..f82109bab35 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.142.4.12 2010/07/01 14:10:42 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.142.4.13 2010/07/29 16:15:47 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -5786,8 +5786,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(); } [parent: 5a54266a8db6]