Commit cf8dc9e1 authored by Simon Riggs's avatar Simon Riggs

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
parent 7844608e
...@@ -273,14 +273,15 @@ end_heap_rewrite(RewriteState state) ...@@ -273,14 +273,15 @@ end_heap_rewrite(RewriteState state)
/* Write the last page, if any */ /* Write the last page, if any */
if (state->rs_buffer_valid) if (state->rs_buffer_valid)
{ {
PageSetChecksumInplace(state->rs_buffer, state->rs_blockno);
if (state->rs_use_wal) if (state->rs_use_wal)
log_newpage(&state->rs_new_rel->rd_node, log_newpage(&state->rs_new_rel->rd_node,
MAIN_FORKNUM, MAIN_FORKNUM,
state->rs_blockno, state->rs_blockno,
state->rs_buffer); state->rs_buffer);
RelationOpenSmgr(state->rs_new_rel); RelationOpenSmgr(state->rs_new_rel);
PageSetChecksumInplace(state->rs_buffer, state->rs_blockno);
smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno, smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, state->rs_blockno,
(char *) state->rs_buffer, true); (char *) state->rs_buffer, true);
} }
...@@ -616,8 +617,6 @@ raw_heap_insert(RewriteState state, HeapTuple tup) ...@@ -616,8 +617,6 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
{ {
/* Doesn't fit, so write out the existing page */ /* Doesn't fit, so write out the existing page */
PageSetChecksumInplace(page, state->rs_blockno);
/* XLOG stuff */ /* XLOG stuff */
if (state->rs_use_wal) if (state->rs_use_wal)
log_newpage(&state->rs_new_rel->rd_node, log_newpage(&state->rs_new_rel->rd_node,
...@@ -632,6 +631,9 @@ raw_heap_insert(RewriteState state, HeapTuple tup) ...@@ -632,6 +631,9 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
* end_heap_rewrite. * end_heap_rewrite.
*/ */
RelationOpenSmgr(state->rs_new_rel); RelationOpenSmgr(state->rs_new_rel);
PageSetChecksumInplace(page, state->rs_blockno);
smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM, smgrextend(state->rs_new_rel->rd_smgr, MAIN_FORKNUM,
state->rs_blockno, (char *) page, true); state->rs_blockno, (char *) page, true);
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "commands/tablespace.h" #include "commands/tablespace.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "commands/typecmds.h" #include "commands/typecmds.h"
#include "common/relpath.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "foreign/foreign.h" #include "foreign/foreign.h"
#include "miscadmin.h" #include "miscadmin.h"
...@@ -8902,12 +8903,21 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst, ...@@ -8902,12 +8903,21 @@ copy_relation_data(SMgrRelation src, SMgrRelation dst,
smgrread(src, forkNum, blkno, buf); 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 */ /* XLOG stuff */
if (use_wal) if (use_wal)
log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page); 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 * 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 * rel, because there's no need for smgr to schedule an fsync for this
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment