diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index baa69fc..79eaf79 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -1394,6 +1394,9 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir)
 			blkno = _bt_parallel_seize(scan, &status);
 			if (status == false)
 			{
+				/* release the previous buffer, if pinned */
+				BTScanPosUnpinIfPinned(so->currPos);
+
 				BTScanPosInvalidate(so->currPos);
 				return false;
 			}
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index c55b7c4..08329b0 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -198,6 +198,11 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
 				ExecIndexScanEstimate((IndexScanState *) planstate,
 									  e->pcxt);
 				break;
+			case T_IndexOnlyScanState:
+				ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate,
+									  e->pcxt);
+				break;
+
 			case T_ForeignScanState:
 				ExecForeignScanEstimate((ForeignScanState *) planstate,
 										e->pcxt);
@@ -254,6 +259,11 @@ ExecParallelInitializeDSM(PlanState *planstate,
 				ExecIndexScanInitializeDSM((IndexScanState *) planstate,
 										   d->pcxt);
 				break;
+			case T_IndexOnlyScanState:
+				ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate,
+										   d->pcxt);
+				break;
+
 			case T_ForeignScanState:
 				ExecForeignScanInitializeDSM((ForeignScanState *) planstate,
 											 d->pcxt);
@@ -701,6 +711,10 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_toc *toc)
 			case T_IndexScanState:
 				ExecIndexScanInitializeWorker((IndexScanState *) planstate, toc);
 				break;
+			case T_IndexOnlyScanState:
+				ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate, toc);
+				break;
+
 			case T_ForeignScanState:
 				ExecForeignScanInitializeWorker((ForeignScanState *) planstate,
 												toc);
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 45566bd..78304d1 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -21,6 +21,9 @@
  *		ExecEndIndexOnlyScan		releases all storage.
  *		ExecIndexOnlyMarkPos		marks scan position.
  *		ExecIndexOnlyRestrPos		restores scan position.
+ *		ExecIndexOnlyScanEstimate		estimates DSM space needed for parallel index-only scan
+ *		ExecIndexOnlyScanInitializeDSM 		initialize DSM for parallel index-only scan
+ *		ExecIndexOnlyScanInitializeWorker 	attach to DSM info in parallel worker
  */
 #include "postgres.h"
 
@@ -277,6 +280,16 @@ ExecIndexOnlyScan(IndexOnlyScanState *node)
 void
 ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
 {
+	bool		reset_parallel_scan = true;
+
+	/*
+	 * if we are here to just update the scan keys, then don't reset parallel
+	 * scan
+	 */
+	if (node->ioss_NumRuntimeKeys != 0 && !node->ioss_RuntimeKeysReady)
+		reset_parallel_scan = false;
+
+
 	/*
 	 * If we are doing runtime key calculations (ie, any of the index key
 	 * values weren't simple Consts), compute the new key values.  But first,
@@ -296,10 +309,16 @@ ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
 	node->ioss_RuntimeKeysReady = true;
 
 	/* reset index scan */
-	index_rescan(node->ioss_ScanDesc,
-				 node->ioss_ScanKeys, node->ioss_NumScanKeys,
-				 node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+	if (node->ioss_ScanDesc)
+	{
+
+		index_rescan(node->ioss_ScanDesc,
+					node->ioss_ScanKeys, node->ioss_NumScanKeys,
+					 node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+		if (reset_parallel_scan)
+			index_parallelrescan(node->ioss_ScanDesc);
 
+	}
 	ExecScanReScan(&node->ss);
 }
 
@@ -534,33 +553,99 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	{
 		indexstate->ioss_RuntimeContext = NULL;
 	}
-
-	/*
-	 * Initialize scan descriptor.
-	 */
-	indexstate->ioss_ScanDesc = index_beginscan(currentRelation,
+	if (!node->scan.plan.parallel_aware)
+	{
+		/*
+		 * Initialize scan descriptor.
+		 */
+		indexstate->ioss_ScanDesc = index_beginscan(currentRelation,
 												indexstate->ioss_RelationDesc,
 												estate->es_snapshot, NULL,
 												indexstate->ioss_NumScanKeys,
 									 indexstate->ioss_NumOrderByKeys, false);
 
-	/* Set it up for index-only scan */
-	indexstate->ioss_ScanDesc->xs_want_itup = true;
-	indexstate->ioss_VMBuffer = InvalidBuffer;
+		/* Set it up for index-only scan */
+		indexstate->ioss_ScanDesc->xs_want_itup = true;
+		indexstate->ioss_VMBuffer = InvalidBuffer;
 
-	/*
-	 * If no run-time keys to calculate, go ahead and pass the scankeys to the
-	 * index AM.
-	 */
-	if (indexstate->ioss_NumRuntimeKeys == 0)
-		index_rescan(indexstate->ioss_ScanDesc,
+		/*
+		 * If no run-time keys to calculate, go ahead and pass the scankeys to the
+		 * index AM.
+		 */
+		if (indexstate->ioss_NumRuntimeKeys == 0)
+			index_rescan(indexstate->ioss_ScanDesc,
 					 indexstate->ioss_ScanKeys,
 					 indexstate->ioss_NumScanKeys,
 					 indexstate->ioss_OrderByKeys,
 					 indexstate->ioss_NumOrderByKeys);
-
+	}
 	/*
 	 * all done.
 	 */
 	return indexstate;
 }
+void
+ExecIndexOnlyScanEstimate(IndexOnlyScanState *node,
+					  ParallelContext *pcxt)
+{
+	EState	   *estate = node->ss.ps.state;
+
+	node->ioss_PscanLen = index_parallelscan_estimate(node->ioss_RelationDesc,
+													 estate->es_snapshot);
+	shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen);
+	shm_toc_estimate_keys(&pcxt->estimator, 1);
+}
+
+void
+ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node,
+						   ParallelContext *pcxt)
+{
+	EState	   *estate = node->ss.ps.state;
+	ParallelIndexScanDesc piscan;
+
+	piscan = shm_toc_allocate(pcxt->toc, node->ioss_PscanLen);
+	index_parallelscan_initialize(node->ss.ss_currentRelation,
+								  node->ioss_RelationDesc,
+								  estate->es_snapshot,
+								  piscan);
+	shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
+	node->ioss_ScanDesc =
+		index_beginscan_parallel(node->ss.ss_currentRelation,
+								 node->ioss_RelationDesc,
+								 node->ioss_NumScanKeys,
+								 node->ioss_NumOrderByKeys,
+								 piscan);
+	node->ioss_ScanDesc->xs_want_itup = true;
+
+	/*
+	 * If no run-time keys to calculate, go ahead and pass the scankeys to the
+	 * index AM.
+	 */
+	if (node->ioss_NumRuntimeKeys == 0)
+		index_rescan(node->ioss_ScanDesc,
+					 node->ioss_ScanKeys, node->ioss_NumScanKeys,
+					 node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+}
+void
+ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, shm_toc *toc)
+{
+	ParallelIndexScanDesc piscan;
+
+	piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
+	node->ioss_ScanDesc =
+		index_beginscan_parallel(node->ss.ss_currentRelation,
+								 node->ioss_RelationDesc,
+								 node->ioss_NumScanKeys,
+								 node->ioss_NumOrderByKeys,
+								 piscan);
+	node->ioss_ScanDesc->xs_want_itup = true;
+
+	/*
+	 * If no run-time keys to calculate, go ahead and pass the scankeys to the
+	 * index AM.
+	 */
+	if (node->ioss_NumRuntimeKeys == 0)
+		index_rescan(node->ioss_ScanDesc,
+					 node->ioss_ScanKeys, node->ioss_NumScanKeys,
+					 node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
+}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 54a8a2f..5d963f5 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1098,8 +1098,8 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
 		 * If appropriate, consider parallel index scan.  We don't allow
 		 * parallel index scan for bitmap scans.
 		 */
-		if (index->amcanparallel &&
-			!index_only_scan &&
+		if ((index->amcanparallel ||
+			index_only_scan) &&
 			rel->consider_parallel &&
 			outer_relids == NULL &&
 			scantype != ST_BITMAPSCAN)
diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h
index d63d194..143d8cd 100644
--- a/src/include/executor/nodeIndexonlyscan.h
+++ b/src/include/executor/nodeIndexonlyscan.h
@@ -14,6 +14,7 @@
 #ifndef NODEINDEXONLYSCAN_H
 #define NODEINDEXONLYSCAN_H
 
+#include "access/parallel.h"
 #include "nodes/execnodes.h"
 
 extern IndexOnlyScanState *ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags);
@@ -23,4 +24,8 @@ extern void ExecIndexOnlyMarkPos(IndexOnlyScanState *node);
 extern void ExecIndexOnlyRestrPos(IndexOnlyScanState *node);
 extern void ExecReScanIndexOnlyScan(IndexOnlyScanState *node);
 
+extern void ExecIndexOnlyScanEstimate(IndexOnlyScanState *node, ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node, ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, shm_toc *toc);
+
 #endif   /* NODEINDEXONLYSCAN_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 17d712a..b8f22da 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1397,6 +1397,8 @@ typedef struct IndexOnlyScanState
 	IndexScanDesc ioss_ScanDesc;
 	Buffer		ioss_VMBuffer;
 	long		ioss_HeapFetches;
+	/* This is needed for parallel index scan */
+	Size	ioss_PscanLen;
 } IndexOnlyScanState;
 
 /* ----------------
