On Thu, Jan 30, 2020 at 06:11:22PM +0100, Michael Banck wrote:
> The other question is whether it is possible to end up with a
> pg_internal.init.$PID file in a running cluster. E.g. if an instance
> crashes and gets started up again - are those cleaned up during crash
> recovery, or should pg_checksums ignore them? Right now pg_checksums
> only checks against a list of filenames and only skips on exact matches
> not prefixes so that might take a bit of work.

Indeed, with a bad timing and a crash in the middle of
write_relcache_init_file(), it could be possible to have such a file
left around in the data folder.  Having a past tablespace version left
around after an upgrade is a pilot error in my opinion because
pg_upgrade generates a script to cleanup past tablespaces, no?  So
your patch does not look like a good idea to me.  And now that I look
at it, if we happen to leave behind a temporary file for
pg_internal.init, backups fail with the following error:
2020-01-31 13:26:18.345 JST [102076] 010_pg_basebackup.pl ERROR:
invalid segment number 0 in file "pg_internal.init.123"

So, I think that it would be better to change basebackup.c,
pg_checksums and pg_rewind so as files are excluded if there is a
prefix match with the exclude lists.  Please see the attached.
--
Michael
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index dea8aab45e..37e4adb57b 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -168,7 +168,8 @@ static const char *const excludeDirContents[] =
 };
 
 /*
- * List of files excluded from backups.
+ * List of files excluded from backups.  Files are excluded if their
+ * prefix match.
  */
 static const char *const excludeFiles[] =
 {
@@ -198,7 +199,8 @@ static const char *const excludeFiles[] =
 };
 
 /*
- * List of files excluded from checksum validation.
+ * List of files excluded from checksum validation.  Files are excluded
+ * if their prefix match.
  *
  * Note: this list should be kept in sync with what pg_checksums.c
  * includes.
@@ -210,7 +212,6 @@ static const char *const noChecksumFiles[] = {
 	"PG_VERSION",
 #ifdef EXEC_BACKEND
 	"config_exec_params",
-	"config_exec_params.new",
 #endif
 	NULL,
 };
@@ -1084,7 +1085,8 @@ sendDir(const char *path, int basepathlen, bool sizeonly, List *tablespaces,
 		excludeFound = false;
 		for (excludeIdx = 0; excludeFiles[excludeIdx] != NULL; excludeIdx++)
 		{
-			if (strcmp(de->d_name, excludeFiles[excludeIdx]) == 0)
+			if (strncmp(de->d_name, excludeFiles[excludeIdx],
+						strlen(excludeFiles[excludeIdx])) == 0)
 			{
 				elog(DEBUG1, "file \"%s\" excluded from backup", de->d_name);
 				excludeFound = true;
@@ -1326,7 +1328,7 @@ is_checksummed_file(const char *fullpath, const char *filename)
 	{
 		/* Compare file against noChecksumFiles skiplist */
 		for (f = noChecksumFiles; *f; f++)
-			if (strcmp(*f, filename) == 0)
+			if (strncmp(*f, filename, strlen(*f)) == 0)
 				return false;
 
 		return true;
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index b7d36b65dd..1c14317099 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -6,7 +6,7 @@ use File::Basename qw(basename dirname);
 use File::Path qw(rmtree);
 use PostgresNode;
 use TestLib;
-use Test::More tests => 106;
+use Test::More tests => 107;
 
 program_help_ok('pg_basebackup');
 program_version_ok('pg_basebackup');
@@ -65,7 +65,8 @@ $node->restart;
 
 # Write some files to test that they are not copied.
 foreach my $filename (
-	qw(backup_label tablespace_map postgresql.auto.conf.tmp current_logfiles.tmp)
+	qw(backup_label tablespace_map postgresql.auto.conf.tmp
+	current_logfiles.tmp global/pg_internal.init.123)
   )
 {
 	open my $file, '>>', "$pgdata/$filename";
@@ -135,7 +136,7 @@ foreach my $dirname (
 # These files should not be copied.
 foreach my $filename (
 	qw(postgresql.auto.conf.tmp postmaster.opts postmaster.pid tablespace_map current_logfiles.tmp
-	global/pg_internal.init))
+	global/pg_internal.init global/pg_internal.init.123))
 {
 	ok(!-f "$tempdir/backup/$filename", "$filename not copied");
 }
diff --git a/src/bin/pg_checksums/pg_checksums.c b/src/bin/pg_checksums/pg_checksums.c
index 46ee1f1dc3..cd1a4bcd60 100644
--- a/src/bin/pg_checksums/pg_checksums.c
+++ b/src/bin/pg_checksums/pg_checksums.c
@@ -92,7 +92,8 @@ usage(void)
 }
 
 /*
- * List of files excluded from checksum validation.
+ * List of files excluded from checksum validation.  Files are excluded
+ * if their prefix match.
  *
  * Note: this list should be kept in sync with what basebackup.c includes.
  */
@@ -103,7 +104,6 @@ static const char *const skip[] = {
 	"PG_VERSION",
 #ifdef EXEC_BACKEND
 	"config_exec_params",
-	"config_exec_params.new",
 #endif
 	NULL,
 };
@@ -160,7 +160,7 @@ skipfile(const char *fn)
 	const char *const *f;
 
 	for (f = skip; *f; f++)
-		if (strcmp(*f, fn) == 0)
+		if (strncmp(*f, fn, strlen(*f)) == 0)
 			return true;
 
 	return false;
diff --git a/src/bin/pg_checksums/t/002_actions.pl b/src/bin/pg_checksums/t/002_actions.pl
index 59228b916c..933cf72a7c 100644
--- a/src/bin/pg_checksums/t/002_actions.pl
+++ b/src/bin/pg_checksums/t/002_actions.pl
@@ -112,6 +112,8 @@ append_to_file "$pgdata/global/99999_vm.123",   "";
 append_to_file "$pgdata/global/pgsql_tmp_123", "foo";
 mkdir "$pgdata/global/pgsql_tmp";
 append_to_file "$pgdata/global/pgsql_tmp/1.1", "foo";
+append_to_file "$pgdata/global/pg_internal.init", "foo";
+append_to_file "$pgdata/global/pg_internal.init.123", "foo";
 
 # Enable checksums.
 command_ok([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ],
diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c
index fd14844eec..7e55f74e8b 100644
--- a/src/bin/pg_rewind/filemap.c
+++ b/src/bin/pg_rewind/filemap.c
@@ -78,7 +78,8 @@ static const char *excludeDirContents[] =
 };
 
 /*
- * List of files excluded from filemap processing.
+ * List of files excluded from filemap processing.   Files are excluded
+ * if their prefix match.
  */
 static const char *excludeFiles[] =
 {
@@ -503,7 +504,8 @@ check_file_excluded(const char *path, bool is_source)
 			filename = path;
 		else
 			filename++;
-		if (strcmp(filename, excludeFiles[excludeIdx]) == 0)
+		if (strncmp(filename, excludeFiles[excludeIdx],
+					strlen(excludeFiles[excludeIdx])) == 0)
 		{
 			if (is_source)
 				pg_log_debug("entry \"%s\" excluded from source file list",

Attachment: signature.asc
Description: PGP signature

Reply via email to