From 893606e2aaf8e4f527d95daa5ef196e9967e6049 Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Mon, 29 Apr 2024 18:58:00 +0100 Subject: [PATCH 1/2] Fix usage of pg_waldump --ignore option. Previously, the --ignore option was only used when reading from a single file. --- src/bin/pg_waldump/pg_waldump.c | 40 +++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index d408315ec25..f8220d9f8b1 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -204,7 +204,7 @@ open_file_in_directory(const char *directory, const char *fname) * wal segment size. */ static bool -search_directory(const char *directory, const char *fname) +search_directory(const char *directory, const char *fname, bool ignore_format_errors) { int fd = -1; DIR *xldir; @@ -248,11 +248,26 @@ search_directory(const char *directory, const char *fname) WalSegSz = longhdr->xlp_seg_size; + // if we skip errors, we don't need to check the segment size if (!IsValidWalSegSize(WalSegSz)) + { + if (!ignore_format_errors) + { pg_fatal(ngettext("WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d byte", "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" header specifies %d bytes", WalSegSz), fname, WalSegSz); + } + else + { + struct stat stat; + if(fstat(fd, &stat) != 0) + pg_fatal("could not stat file \"%s\"", fname); + + /* Round up segment size to next power of 2 or 1MB */ + WalSegSz = Max(next_pow2_int(stat.st_size), 1024 * 1024); + } + } } else if (r < 0) pg_fatal("could not read file \"%s\": %m", @@ -282,18 +297,18 @@ search_directory(const char *directory, const char *fname) * The valid target directory is returned. */ static char * -identify_target_directory(char *directory, char *fname) +identify_target_directory(char *directory, char *fname, bool ignore_format_errors) { char fpath[MAXPGPATH]; if (directory != NULL) { - if (search_directory(directory, fname)) + if (search_directory(directory, fname, ignore_format_errors)) return pg_strdup(directory); /* directory / XLOGDIR */ snprintf(fpath, MAXPGPATH, "%s/%s", directory, XLOGDIR); - if (search_directory(fpath, fname)) + if (search_directory(fpath, fname, ignore_format_errors)) return pg_strdup(fpath); } else @@ -301,10 +316,10 @@ identify_target_directory(char *directory, char *fname) const char *datadir; /* current directory */ - if (search_directory(".", fname)) + if (search_directory(".", fname, ignore_format_errors)) return pg_strdup("."); /* XLOGDIR */ - if (search_directory(XLOGDIR, fname)) + if (search_directory(XLOGDIR, fname, ignore_format_errors)) return pg_strdup(XLOGDIR); datadir = getenv("PGDATA"); @@ -312,7 +327,7 @@ identify_target_directory(char *directory, char *fname) if (datadir != NULL) { snprintf(fpath, MAXPGPATH, "%s/%s", datadir, XLOGDIR); - if (search_directory(fpath, fname)) + if (search_directory(fpath, fname, ignore_format_errors)) return pg_strdup(fpath); } } @@ -1147,7 +1162,7 @@ main(int argc, char **argv) pg_fatal("could not open directory \"%s\": %m", waldir); } - waldir = identify_target_directory(waldir, fname); + waldir = identify_target_directory(waldir, fname, config.ignore_format_errors); fd = open_file_in_directory(waldir, fname); if (fd < 0) pg_fatal("could not open file \"%s\"", fname); @@ -1210,7 +1225,7 @@ main(int argc, char **argv) } else if (!single_file) - waldir = identify_target_directory(waldir, NULL); + waldir = identify_target_directory(waldir, NULL, config.ignore_format_errors); /* we don't know what to print */ if (XLogRecPtrIsInvalid(private.startptr) && !single_file) @@ -1245,6 +1260,13 @@ main(int argc, char **argv) } else { + if(config.ignore_format_errors) + { + xlogreader_state->skip_page_validation = true; + xlogreader_state->skip_invalid_records = true; + xlogreader_state->skip_lsn_checks = true; + } + /* first find a valid recptr to start from */ first_record = XLogFindNextRecord(xlogreader_state, private.startptr); From d6c949db38c932d9f29413a185f4dcf0d0b116b9 Mon Sep 17 00:00:00 2001 From: Anastasia Lubennikova Date: Wed, 1 May 2024 19:43:00 +0100 Subject: [PATCH 2/2] fix file size check --- src/bin/pg_waldump/pg_waldump.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index f8220d9f8b1..0d290968977 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -264,8 +264,17 @@ search_directory(const char *directory, const char *fname, bool ignore_format_er if(fstat(fd, &stat) != 0) pg_fatal("could not stat file \"%s\"", fname); - /* Round up segment size to next power of 2 or 1MB */ - WalSegSz = Max(next_pow2_int(stat.st_size), 1024 * 1024); + WalSegSz = stat.st_size; + + // if file size is invalid, the xlogreader will fail later with some obscure error + // so better to fail here + if (!IsValidWalSegSize(WalSegSz)) + { + pg_fatal(ngettext("WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" size is %d byte", + "WAL segment size must be a power of two between 1 MB and 1 GB, but the WAL file \"%s\" size is %d bytes", + WalSegSz), + fname, WalSegSz); + } } } }