mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-07 19:47:50 +08:00
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
This commit is contained in:
parent
7844608e54
commit
cf8dc9e10c
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user