From 306c827c876378ddc128b030b8838a8e811743f2 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 15 Aug 2024 08:27:54 +0200 Subject: [PATCH v0] pg_upgrade support for upgrading to checksums enabled --- src/bin/pg_upgrade/controldata.c | 17 +++++------------ src/bin/pg_upgrade/file.c | 21 ++++++++++++++++++++- src/bin/pg_upgrade/pg_upgrade.h | 3 ++- src/bin/pg_upgrade/relfilenumber.c | 2 +- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/bin/pg_upgrade/controldata.c b/src/bin/pg_upgrade/controldata.c index 854c6887a23..16d0b84b337 100644 --- a/src/bin/pg_upgrade/controldata.c +++ b/src/bin/pg_upgrade/controldata.c @@ -693,18 +693,11 @@ check_control_data(ControlData *oldctrl, * check_for_isn_and_int8_passing_mismatch(). */ - /* - * We might eventually allow upgrades from checksum to no-checksum - * clusters. - */ - if (oldctrl->data_checksum_version == 0 && - newctrl->data_checksum_version != 0) - pg_fatal("old cluster does not use data checksums but the new one does"); - else if (oldctrl->data_checksum_version != 0 && - newctrl->data_checksum_version == 0) - pg_fatal("old cluster uses data checksums but the new one does not"); - else if (oldctrl->data_checksum_version != newctrl->data_checksum_version) - pg_fatal("old and new cluster pg_controldata checksum versions do not match"); + if (user_opts.transfer_mode != TRANSFER_MODE_COPY) + { + if (oldctrl->data_checksum_version != newctrl->data_checksum_version) + pg_fatal("when upgrading between clusters with different data checksum settings, transfer mode --copy must be used"); + } } diff --git a/src/bin/pg_upgrade/file.c b/src/bin/pg_upgrade/file.c index 73932504cae..cef33b8f6eb 100644 --- a/src/bin/pg_upgrade/file.c +++ b/src/bin/pg_upgrade/file.c @@ -80,12 +80,14 @@ cloneFile(const char *src, const char *dst, */ void copyFile(const char *src, const char *dst, - const char *schemaName, const char *relName) + const char *schemaName, const char *relName, + int segno) { #ifndef WIN32 int src_fd; int dest_fd; char *buffer; + BlockNumber blocknum; if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0) pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %m", @@ -101,6 +103,8 @@ copyFile(const char *src, const char *dst, buffer = (char *) pg_malloc(COPY_BUF_SIZE); + blocknum = segno * old_cluster.controldata.largesz; + /* perform data copying i.e read src source, write to destination */ while (true) { @@ -113,6 +117,19 @@ copyFile(const char *src, const char *dst, if (nbytes == 0) break; + if (new_cluster.controldata.data_checksum_version == 1) + { + for (int i = 0; i < 50 && i * BLCKSZ < nbytes; i++) + { + uint16 csum; + char *block = buffer + i * BLCKSZ; + PageHeader header = (PageHeader) block; + + csum = pg_checksum_page(block, blocknum + i); + header->pd_checksum = csum; + } + } + errno = 0; if (write(dest_fd, buffer, nbytes) != nbytes) { @@ -122,6 +139,8 @@ copyFile(const char *src, const char *dst, pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %m", schemaName, relName, dst); } + + blocknum += 50; } pg_free(buffer); diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h index cdb6e2b7597..c6a4ade53a7 100644 --- a/src/bin/pg_upgrade/pg_upgrade.h +++ b/src/bin/pg_upgrade/pg_upgrade.h @@ -404,7 +404,8 @@ bool pid_lock_file_exists(const char *datadir); void cloneFile(const char *src, const char *dst, const char *schemaName, const char *relName); void copyFile(const char *src, const char *dst, - const char *schemaName, const char *relName); + const char *schemaName, const char *relName, + int segno); void copyFileByRange(const char *src, const char *dst, const char *schemaName, const char *relName); void linkFile(const char *src, const char *dst, diff --git a/src/bin/pg_upgrade/relfilenumber.c b/src/bin/pg_upgrade/relfilenumber.c index 1d3054d78bd..2ae69d71159 100644 --- a/src/bin/pg_upgrade/relfilenumber.c +++ b/src/bin/pg_upgrade/relfilenumber.c @@ -250,7 +250,7 @@ transfer_relfile(FileNameMap *map, const char *type_suffix, bool vm_must_add_fro case TRANSFER_MODE_COPY: pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\"", old_file, new_file); - copyFile(old_file, new_file, map->nspname, map->relname); + copyFile(old_file, new_file, map->nspname, map->relname, segno); break; case TRANSFER_MODE_COPY_FILE_RANGE: pg_log(PG_VERBOSE, "copying \"%s\" to \"%s\" with copy_file_range", -- 2.46.0