diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
new file mode 100644
index c5732c3..dae860f
*** a/src/backend/access/gin/ginfast.c
--- b/src/backend/access/gin/ginfast.c
*************** processPendingPage(BuildAccumulator *acc
*** 713,718 ****
--- 713,719 ----
   * Move tuples from pending pages into regular GIN structure.
   *
   * This can be called concurrently by multiple backends, so it must cope.
+  * XXX: not any more
   * On first glance it looks completely not concurrent-safe and not crash-safe
   * either.  The reason it's okay is that multiple insertion of the same entry
   * is detected and treated as a no-op by gininsert.c.  If we crash after
*************** ginInsertCleanup(GinState *ginstate,
*** 746,751 ****
--- 747,770 ----
  	BlockNumber blkno;
  
  	metabuffer = ReadBuffer(index, GIN_METAPAGE_BLKNO);
+ 
+ 	/*
+ 	 * A buffer cleanup lock on the metapage represents the exclusive right
+ 	 * to clean the pending list.  Unlike VACUUM's use of cleanup locks,
+ 	 * this right persists until the pin on the metabuffer is dropped. 
+ 	 */
+ 	if (vac_delay) 
+ 	{
+ 		LockBufferForCleanup(metabuffer);
+ 	}
+ 	else if (!ConditionalLockBufferForCleanup(metabuffer)) 
+ 	{
+ 		ReleaseBuffer(metabuffer);
+ 		return;
+ 	}
+ 
+ 	/* Exchange the exclusive content lock for a shared one */
+ 	LockBuffer(metabuffer, GIN_UNLOCK);
  	LockBuffer(metabuffer, GIN_SHARE);
  	metapage = BufferGetPage(metabuffer);
  	metadata = GinPageGetMeta(metapage);
