@@ -136,7 +136,7 @@ static void apply_map_update(RelMapFile *map, Oid relationId, Oid fileNode,
136136 bool add_okay );
137137static void merge_map_updates (RelMapFile * map , const RelMapFile * updates ,
138138 bool add_okay );
139- static void load_relmap_file (bool shared );
139+ static void load_relmap_file (bool shared , bool lock_held );
140140static void write_relmap_file (bool shared , RelMapFile * newmap ,
141141 bool write_wal , bool send_sinval , bool preserve_files ,
142142 Oid dbid , Oid tsid , const char * dbpath );
@@ -405,12 +405,12 @@ RelationMapInvalidate(bool shared)
405405 if (shared )
406406 {
407407 if (shared_map .magic == RELMAPPER_FILEMAGIC )
408- load_relmap_file (true);
408+ load_relmap_file (true, false );
409409 }
410410 else
411411 {
412412 if (local_map .magic == RELMAPPER_FILEMAGIC )
413- load_relmap_file (false);
413+ load_relmap_file (false, false );
414414 }
415415}
416416
425425RelationMapInvalidateAll (void )
426426{
427427 if (shared_map .magic == RELMAPPER_FILEMAGIC )
428- load_relmap_file (true);
428+ load_relmap_file (true, false );
429429 if (local_map .magic == RELMAPPER_FILEMAGIC )
430- load_relmap_file (false);
430+ load_relmap_file (false, false );
431431}
432432
433433/*
@@ -612,7 +612,7 @@ RelationMapInitializePhase2(void)
612612 /*
613613 * Load the shared map file, die on error.
614614 */
615- load_relmap_file (true);
615+ load_relmap_file (true, false );
616616}
617617
618618/*
@@ -633,7 +633,7 @@ RelationMapInitializePhase3(void)
633633 /*
634634 * Load the local map file, die on error.
635635 */
636- load_relmap_file (false);
636+ load_relmap_file (false, false );
637637}
638638
639639/*
@@ -695,7 +695,7 @@ RestoreRelationMap(char *startAddress)
695695 * Note that the local case requires DatabasePath to be set up.
696696 */
697697static void
698- load_relmap_file (bool shared )
698+ load_relmap_file (bool shared , bool lock_held )
699699{
700700 RelMapFile * map ;
701701 char mapfilename [MAXPGPATH ];
@@ -725,12 +725,15 @@ load_relmap_file(bool shared)
725725 mapfilename )));
726726
727727 /*
728- * Note: we could take RelationMappingLock in shared mode here, but it
729- * seems unnecessary since our read() should be atomic against any
730- * concurrent updater's write(). If the file is updated shortly after we
731- * look, the sinval signaling mechanism will make us re-read it before we
732- * are able to access any relation that's affected by the change.
728+ * Grab the lock to prevent the file from being updated while we read it,
729+ * unless the caller is already holding the lock. If the file is updated
730+ * shortly after we look, the sinval signaling mechanism will make us
731+ * re-read it before we are able to access any relation that's affected by
732+ * the change.
733733 */
734+ if (!lock_held )
735+ LWLockAcquire (RelationMappingLock , LW_SHARED );
736+
734737 pgstat_report_wait_start (WAIT_EVENT_RELATION_MAP_READ );
735738 r = read (fd , map , sizeof (RelMapFile ));
736739 if (r != sizeof (RelMapFile ))
@@ -747,6 +750,9 @@ load_relmap_file(bool shared)
747750 }
748751 pgstat_report_wait_end ();
749752
753+ if (!lock_held )
754+ LWLockRelease (RelationMappingLock );
755+
750756 if (CloseTransientFile (fd ) != 0 )
751757 ereport (FATAL ,
752758 (errcode_for_file_access (),
@@ -969,7 +975,7 @@ perform_relmap_update(bool shared, const RelMapFile *updates)
969975 LWLockAcquire (RelationMappingLock , LW_EXCLUSIVE );
970976
971977 /* Be certain we see any other updates just made */
972- load_relmap_file (shared );
978+ load_relmap_file (shared , true );
973979
974980 /* Prepare updated data in a local variable */
975981 if (shared )
0 commit comments