diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index 69a7a23874..d854a84bf3 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -500,12 +500,6 @@ loop:
 			/* use this page as future insert target, too */
 			RelationSetTargetBlock(relation, targetBlock);
 
-			/*
-			 * In case we used an in-memory map of available blocks, reset it
-			 * for next use.
-			 */
-			FSMClearLocalMap();
-
 			return buffer;
 		}
 
@@ -675,8 +669,5 @@ loop:
 	 */
 	RelationSetTargetBlock(relation, BufferGetBlockNumber(buffer));
 
-	/* This should already be cleared by now, but make sure it is. */
-	FSMClearLocalMap();
-
 	return buffer;
 }
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 8522a2f51c..d14c41ddaa 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -2587,12 +2587,6 @@ AbortTransaction(void)
 	pgstat_report_wait_end();
 	pgstat_progress_end_command();
 
-	/*
-	 * In case we aborted during RelationGetBufferForTuple(), clear the local
-	 * map of heap pages.
-	 */
-	FSMClearLocalMap();
-
 	/* Clean up buffer I/O and buffer context locks, too */
 	AbortBufferIO();
 	UnlockBuffers();
@@ -4881,12 +4875,6 @@ AbortSubTransaction(void)
 	pgstat_report_wait_end();
 	pgstat_progress_end_command();
 
-	/*
-	 * In case we aborted during RelationGetBufferForTuple(), clear the local
-	 * map of heap pages.
-	 */
-	FSMClearLocalMap();
-
 	AbortBufferIO();
 	UnlockBuffers();
 
diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index c3ed4242e2..107b2da030 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -30,6 +30,7 @@
 #include "storage/fsm_internals.h"
 #include "storage/lmgr.h"
 #include "storage/smgr.h"
+#include "utils/memutils.h"
 
 
 /*
@@ -76,14 +77,6 @@
 #define FSM_ROOT_LEVEL	(FSM_TREE_DEPTH - 1)
 #define FSM_BOTTOM_LEVEL 0
 
-/* Status codes for the local map. */
-
-/* Either already tried, or beyond the end of the relation */
-#define FSM_LOCAL_NOT_AVAIL 0x00
-
-/* Available to try */
-#define FSM_LOCAL_AVAIL		0x01
-
 /*
  * The internal FSM routines work on a logical addressing scheme. Each
  * level of the tree can be thought of as a separately addressable file.
@@ -97,31 +90,7 @@ typedef struct
 /* Address of the root page. */
 static const FSMAddress FSM_ROOT_ADDRESS = {FSM_ROOT_LEVEL, 0};
 
-/*
- * For small relations, we don't create FSM to save space, instead we use
- * local in-memory map of pages to try.  To locate free space, we simply try
- * pages directly without knowing ahead of time how much free space they have.
- *
- * Note that this map is used to the find the block with required free space
- * for any given relation.  We clear this map when we have found a block with
- * enough free space, when we extend the relation, or on transaction abort.
- * See src/backend/storage/freespace/README for further details.
- */
-typedef struct
-{
-	BlockNumber nblocks;
-	uint8		map[HEAP_FSM_CREATION_THRESHOLD];
-}			FSMLocalMap;
-
-static FSMLocalMap fsm_local_map =
-{
-	0,
-	{
-		FSM_LOCAL_NOT_AVAIL
-	}
-};
-
-#define FSM_LOCAL_MAP_EXISTS (fsm_local_map.nblocks > 0)
+#define FSM_LOCAL_MAP_EXISTS(rel) (rel->fsm_local_map->nblocks > 0)
 
 /* functions to navigate the tree */
 static FSMAddress fsm_get_child(FSMAddress parent, uint16 slot);
@@ -143,12 +112,13 @@ static int fsm_set_and_search(Relation rel, FSMAddress addr, uint16 slot,
 				   uint8 newValue, uint8 minValue);
 static void fsm_local_set(Relation rel, BlockNumber cur_nblocks);
 static BlockNumber fsm_search(Relation rel, uint8 min_cat);
-static BlockNumber fsm_local_search(void);
+static BlockNumber fsm_local_search(Relation rel);
 static uint8 fsm_vacuum_page(Relation rel, FSMAddress addr,
 				BlockNumber start, BlockNumber end,
 				bool *eof);
 static bool fsm_allow_writes(Relation rel, BlockNumber heapblk,
 				 BlockNumber nblocks, BlockNumber *get_nblocks);
+static void fsm_clear_local_map(Relation rel);
 
 
 /******** Public API ********/
@@ -195,14 +165,17 @@ GetPageWithFreeSpace(Relation rel, Size spaceNeeded, bool check_fsm_only)
 			 * during bootstrapping or in a recently-started system.
 			 */
 			target_block = nblocks - 1;
+			fsm_clear_local_map(rel);
 		}
 		else if (nblocks > 0)
 		{
 			/* Initialize local map and get first candidate block. */
 			fsm_local_set(rel, nblocks);
-			target_block = fsm_local_search();
+			target_block = fsm_local_search(rel);
 		}
 	}
+	else
+		fsm_clear_local_map(rel);
 
 	return target_block;
 }
@@ -231,14 +204,14 @@ RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage,
 	BlockNumber nblocks = InvalidBlockNumber;
 
 	/* First try the local map, if it exists. */
-	if (FSM_LOCAL_MAP_EXISTS)
+	if (FSM_LOCAL_MAP_EXISTS(rel))
 	{
 		Assert((rel->rd_rel->relkind == RELKIND_RELATION ||
 				rel->rd_rel->relkind == RELKIND_TOASTVALUE) &&
-			   fsm_local_map.map[oldPage] == FSM_LOCAL_AVAIL);
+			   rel->fsm_local_map->map[oldPage] == FSM_LOCAL_AVAIL);
 
-		fsm_local_map.map[oldPage] = FSM_LOCAL_NOT_AVAIL;
-		return fsm_local_search();
+		rel->fsm_local_map->map[oldPage] = FSM_LOCAL_NOT_AVAIL;
+		return fsm_local_search(rel);
 	}
 
 	if (!fsm_allow_writes(rel, oldPage, InvalidBlockNumber, &nblocks))
@@ -249,8 +222,10 @@ RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage,
 		 * need to create the local map.
 		 */
 		fsm_local_set(rel, nblocks);
-		return fsm_local_search();
+		return fsm_local_search(rel);
 	}
+	else
+		fsm_clear_local_map(rel);
 
 	/* Normal FSM logic follows */
 
@@ -302,18 +277,21 @@ RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk,
 }
 
 /*
- * Clear the local map.  We must call this when we have found a block with
- * enough free space, when we extend the relation, or on transaction abort.
+ * Initialize FSM Relation Map.
  */
 void
-FSMClearLocalMap(void)
+RelationInitFSMMap(Relation rel)
 {
-	if (FSM_LOCAL_MAP_EXISTS)
-	{
-		fsm_local_map.nblocks = 0;
-		memset(&fsm_local_map.map, FSM_LOCAL_NOT_AVAIL,
-			   sizeof(fsm_local_map.map));
-	}
+	FSMLocalMap *fsm_local_map;
+	MemoryContext	oldcontext;
+
+	oldcontext = MemoryContextSwitchTo(CacheMemoryContext);
+	fsm_local_map = palloc(sizeof(FSMLocalMap));
+	fsm_local_map->nblocks = 0;
+	memset(&fsm_local_map->map, FSM_LOCAL_NOT_AVAIL,
+		   sizeof(fsm_local_map->map));
+	rel->fsm_local_map = fsm_local_map;
+	MemoryContextSwitchTo(oldcontext);
 }
 
 /*
@@ -1132,9 +1110,6 @@ fsm_local_set(Relation rel, BlockNumber cur_nblocks)
 	BlockNumber blkno,
 				cached_target_block;
 
-	/* The local map must not be set already. */
-	Assert(!FSM_LOCAL_MAP_EXISTS);
-
 	/*
 	 * Starting at the current last block in the relation and working
 	 * backwards, mark alternating blocks as available.
@@ -1142,7 +1117,7 @@ fsm_local_set(Relation rel, BlockNumber cur_nblocks)
 	blkno = cur_nblocks - 1;
 	while (true)
 	{
-		fsm_local_map.map[blkno] = FSM_LOCAL_AVAIL;
+		rel->fsm_local_map->map[blkno] = FSM_LOCAL_AVAIL;
 		if (blkno >= 2)
 			blkno -= 2;
 		else
@@ -1150,13 +1125,13 @@ fsm_local_set(Relation rel, BlockNumber cur_nblocks)
 	}
 
 	/* Cache the number of blocks. */
-	fsm_local_map.nblocks = cur_nblocks;
+	rel->fsm_local_map->nblocks = cur_nblocks;
 
 	/* Set the status of the cached target block to 'unavailable'. */
 	cached_target_block = RelationGetTargetBlock(rel);
 	if (cached_target_block != InvalidBlockNumber &&
 		cached_target_block < cur_nblocks)
-		fsm_local_map.map[cached_target_block] = FSM_LOCAL_NOT_AVAIL;
+		rel->fsm_local_map->map[cached_target_block] = FSM_LOCAL_NOT_AVAIL;
 }
 
 /*
@@ -1168,18 +1143,18 @@ fsm_local_set(Relation rel, BlockNumber cur_nblocks)
  * This function is used when there is no FSM.
  */
 static BlockNumber
-fsm_local_search(void)
+fsm_local_search(Relation rel)
 {
 	BlockNumber target_block;
 
 	/* Local map must be set by now. */
-	Assert(FSM_LOCAL_MAP_EXISTS);
+	Assert(FSM_LOCAL_MAP_EXISTS(rel));
 
-	target_block = fsm_local_map.nblocks;
+	target_block = rel->fsm_local_map->nblocks;
 	do
 	{
 		target_block--;
-		if (fsm_local_map.map[target_block] == FSM_LOCAL_AVAIL)
+		if (rel->fsm_local_map->map[target_block] == FSM_LOCAL_AVAIL)
 			return target_block;
 	} while (target_block > 0);
 
@@ -1189,7 +1164,22 @@ fsm_local_search(void)
 	 * first, which would otherwise lead to the same conclusion again and
 	 * again.
 	 */
-	FSMClearLocalMap();
+	fsm_clear_local_map(rel);
 
 	return InvalidBlockNumber;
 }
+
+/*
+ * Clear the local map.  We must call this when we have found a block with
+ * enough free space, when we extend the relation, or on transaction abort.
+ */
+static void
+fsm_clear_local_map(Relation rel)
+{
+	if (FSM_LOCAL_MAP_EXISTS(rel))
+	{
+		rel->fsm_local_map->nblocks = 0;
+		memset(&rel->fsm_local_map->map, FSM_LOCAL_NOT_AVAIL,
+			sizeof(rel->fsm_local_map->map));
+	}
+}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index bab59f16e6..57fac56c92 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -75,6 +75,7 @@
 #include "partitioning/partdesc.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rowsecurity.h"
+#include "storage/freespace.h"
 #include "storage/lmgr.h"
 #include "storage/smgr.h"
 #include "utils/array.h"
@@ -1226,6 +1227,9 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	 */
 	RelationInitPhysicalAddr(relation);
 
+	/* Initialize FSM map for the relation. */
+	RelationInitFSMMap(relation);
+
 	/* make sure relation is marked as having no open file yet */
 	relation->rd_smgr = NULL;
 
@@ -1936,6 +1940,9 @@ formrdesc(const char *relationName, Oid relationReltype,
 	 */
 	RelationInitPhysicalAddr(relation);
 
+	/* Initialize FSM map for the relation. */
+	RelationInitFSMMap(relation);
+
 	/*
 	 * initialize the table am handler
 	 */
@@ -2612,6 +2619,7 @@ RelationClearRelation(Relation relation, bool rebuild)
 		SWAPFIELD(Oid, rd_toastoid);
 		/* pgstat_info must be preserved */
 		SWAPFIELD(struct PgStat_TableStatus *, pgstat_info);
+		SWAPFIELD(struct FSMLocalMap *, fsm_local_map);
 		/* preserve old partitioning info if no logical change */
 		if (keep_partkey)
 		{
@@ -3376,6 +3384,9 @@ RelationBuildLocalRelation(const char *relname,
 
 	RelationInitPhysicalAddr(rel);
 
+	/* Initialize FSM map for the relation. */
+	RelationInitFSMMap(rel);
+
 	rel->rd_rel->relam = accessmtd;
 
 	if (relkind == RELKIND_RELATION ||
@@ -5665,6 +5676,9 @@ load_relcache_init_file(bool shared)
 		 */
 		RelationInitLockInfo(rel);
 		RelationInitPhysicalAddr(rel);
+
+		/* Initialize FSM map for the relation. */
+		RelationInitFSMMap(rel);
 	}
 
 	/*
diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h
index dbaae651c5..2cabb725e2 100644
--- a/src/include/storage/freespace.h
+++ b/src/include/storage/freespace.h
@@ -21,6 +21,31 @@
 /* Only create the FSM if the heap has greater than this many blocks */
 #define HEAP_FSM_CREATION_THRESHOLD 4
 
+/*
+ * For small relations, we don't create FSM to save space, instead we use
+ * local in-memory map of pages to try.  To locate free space, we simply try
+ * pages directly without knowing ahead of time how much free space they have.
+ *
+ * Note that this map is used to the find the block with required free space
+ * for any given relation.  We clear this map when we have found a block with
+ * enough free space, when we extend the relation, or on transaction abort.
+ * See src/backend/storage/freespace/README for further details.
+ */
+typedef struct FSMLocalMap
+{
+	BlockNumber nblocks;
+	uint8		map[HEAP_FSM_CREATION_THRESHOLD];
+}			FSMLocalMap;
+
+/* Status codes for the local map. */
+
+/* Either already tried, or beyond the end of the relation */
+#define FSM_LOCAL_NOT_AVAIL 0x00
+
+/* Available to try */
+#define FSM_LOCAL_AVAIL		0x01
+
+
 /* prototypes for public functions in freespace.c */
 extern Size GetRecordedFreeSpace(Relation rel, BlockNumber heapBlk);
 extern BlockNumber GetPageWithFreeSpace(Relation rel, Size spaceNeeded,
@@ -31,7 +56,7 @@ extern BlockNumber RecordAndGetPageWithFreeSpace(Relation rel,
 							  Size spaceNeeded);
 extern void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk,
 						Size spaceAvail, BlockNumber nblocks);
-extern void FSMClearLocalMap(void);
+extern void RelationInitFSMMap(Relation rel);
 extern void XLogRecordPageWithFreeSpace(RelFileNode rnode, BlockNumber heapBlk,
 							Size spaceAvail);
 
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index bddfcafe26..5e12c40890 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -200,6 +200,7 @@ typedef struct RelationData
 
 	/* use "struct" here to avoid needing to include pgstat.h: */
 	struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
+	struct FSMLocalMap *fsm_local_map;
 } RelationData;
 
 
