@@ -82,7 +82,8 @@ static int64 sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeo
8282 backup_manifest_info * manifest , Oid spcoid );
8383static bool sendFile (bbsink * sink , const char * readfilename , const char * tarfilename ,
8484 struct stat * statbuf , bool missing_ok ,
85- Oid dboid , Oid spcoid ,
85+ Oid dboid , Oid spcoid , RelFileNumber relfilenumber ,
86+ unsigned segno ,
8687 backup_manifest_info * manifest );
8788static off_t read_file_data_into_buffer (bbsink * sink ,
8889 const char * readfilename , int fd ,
@@ -104,7 +105,6 @@ static void convert_link_to_directory(const char *pathbuf, struct stat *statbuf)
104105static void perform_base_backup (basebackup_options * opt , bbsink * sink );
105106static void parse_basebackup_options (List * options , basebackup_options * opt );
106107static int compareWalFileNames (const ListCell * a , const ListCell * b );
107- static bool is_checksummed_file (const char * fullpath , const char * filename );
108108static int basebackup_read_file (int fd , char * buf , size_t nbytes , off_t offset ,
109109 const char * filename , bool partial_read_ok );
110110
@@ -213,23 +213,6 @@ static const struct exclude_list_item excludeFiles[] =
213213 {NULL , false}
214214};
215215
216- /*
217- * List of files excluded from checksum validation.
218- *
219- * Note: this list should be kept in sync with what pg_checksums.c
220- * includes.
221- */
222- static const struct exclude_list_item noChecksumFiles [] = {
223- {"pg_control" , false},
224- {"pg_filenode.map" , false},
225- {"pg_internal.init" , true},
226- {"PG_VERSION" , false},
227- #ifdef EXEC_BACKEND
228- {"config_exec_params" , true},
229- #endif
230- {NULL , false}
231- };
232-
233216/*
234217 * Actually do a base backup for the specified tablespaces.
235218 *
@@ -356,7 +339,8 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
356339 errmsg ("could not stat file \"%s\": %m" ,
357340 XLOG_CONTROL_FILE )));
358341 sendFile (sink , XLOG_CONTROL_FILE , XLOG_CONTROL_FILE , & statbuf ,
359- false, InvalidOid , InvalidOid , & manifest );
342+ false, InvalidOid , InvalidOid ,
343+ InvalidRelFileNumber , 0 , & manifest );
360344 }
361345 else
362346 {
@@ -625,7 +609,8 @@ perform_base_backup(basebackup_options *opt, bbsink *sink)
625609 errmsg ("could not stat file \"%s\": %m" , pathbuf )));
626610
627611 sendFile (sink , pathbuf , pathbuf , & statbuf , false,
628- InvalidOid , InvalidOid , & manifest );
612+ InvalidOid , InvalidOid , InvalidRelFileNumber , 0 ,
613+ & manifest );
629614
630615 /* unconditionally mark file as archived */
631616 StatusFilePath (pathbuf , fname , ".done" );
@@ -1166,7 +1151,8 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
11661151 struct stat statbuf ;
11671152 int64 size = 0 ;
11681153 const char * lastDir ; /* Split last dir from parent path. */
1169- bool isDbDir = false; /* Does this directory contain relations? */
1154+ bool isRelationDir = false; /* Does directory contain relations? */
1155+ Oid dboid = InvalidOid ;
11701156
11711157 /*
11721158 * Determine if the current path is a database directory that can contain
@@ -1193,17 +1179,23 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
11931179 strncmp (lastDir - (sizeof (TABLESPACE_VERSION_DIRECTORY ) - 1 ),
11941180 TABLESPACE_VERSION_DIRECTORY ,
11951181 sizeof (TABLESPACE_VERSION_DIRECTORY ) - 1 ) == 0 ))
1196- isDbDir = true;
1182+ {
1183+ isRelationDir = true;
1184+ dboid = atooid (lastDir + 1 );
1185+ }
11971186 }
1187+ else if (strcmp (path , "./global" ) == 0 )
1188+ isRelationDir = true;
11981189
11991190 dir = AllocateDir (path );
12001191 while ((de = ReadDir (dir , path )) != NULL )
12011192 {
12021193 int excludeIdx ;
12031194 bool excludeFound ;
1204- RelFileNumber relNumber ;
1205- ForkNumber relForkNum ;
1206- unsigned segno ;
1195+ RelFileNumber relfilenumber = InvalidRelFileNumber ;
1196+ ForkNumber relForkNum = InvalidForkNumber ;
1197+ unsigned segno = 0 ;
1198+ bool isRelationFile = false;
12071199
12081200 /* Skip special stuff */
12091201 if (strcmp (de -> d_name , "." ) == 0 || strcmp (de -> d_name , ".." ) == 0 )
@@ -1251,37 +1243,40 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
12511243 if (excludeFound )
12521244 continue ;
12531245
1246+ /*
1247+ * If there could be non-temporary relation files in this directory,
1248+ * try to parse the filename.
1249+ */
1250+ if (isRelationDir )
1251+ isRelationFile =
1252+ parse_filename_for_nontemp_relation (de -> d_name ,
1253+ & relfilenumber ,
1254+ & relForkNum , & segno );
1255+
12541256 /* Exclude all forks for unlogged tables except the init fork */
1255- if (isDbDir &&
1256- parse_filename_for_nontemp_relation (de -> d_name , & relNumber ,
1257- & relForkNum , & segno ))
1257+ if (isRelationFile && relForkNum != INIT_FORKNUM )
12581258 {
1259- /* Never exclude init forks */
1260- if (relForkNum != INIT_FORKNUM )
1261- {
1262- char initForkFile [MAXPGPATH ];
1259+ char initForkFile [MAXPGPATH ];
12631260
1264- /*
1265- * If any other type of fork, check if there is an init fork
1266- * with the same RelFileNumber. If so, the file can be
1267- * excluded.
1268- */
1269- snprintf (initForkFile , sizeof (initForkFile ), "%s/%u_init" ,
1270- path , relNumber );
1261+ /*
1262+ * If any other type of fork, check if there is an init fork with
1263+ * the same RelFileNumber. If so, the file can be excluded.
1264+ */
1265+ snprintf (initForkFile , sizeof (initForkFile ), "%s/%u_init" ,
1266+ path , relfilenumber );
12711267
1272- if (lstat (initForkFile , & statbuf ) == 0 )
1273- {
1274- elog (DEBUG2 ,
1275- "unlogged relation file \"%s\" excluded from backup" ,
1276- de -> d_name );
1268+ if (lstat (initForkFile , & statbuf ) == 0 )
1269+ {
1270+ elog (DEBUG2 ,
1271+ "unlogged relation file \"%s\" excluded from backup" ,
1272+ de -> d_name );
12771273
1278- continue ;
1279- }
1274+ continue ;
12801275 }
12811276 }
12821277
12831278 /* Exclude temporary relations */
1284- if (isDbDir && looks_like_temp_rel_name (de -> d_name ))
1279+ if (OidIsValid ( dboid ) && looks_like_temp_rel_name (de -> d_name ))
12851280 {
12861281 elog (DEBUG2 ,
12871282 "temporary relation file \"%s\" excluded from backup" ,
@@ -1420,8 +1415,8 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
14201415
14211416 if (!sizeonly )
14221417 sent = sendFile (sink , pathbuf , pathbuf + basepathlen + 1 , & statbuf ,
1423- true, isDbDir ? atooid ( lastDir + 1 ) : InvalidOid , spcoid ,
1424- manifest );
1418+ true, dboid , spcoid ,
1419+ relfilenumber , segno , manifest );
14251420
14261421 if (sent || sizeonly )
14271422 {
@@ -1443,40 +1438,6 @@ sendDir(bbsink *sink, const char *path, int basepathlen, bool sizeonly,
14431438 return size ;
14441439}
14451440
1446- /*
1447- * Check if a file should have its checksum validated.
1448- * We validate checksums on files in regular tablespaces
1449- * (including global and default) only, and in those there
1450- * are some files that are explicitly excluded.
1451- */
1452- static bool
1453- is_checksummed_file (const char * fullpath , const char * filename )
1454- {
1455- /* Check that the file is in a tablespace */
1456- if (strncmp (fullpath , "./global/" , 9 ) == 0 ||
1457- strncmp (fullpath , "./base/" , 7 ) == 0 ||
1458- strncmp (fullpath , "/" , 1 ) == 0 )
1459- {
1460- int excludeIdx ;
1461-
1462- /* Compare file against noChecksumFiles skip list */
1463- for (excludeIdx = 0 ; noChecksumFiles [excludeIdx ].name != NULL ; excludeIdx ++ )
1464- {
1465- int cmplen = strlen (noChecksumFiles [excludeIdx ].name );
1466-
1467- if (!noChecksumFiles [excludeIdx ].match_prefix )
1468- cmplen ++ ;
1469- if (strncmp (filename , noChecksumFiles [excludeIdx ].name ,
1470- cmplen ) == 0 )
1471- return false;
1472- }
1473-
1474- return true;
1475- }
1476- else
1477- return false;
1478- }
1479-
14801441/*
14811442 * Given the member, write the TAR header & send the file.
14821443 *
@@ -1491,15 +1452,14 @@ is_checksummed_file(const char *fullpath, const char *filename)
14911452static bool
14921453sendFile (bbsink * sink , const char * readfilename , const char * tarfilename ,
14931454 struct stat * statbuf , bool missing_ok , Oid dboid , Oid spcoid ,
1455+ RelFileNumber relfilenumber , unsigned segno ,
14941456 backup_manifest_info * manifest )
14951457{
14961458 int fd ;
14971459 BlockNumber blkno = 0 ;
14981460 int checksum_failures = 0 ;
14991461 off_t cnt ;
15001462 pgoff_t bytes_done = 0 ;
1501- int segmentno = 0 ;
1502- char * segmentpath ;
15031463 bool verify_checksum = false;
15041464 pg_checksum_context checksum_ctx ;
15051465
@@ -1525,36 +1485,14 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
15251485 */
15261486 Assert ((sink -> bbs_buffer_length % BLCKSZ ) == 0 );
15271487
1528- if (!noverify_checksums && DataChecksumsEnabled ())
1529- {
1530- char * filename ;
1531-
1532- /*
1533- * Get the filename (excluding path). As last_dir_separator()
1534- * includes the last directory separator, we chop that off by
1535- * incrementing the pointer.
1536- */
1537- filename = last_dir_separator (readfilename ) + 1 ;
1538-
1539- if (is_checksummed_file (readfilename , filename ))
1540- {
1541- verify_checksum = true;
1542-
1543- /*
1544- * Cut off at the segment boundary (".") to get the segment number
1545- * in order to mix it into the checksum.
1546- */
1547- segmentpath = strstr (filename , "." );
1548- if (segmentpath != NULL )
1549- {
1550- segmentno = atoi (segmentpath + 1 );
1551- if (segmentno == 0 )
1552- ereport (ERROR ,
1553- (errmsg ("invalid segment number %d in file \"%s\"" ,
1554- segmentno , filename )));
1555- }
1556- }
1557- }
1488+ /*
1489+ * If we weren't told not to verify checksums, and if checksums are
1490+ * enabled for this cluster, and if this is a relation file, then verify
1491+ * the checksum.
1492+ */
1493+ if (!noverify_checksums && DataChecksumsEnabled () &&
1494+ RelFileNumberIsValid (relfilenumber ))
1495+ verify_checksum = true;
15581496
15591497 /*
15601498 * Loop until we read the amount of data the caller told us to expect. The
@@ -1569,7 +1507,7 @@ sendFile(bbsink *sink, const char *readfilename, const char *tarfilename,
15691507 /* Try to read some more data. */
15701508 cnt = read_file_data_into_buffer (sink , readfilename , fd , bytes_done ,
15711509 remaining ,
1572- blkno + segmentno * RELSEG_SIZE ,
1510+ blkno + segno * RELSEG_SIZE ,
15731511 verify_checksum ,
15741512 & checksum_failures );
15751513
0 commit comments