From 92da58e2f4e05960ca005c69c1d11ec1f9edd965 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Sun, 31 Mar 2024 14:55:29 +0200 Subject: [PATCH v20240401 1/7] WIP: block alignment Make sure the blocks in the incremental files are properly aligned to 8KB boundaries, so that CoW works correctly. --- src/backend/backup/basebackup.c | 16 ++++++++++++++++ src/backend/backup/basebackup_incremental.c | 10 ++++++++-- src/bin/pg_combinebackup/reconstruct.c | 6 ++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/backend/backup/basebackup.c b/src/backend/backup/basebackup.c index 5fea86ad0fd..96e981a98f0 100644 --- a/src/backend/backup/basebackup.c +++ b/src/backend/backup/basebackup.c @@ -1635,6 +1635,19 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, incremental_blocks, sizeof(BlockNumber) * num_incremental_blocks); + /* align header to a multiple of BLCKSZ */ + if (header_bytes_done % BLCKSZ != 0) + { + char padding[BLCKSZ]; + size_t paddinglen = (BLCKSZ - (header_bytes_done % BLCKSZ)); + + bytes_done += paddinglen; + memset(padding, 0, paddinglen); + + push_to_sink(sink, &checksum_ctx, &header_bytes_done, + padding, paddinglen); + } + /* Flush out any data still in the buffer so it's again empty. */ if (header_bytes_done > 0) { @@ -1748,6 +1761,9 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename, blkno += cnt / BLCKSZ; bytes_done += cnt; + if ((incremental_blocks != NULL) && (bytes_done % BLCKSZ != 0)) + elog(FATAL, "incorrect file size '%s' bytes_done %lu", tarfilename, bytes_done); + /* Archive the data we just read. */ bbsink_archive_contents(sink, cnt); diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c index 990b2872eaf..d425a3f555e 100644 --- a/src/backend/backup/basebackup_incremental.c +++ b/src/backend/backup/basebackup_incremental.c @@ -917,8 +917,14 @@ GetIncrementalFileSize(unsigned num_blocks_required) * Three four byte quantities (magic number, truncation block length, * block count) followed by block numbers followed by block contents. */ - result = 3 * sizeof(uint32); - result += (BLCKSZ + sizeof(BlockNumber)) * num_blocks_required; + result = 3 * sizeof(uint32) + (sizeof(BlockNumber) * num_blocks_required); + + if (result % BLCKSZ != 0) + { + result += BLCKSZ - (result % BLCKSZ); + } + + result += BLCKSZ * num_blocks_required; return result; } diff --git a/src/bin/pg_combinebackup/reconstruct.c b/src/bin/pg_combinebackup/reconstruct.c index 41f06bb26b5..e6cb9a206e2 100644 --- a/src/bin/pg_combinebackup/reconstruct.c +++ b/src/bin/pg_combinebackup/reconstruct.c @@ -472,6 +472,12 @@ make_incremental_rfile(char *filename) sizeof(rf->truncation_block_length) + sizeof(BlockNumber) * rf->num_blocks; + /* align header to multiple of BLCKSZ */ + if (rf->header_length % BLCKSZ != 0) + { + rf->header_length += (BLCKSZ - (rf->header_length % BLCKSZ)); + } + return rf; } -- 2.44.0