@@ -137,8 +137,10 @@ static void apply_map_update(RelMapFile *map, Oid relationId, Oid fileNode,
137137static void merge_map_updates (RelMapFile * map , const RelMapFile * updates ,
138138 bool add_okay );
139139static void load_relmap_file (bool shared , bool lock_held );
140- static void write_relmap_file (bool shared , RelMapFile * newmap ,
141- bool write_wal , bool send_sinval , bool preserve_files ,
140+ static void read_relmap_file (RelMapFile * map , char * dbpath , bool lock_held ,
141+ int elevel );
142+ static void write_relmap_file (RelMapFile * newmap , bool write_wal ,
143+ bool send_sinval , bool preserve_files ,
142144 Oid dbid , Oid tsid , const char * dbpath );
143145static void perform_relmap_update (bool shared , const RelMapFile * updates );
144146
@@ -568,9 +570,9 @@ RelationMapFinishBootstrap(void)
568570 Assert (pending_local_updates .num_mappings == 0 );
569571
570572 /* Write the files; no WAL or sinval needed */
571- write_relmap_file (true, & shared_map , false, false, false,
572- InvalidOid , GLOBALTABLESPACE_OID , NULL );
573- write_relmap_file (false, & local_map , false, false, false,
573+ write_relmap_file (& shared_map , false, false, false,
574+ InvalidOid , GLOBALTABLESPACE_OID , "global" );
575+ write_relmap_file (& local_map , false, false, false,
574576 MyDatabaseId , MyDatabaseTableSpace , DatabasePath );
575577}
576578
@@ -687,39 +689,48 @@ RestoreRelationMap(char *startAddress)
687689}
688690
689691/*
690- * load_relmap_file -- load data from the shared or local map file
692+ * load_relmap_file -- load the shared or local map file
691693 *
692- * Because the map file is essential for access to core system catalogs,
693- * failure to read it is a fatal error.
694+ * Because these files are essential for access to core system catalogs,
695+ * failure to load either of them is a fatal error.
694696 *
695697 * Note that the local case requires DatabasePath to be set up.
696698 */
697699static void
698700load_relmap_file (bool shared , bool lock_held )
699701{
700- RelMapFile * map ;
702+ if (shared )
703+ read_relmap_file (& shared_map , "global" , lock_held , FATAL );
704+ else
705+ read_relmap_file (& local_map , DatabasePath , lock_held , FATAL );
706+ }
707+
708+ /*
709+ * read_relmap_file -- load data from any relation mapper file
710+ *
711+ * dbpath must be the relevant database path, or "global" for shared relations.
712+ *
713+ * RelationMappingLock will be acquired released unless lock_held = true.
714+ *
715+ * Errors will be reported at the indicated elevel, which should be at least
716+ * ERROR.
717+ */
718+ static void
719+ read_relmap_file (RelMapFile * map , char * dbpath , bool lock_held , int elevel )
720+ {
701721 char mapfilename [MAXPGPATH ];
702722 pg_crc32c crc ;
703723 int fd ;
704724 int r ;
705725
706- if (shared )
707- {
708- snprintf (mapfilename , sizeof (mapfilename ), "global/%s" ,
709- RELMAPPER_FILENAME );
710- map = & shared_map ;
711- }
712- else
713- {
714- snprintf (mapfilename , sizeof (mapfilename ), "%s/%s" ,
715- DatabasePath , RELMAPPER_FILENAME );
716- map = & local_map ;
717- }
726+ Assert (elevel >= ERROR );
718727
719- /* Read data ... */
728+ /* Open the target file. */
729+ snprintf (mapfilename , sizeof (mapfilename ), "%s/%s" , dbpath ,
730+ RELMAPPER_FILENAME );
720731 fd = OpenTransientFile (mapfilename , O_RDONLY | PG_BINARY );
721732 if (fd < 0 )
722- ereport (FATAL ,
733+ ereport (elevel ,
723734 (errcode_for_file_access (),
724735 errmsg ("could not open file \"%s\": %m" ,
725736 mapfilename )));
@@ -734,16 +745,17 @@ load_relmap_file(bool shared, bool lock_held)
734745 if (!lock_held )
735746 LWLockAcquire (RelationMappingLock , LW_SHARED );
736747
748+ /* Now read the data. */
737749 pgstat_report_wait_start (WAIT_EVENT_RELATION_MAP_READ );
738750 r = read (fd , map , sizeof (RelMapFile ));
739751 if (r != sizeof (RelMapFile ))
740752 {
741753 if (r < 0 )
742- ereport (FATAL ,
754+ ereport (elevel ,
743755 (errcode_for_file_access (),
744756 errmsg ("could not read file \"%s\": %m" , mapfilename )));
745757 else
746- ereport (FATAL ,
758+ ereport (elevel ,
747759 (errcode (ERRCODE_DATA_CORRUPTED ),
748760 errmsg ("could not read file \"%s\": read %d of %zu" ,
749761 mapfilename , r , sizeof (RelMapFile ))));
@@ -754,7 +766,7 @@ load_relmap_file(bool shared, bool lock_held)
754766 LWLockRelease (RelationMappingLock );
755767
756768 if (CloseTransientFile (fd ) != 0 )
757- ereport (FATAL ,
769+ ereport (elevel ,
758770 (errcode_for_file_access (),
759771 errmsg ("could not close file \"%s\": %m" ,
760772 mapfilename )));
@@ -763,7 +775,7 @@ load_relmap_file(bool shared, bool lock_held)
763775 if (map -> magic != RELMAPPER_FILEMAGIC ||
764776 map -> num_mappings < 0 ||
765777 map -> num_mappings > MAX_MAPPINGS )
766- ereport (FATAL ,
778+ ereport (elevel ,
767779 (errmsg ("relation mapping file \"%s\" contains invalid data" ,
768780 mapfilename )));
769781
@@ -773,7 +785,7 @@ load_relmap_file(bool shared, bool lock_held)
773785 FIN_CRC32C (crc );
774786
775787 if (!EQ_CRC32C (crc , map -> crc ))
776- ereport (FATAL ,
788+ ereport (elevel ,
777789 (errmsg ("relation mapping file \"%s\" contains incorrect checksum" ,
778790 mapfilename )));
779791}
@@ -795,16 +807,16 @@ load_relmap_file(bool shared, bool lock_held)
795807 *
796808 * Because this may be called during WAL replay when MyDatabaseId,
797809 * DatabasePath, etc aren't valid, we require the caller to pass in suitable
798- * values. The caller is also responsible for being sure no concurrent
799- * map update could be happening.
810+ * values. Pass dbpath as "global" for the shared map.
811+ *
812+ * The caller is also responsible for being sure no concurrent map update
813+ * could be happening.
800814 */
801815static void
802- write_relmap_file (bool shared , RelMapFile * newmap ,
803- bool write_wal , bool send_sinval , bool preserve_files ,
804- Oid dbid , Oid tsid , const char * dbpath )
816+ write_relmap_file (RelMapFile * newmap , bool write_wal , bool send_sinval ,
817+ bool preserve_files , Oid dbid , Oid tsid , const char * dbpath )
805818{
806819 int fd ;
807- RelMapFile * realmap ;
808820 char mapfilename [MAXPGPATH ];
809821
810822 /*
@@ -822,19 +834,8 @@ write_relmap_file(bool shared, RelMapFile *newmap,
822834 * Open the target file. We prefer to do this before entering the
823835 * critical section, so that an open() failure need not force PANIC.
824836 */
825- if (shared )
826- {
827- snprintf (mapfilename , sizeof (mapfilename ), "global/%s" ,
828- RELMAPPER_FILENAME );
829- realmap = & shared_map ;
830- }
831- else
832- {
833- snprintf (mapfilename , sizeof (mapfilename ), "%s/%s" ,
834- dbpath , RELMAPPER_FILENAME );
835- realmap = & local_map ;
836- }
837-
837+ snprintf (mapfilename , sizeof (mapfilename ), "%s/%s" ,
838+ dbpath , RELMAPPER_FILENAME );
838839 fd = OpenTransientFile (mapfilename , O_WRONLY | O_CREAT | PG_BINARY );
839840 if (fd < 0 )
840841 ereport (ERROR ,
@@ -934,16 +935,6 @@ write_relmap_file(bool shared, RelMapFile *newmap,
934935 }
935936 }
936937
937- /*
938- * Success, update permanent copy. During bootstrap, we might be working
939- * on the permanent copy itself, in which case skip the memcpy() to avoid
940- * invoking nominally-undefined behavior.
941- */
942- if (realmap != newmap )
943- memcpy (realmap , newmap , sizeof (RelMapFile ));
944- else
945- Assert (!send_sinval ); /* must be bootstrapping */
946-
947938 /* Critical section done */
948939 if (write_wal )
949940 END_CRIT_SECTION ();
@@ -990,10 +981,19 @@ perform_relmap_update(bool shared, const RelMapFile *updates)
990981 merge_map_updates (& newmap , updates , allowSystemTableMods );
991982
992983 /* Write out the updated map and do other necessary tasks */
993- write_relmap_file (shared , & newmap , true, true, true,
984+ write_relmap_file (& newmap , true, true, true,
994985 (shared ? InvalidOid : MyDatabaseId ),
995986 (shared ? GLOBALTABLESPACE_OID : MyDatabaseTableSpace ),
996- DatabasePath );
987+ (shared ? "global" : DatabasePath ));
988+
989+ /*
990+ * We succesfully wrote the updated file, so it's now safe to rely on the
991+ * new values in this process, too.
992+ */
993+ if (shared )
994+ memcpy (& shared_map , & newmap , sizeof (RelMapFile ));
995+ else
996+ memcpy (& local_map , & newmap , sizeof (RelMapFile ));
997997
998998 /* Now we can release the lock */
999999 LWLockRelease (RelationMappingLock );
@@ -1033,8 +1033,7 @@ relmap_redo(XLogReaderState *record)
10331033 * but grab the lock to interlock against load_relmap_file().
10341034 */
10351035 LWLockAcquire (RelationMappingLock , LW_EXCLUSIVE );
1036- write_relmap_file ((xlrec -> dbid == InvalidOid ), & newmap ,
1037- false, true, false,
1036+ write_relmap_file (& newmap , false, true, false,
10381037 xlrec -> dbid , xlrec -> tsid , dbpath );
10391038 LWLockRelease (RelationMappingLock );
10401039
0 commit comments