Skip foreign tablespaces when running pg_checksums/pg_verify_checksums
Attempting to use pg_checksums (pg_verify_checksums in 11) on a data folder which includes tablespace paths used across multiple major versions would cause pg_checksums to scan all directories present in pg_tblspc, and not only marked with TABLESPACE_VERSION_DIRECTORY. This could lead to failures when for example running sanity checks on an upgraded instance with --check. Even worse, it was possible to rewrite on-disk pages with --enable for a cluster potentially online. This commit makes pg_checksums skip any directories not named TABLESPACE_VERSION_DIRECTORY, similarly to what is done for base backups. Reported-by: Michael Banck Author: Michael Banck, Bernd Helmle Discussion: https://postgr.es/m/62031974fd8e941dd8351fbc8c7eff60d59c5338.camel@credativ.de backpatch-through: 11
This commit is contained in:
parent
05d8449e73
commit
428a2609ef
@ -385,8 +385,53 @@ scan_directory(const char *basedir, const char *subdir, bool sizeonly)
|
|||||||
#else
|
#else
|
||||||
else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
|
else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If going through the entries of pg_tblspc, we assume to operate
|
||||||
|
* on tablespace locations where only TABLESPACE_VERSION_DIRECTORY
|
||||||
|
* is valid, resolving the linked locations and dive into them
|
||||||
|
* directly.
|
||||||
|
*/
|
||||||
|
if (strncmp("pg_tblspc", subdir, strlen("pg_tblspc")) == 0)
|
||||||
|
{
|
||||||
|
char tblspc_path[MAXPGPATH];
|
||||||
|
struct stat tblspc_st;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resolve tablespace location path and check whether
|
||||||
|
* TABLESPACE_VERSION_DIRECTORY exists. Not finding a valid
|
||||||
|
* location is unexpected, since there should be no orphaned
|
||||||
|
* links and no links pointing to something else than a
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
snprintf(tblspc_path, sizeof(tblspc_path), "%s/%s/%s",
|
||||||
|
path, de->d_name, TABLESPACE_VERSION_DIRECTORY);
|
||||||
|
|
||||||
|
if (lstat(tblspc_path, &tblspc_st) < 0)
|
||||||
|
{
|
||||||
|
pg_log_error("could not stat file \"%s\": %m",
|
||||||
|
tblspc_path);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move backwards once as the scan needs to happen for the
|
||||||
|
* contents of TABLESPACE_VERSION_DIRECTORY.
|
||||||
|
*/
|
||||||
|
snprintf(tblspc_path, sizeof(tblspc_path), "%s/%s",
|
||||||
|
path, de->d_name);
|
||||||
|
|
||||||
|
/* Looks like a valid tablespace location */
|
||||||
|
dirsize += scan_directory(tblspc_path,
|
||||||
|
TABLESPACE_VERSION_DIRECTORY,
|
||||||
|
sizeonly);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
dirsize += scan_directory(path, de->d_name, sizeonly);
|
dirsize += scan_directory(path, de->d_name, sizeonly);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
return dirsize;
|
return dirsize;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use strict;
|
|||||||
use warnings;
|
use warnings;
|
||||||
use PostgresNode;
|
use PostgresNode;
|
||||||
use TestLib;
|
use TestLib;
|
||||||
use Test::More tests => 62;
|
use Test::More tests => 63;
|
||||||
|
|
||||||
|
|
||||||
# Utility routine to create and check a table with corrupted checksums
|
# Utility routine to create and check a table with corrupted checksums
|
||||||
@ -217,6 +217,13 @@ sub fail_corrupt
|
|||||||
# Stop instance for the follow-up checks.
|
# Stop instance for the follow-up checks.
|
||||||
$node->stop;
|
$node->stop;
|
||||||
|
|
||||||
|
# Create a fake tablespace location that should not be scanned
|
||||||
|
# when verifying checksums.
|
||||||
|
mkdir "$tablespace_dir/PG_99_999999991/";
|
||||||
|
append_to_file "$tablespace_dir/PG_99_999999991/foo", "123";
|
||||||
|
command_ok([ 'pg_checksums', '--check', '-D', $pgdata ],
|
||||||
|
"succeeds with foreign tablespace");
|
||||||
|
|
||||||
# Authorized relation files filled with corrupted data cause the
|
# Authorized relation files filled with corrupted data cause the
|
||||||
# checksum checks to fail. Make sure to use file names different
|
# checksum checks to fail. Make sure to use file names different
|
||||||
# than the previous ones.
|
# than the previous ones.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user