diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 8872920..af11eb0 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -182,8 +182,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       automatically truncated after a crash or unclean shutdown.  The contents
       of an unlogged table are also not replicated to standby servers.
       Any indexes created on an unlogged table are automatically unlogged as
-      well; however, unlogged <link linkend="GiST">GiST indexes</link> are
-      currently not supported and cannot be created on an unlogged table.
+      well.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 95d33c8..58d033cc 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -71,9 +71,22 @@ createTempGistContext(void)
 Datum
 gistbuildempty(PG_FUNCTION_ARGS)
 {
-	ereport(ERROR,
-			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-			 errmsg("unlogged GiST indexes are not supported")));
+	Relation	index = (Relation) PG_GETARG_POINTER(0);
+	Buffer		buffer;
+
+	/* Initialize the root page */
+	buffer = ReadBufferExtended(index, INIT_FORKNUM, P_NEW, RBM_NORMAL, NULL);
+	LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+
+	/* Initialize and xlog buffer */
+	START_CRIT_SECTION();
+	GISTInitBuffer(buffer, F_LEAF);
+	MarkBufferDirty(buffer);
+	log_newpage_buffer(buffer);
+	END_CRIT_SECTION();
+
+	/* Unlock and release the buffer */
+	UnlockReleaseBuffer(buffer);
 
 	PG_RETURN_VOID();
 }
@@ -391,7 +404,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 								   dist, oldrlink, oldnsn, leftchildbuf,
 								   markfollowright);
 		else
-			recptr = GetXLogRecPtrForTemp();
+			recptr = GetXLogRecPtrForUnloggedRel(rel);
 
 		for (ptr = dist; ptr; ptr = ptr->next)
 		{
@@ -448,7 +461,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 		}
 		else
 		{
-			recptr = GetXLogRecPtrForTemp();
+			recptr = GetXLogRecPtrForUnloggedRel(rel);
 			PageSetLSN(page, recptr);
 		}
 
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index aec5b52..235365d 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -158,16 +158,6 @@ gistbuild(PG_FUNCTION_ARGS)
 		elog(ERROR, "index \"%s\" already contains data",
 			 RelationGetRelationName(index));
 
-	/*
-	 * We can't yet handle unlogged GiST indexes, because we depend on LSNs.
-	 * This is duplicative of an error in gistbuildempty, but we want to check
-	 * here so as to throw error before doing all the index-build work.
-	 */
-	if (heap->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("unlogged GiST indexes are not supported")));
-
 	/* no locking is needed */
 	buildstate.giststate = initGISTstate(index);
 
@@ -204,7 +194,7 @@ gistbuild(PG_FUNCTION_ARGS)
 		PageSetTLI(page, ThisTimeLineID);
 	}
 	else
-		PageSetLSN(page, GetXLogRecPtrForTemp());
+		PageSetLSN(page, GetXLogRecPtrForUnloggedRel(heap));
 
 	UnlockReleaseBuffer(buffer);
 
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 8b60774..1dce570 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -743,18 +743,3 @@ gistoptions(PG_FUNCTION_ARGS)
 	PG_RETURN_BYTEA_P(rdopts);
 
 }
-
-/*
- * Temporary GiST indexes are not WAL-logged, but we need LSNs to detect
- * concurrent page splits anyway. GetXLogRecPtrForTemp() provides a fake
- * sequence of LSNs for that purpose. Each call generates an LSN that is
- * greater than any previous value returned by this function in the same
- * session.
- */
-XLogRecPtr
-GetXLogRecPtrForTemp(void)
-{
-	static XLogRecPtr counter = 1;
-	counter++;
-	return counter;
-}
diff --git a/src/backend/access/gist/gistvacuum.c b/src/backend/access/gist/gistvacuum.c
index dcad36e..7c19092 100644
--- a/src/backend/access/gist/gistvacuum.c
+++ b/src/backend/access/gist/gistvacuum.c
@@ -238,7 +238,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
 					PageSetTLI(page, ThisTimeLineID);
 				}
 				else
-					PageSetLSN(page, GetXLogRecPtrForTemp());
+					PageSetLSN(page, GetXLogRecPtrForUnloggedRel(rel));
 
 				END_CRIT_SECTION();
 			}
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 51a515a..e0a5d93 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -55,6 +55,7 @@
 #include "utils/builtins.h"
 #include "utils/guc.h"
 #include "utils/ps_status.h"
+#include "utils/rel.h"
 #include "utils/relmapper.h"
 #include "utils/snapmgr.h"
 #include "utils/timestamp.h"
@@ -385,6 +386,7 @@ typedef struct XLogCtlData
 	TransactionId ckptXid;
 	XLogRecPtr	asyncXactLSN;	/* LSN of newest async commit/abort */
 	XLogSegNo	lastRemovedSegNo; /* latest removed/recycled XLOG segment */
+	XLogRecPtr  unloggedLSN;	/* Fake LSN for unlogged GiST index */
 
 	/* Protected by WALWriteLock: */
 	XLogCtlWrite Write;
@@ -4208,6 +4210,44 @@ GetSystemIdentifier(void)
 }
 
 /*
+ * Temporary GiST indexes are not WAL-logged, but we need LSNs to detect
+ * concurrent page splits anyway. GetXLogRecPtrForUnloggedRel() provides a fake
+ * sequence of LSNs for that purpose. Each call generates an LSN that is
+ * greater than any previous value returned by this function in the same
+ * session using static counter
+ * Similarily unlogged GiST indexes are also not WAL-logged. But we need a
+ * persistent counter across clean shutdown. Use counter from ControlFile which
+ * is copied in XLogCtl.unloggedLSN to accomplish that
+ * If relation is UNLOGGED, return persistent counter from XLogCtl else return
+ * session wide temporary counter
+ */
+XLogRecPtr
+GetXLogRecPtrForUnloggedRel(Relation rel)
+{
+	XLogRecPtr nextUnloggedLSN;
+	static XLogRecPtr counter = 1;
+
+	/* Make sure relation is either UNLOGGED or TEMP */
+	Assert(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED ||
+		   rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP);
+
+	if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
+	{
+		/* use volatile pointer to prevent code rearrangement */
+		volatile XLogCtlData *xlogctl = XLogCtl;
+
+		SpinLockAcquire(&xlogctl->info_lck);
+		/* increment the unloggedLSN counter, need SpinLock */
+		nextUnloggedLSN = xlogctl->unloggedLSN++;
+		SpinLockRelease(&xlogctl->info_lck);
+	}
+	else
+		nextUnloggedLSN = counter++;	/* TEMP relation, use static counter */
+
+	return nextUnloggedLSN;
+}
+
+/*
  * Auto-tune the number of XLOG buffers.
  *
  * The preferred setting for wal_buffers is about 3% of shared_buffers, with
@@ -4496,6 +4536,7 @@ BootStrapXLOG(void)
 	ControlFile->time = checkPoint.time;
 	ControlFile->checkPoint = checkPoint.redo;
 	ControlFile->checkPointCopy = checkPoint;
+	ControlFile->unloggedLSN = 1;
 
 	/* Set important parameter values for use when replaying WAL */
 	ControlFile->MaxConnections = MaxConnections;
@@ -5505,6 +5546,9 @@ StartupXLOG(void)
 	XLogCtl->ckptXidEpoch = checkPoint.nextXidEpoch;
 	XLogCtl->ckptXid = checkPoint.nextXid;
 
+	/* initaiize unlogged LSN from Control File */
+	XLogCtl->unloggedLSN = ControlFile->unloggedLSN;
+
 	/*
 	 * We must replay WAL entries using the same TimeLineID they were created
 	 * under, so temporarily adopt the TLI indicated by the checkpoint (see
@@ -7034,6 +7078,8 @@ CreateCheckPoint(int flags)
 		LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
 		ControlFile->state = DB_SHUTDOWNING;
 		ControlFile->time = (pg_time_t) time(NULL);
+		/* Store unloggedLSN value as we want it persistent across shutdown */
+		ControlFile->unloggedLSN = XLogCtl->unloggedLSN;
 		UpdateControlFile();
 		LWLockRelease(ControlFileLock);
 	}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 03ed41d..fe740c3 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1921,8 +1921,11 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln)
 	 * rule that log updates must hit disk before any of the data-file changes
 	 * they describe do.
 	 */
-	recptr = BufferGetLSN(buf);
-	XLogFlush(recptr);
+	if (buf->flags & BM_PERMANENT)
+	{
+		recptr = BufferGetLSN(buf);
+		XLogFlush(recptr);
+	}
 
 	/*
 	 * Now it's safe to write buffer to disk. Note that no one else should
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 357b8c9..8d4fa9d 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -16,6 +16,7 @@
 
 #include "access/gist.h"
 #include "access/itup.h"
+#include "access/xlog.h"
 #include "fmgr.h"
 #include "storage/bufmgr.h"
 #include "storage/buffile.h"
@@ -511,8 +512,6 @@ extern void gistMakeUnionKey(GISTSTATE *giststate, int attno,
 				 GISTENTRY *entry2, bool isnull2,
 				 Datum *dst, bool *dstisnull);
 
-extern XLogRecPtr GetXLogRecPtrForTemp(void);
-
 /* gistvacuum.c */
 extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
 extern Datum gistvacuumcleanup(PG_FUNCTION_ARGS);
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 885b5fc..856bf04 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -16,6 +16,7 @@
 #include "datatype/timestamp.h"
 #include "lib/stringinfo.h"
 #include "storage/buf.h"
+#include "utils/rel.h"
 #include "utils/pg_crc.h"
 
 /*
@@ -294,6 +295,7 @@ extern char *XLogFileNameP(TimeLineID tli, XLogSegNo segno);
 
 extern void UpdateControlFile(void);
 extern uint64 GetSystemIdentifier(void);
+extern XLogRecPtr GetXLogRecPtrForUnloggedRel(Relation rel);
 extern Size XLOGShmemSize(void);
 extern void XLOGShmemInit(void);
 extern void BootStrapXLOG(void);
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index ead3a6e..17522d0 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -157,6 +157,7 @@ typedef struct ControlFileData
 	XLogRecPtr	backupStartPoint;
 	XLogRecPtr	backupEndPoint;
 	bool		backupEndRequired;
+	XLogRecPtr  unloggedLSN;		/* fake LSN for unlogged GiST index */
 
 	/*
 	 * Parameter settings that determine if the WAL can be used for archival
