From: Simon Riggs Date: Sun, 7 Apr 2013 21:16:51 +0000 (+0100) Subject: Fix checksums for CLUSTER, VACUUM FULL etc. X-Git-Tag: REL9_3_BETA1~126 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cf8dc9e10c0d954970cbe5ca9be4c6b881cde482;p=postgresql Fix checksums for CLUSTER, VACUUM FULL etc. In CLUSTER, VACUUM FULL and ALTER TABLE SET TABLESPACE I erroneously set checksum before log_newpage, which sets the LSN and invalidates the checksum. So set checksum immediately *after* log_newpage. Bug report Fujii Masao, Fix and patch by Jeff Davis --- diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 8a22eccf87..a3aad3adf9 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -273,14 +273,15 @@ end_heap_rewrite(RewriteState state) /* Write the last page, if any */ if (state->rs_buffer_valid) { - PageSetChecksumInplace(state->rs_buffer, state->rs_blockno); - if (state->rs_use_wal) log_newpage(&state->rs_new_rel->rd_node, MAIN_FORKNUM, state->rs_blockno, state->rs_buffer); RelationOpenSmgr(state->rs_new_rel); + + PageSetChecksumInplace(state->rs_buffer, state->rs_blockno); + smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno, (char *) state->rs_buffer, true); } @@ -616,8 +617,6 @@ raw_heap_insert(RewriteState state, HeapTuple tup) { /* Doesn't fit, so write out the existing page */ - PageSetChecksumInplace(page, state->rs_blockno); - /* XLOG stuff */ if (state->rs_use_wal) log_newpage(&state->rs_new_rel->rd_node, @@ -632,6 +631,9 @@ raw_heap_insert(RewriteState state, HeapTuple tup) * end_heap_rewrite. */ RelationOpenSmgr(state->rs_new_rel); + + PageSetChecksumInplace(page, state->rs_blockno); + smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno, (char *) page, true); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 536d232dd4..81c1199742 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -51,6 +51,7 @@ #include "commands/tablespace.h" #include "commands/trigger.h" #include "commands/typecmds.h" +#include "common/relpath.h" #include "executor/executor.h" #include "foreign/foreign.h" #include "miscadmin.h" @@ -8902,12 +8903,21 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst, smgrread(src, forkNum, blkno, buf); - PageSetChecksumInplace(page, blkno); + if (!PageIsVerified(page, blkno)) + ereport(ERROR, + (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("invalid page in block %u of relation %s", + blkno, + relpathbackend(src->smgr_rnode.node, + src->smgr_rnode.backend, + forkNum)))); /* XLOG stuff */ if (use_wal) log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page); + PageSetChecksumInplace(page, blkno); + /* * Now write the page. We say isTemp = true even if it's not a temp * rel, because there's no need for smgr to schedule an fsync for this