*** a/src/backend/access/gist/gist.c
--- b/src/backend/access/gist/gist.c
***************
*** 148,163 **** gistinsert(PG_FUNCTION_ARGS)
--- 148,169 ----
   * pages are released; note that new tuple(s) are *not* on the root page
   * but in one of the new child pages.
   *
+  * If 'newblkno' is not NULL, returns the block number of page the first
+  * new/updated tuple was inserted to. Usually it's the given page, but could
+  * be its right sibling if the page was split.
+  *
   * Returns 'true' if the page was split, 'false' otherwise.
   */
  bool
  gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
  				Buffer buffer,
  				IndexTuple *itup, int ntup, OffsetNumber oldoffnum,
+ 				BlockNumber *newblkno,
  				Buffer leftchildbuf,
  				List **splitinfo,
  				bool markfollowright)
  {
+ 	BlockNumber blkno = BufferGetBlockNumber(buffer);
  	Page		page = BufferGetPage(buffer);
  	bool		is_leaf = (GistPageIsLeaf(page)) ? true : false;
  	XLogRecPtr	recptr;
***************
*** 199,205 **** gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
  		BlockNumber oldrlink = InvalidBlockNumber;
  		GistNSN		oldnsn = 0;
  		SplitedPageLayout rootpg;
- 		BlockNumber blkno = BufferGetBlockNumber(buffer);
  		bool		is_rootsplit;
  
  		is_rootsplit = (blkno == GIST_ROOT_BLKNO);
--- 205,210 ----
***************
*** 319,327 **** gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
  
  			for (i = 0; i < ptr->block.num; i++)
  			{
! 				if (PageAddItem(ptr->page, (Item) data, IndexTupleSize((IndexTuple) data), i + FirstOffsetNumber, false, false) == InvalidOffsetNumber)
  					elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(rel));
! 				data += IndexTupleSize((IndexTuple) data);
  			}
  
  			/* Set up rightlinks */
--- 324,342 ----
  
  			for (i = 0; i < ptr->block.num; i++)
  			{
! 				IndexTuple	thistup = (IndexTuple) data;
! 
! 				if (PageAddItem(ptr->page, (Item) data, IndexTupleSize(thistup), i + FirstOffsetNumber, false, false) == InvalidOffsetNumber)
  					elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(rel));
! 
! 				/*
! 				 * If this is the first inserted/updated tuple, let the caller
! 				 * know which page it landed on.
! 				 */
! 				if (newblkno && ItemPointerEquals(&thistup->t_tid, &(*itup)->t_tid))
! 					*newblkno = ptr->block.blkno;
! 
! 				data += IndexTupleSize(thistup);
  			}
  
  			/* Set up rightlinks */
***************
*** 436,441 **** gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
--- 451,459 ----
  			recptr = GetXLogRecPtrForTemp();
  			PageSetLSN(page, recptr);
  		}
+ 
+ 		if (newblkno)
+ 			*newblkno = blkno;
  	}
  
  	/*
***************
*** 1074,1082 **** gistinserttuple(GISTInsertState *state, GISTInsertStack *stack,
   *	  is kept pinned.
   *	- Lock and pin on 'rightchild' are always released.
   *
!  * Returns 'true' if the page had to be split. Note that if the page had
!  * be split, the inserted/updated might've been inserted to a right sibling
!  * of stack->buffer instead of stack->buffer itself.
   */
  static bool
  gistinserttuples(GISTInsertState *state, GISTInsertStack *stack,
--- 1092,1100 ----
   *	  is kept pinned.
   *	- Lock and pin on 'rightchild' are always released.
   *
!  * Returns 'true' if the page had to be split. Note that if the page was
!  * split, the inserted/updated tuples might've been inserted to a right
!  * sibling of stack->buffer instead of stack->buffer itself.
   */
  static bool
  gistinserttuples(GISTInsertState *state, GISTInsertStack *stack,
***************
*** 1091,1097 **** gistinserttuples(GISTInsertState *state, GISTInsertStack *stack,
  	/* Insert the tuple(s) to the page, splitting the page if necessary */
  	is_split = gistplacetopage(state->r, state->freespace, giststate,
  							   stack->buffer,
! 							   tuples, ntup, oldoffnum,
  							   leftchild,
  							   &splitinfo,
  							   true);
--- 1109,1116 ----
  	/* Insert the tuple(s) to the page, splitting the page if necessary */
  	is_split = gistplacetopage(state->r, state->freespace, giststate,
  							   stack->buffer,
! 							   tuples, ntup,
! 							   oldoffnum, NULL,
  							   leftchild,
  							   &splitinfo,
  							   true);
*** a/src/backend/access/gist/gistbuild.c
--- b/src/backend/access/gist/gistbuild.c
***************
*** 85,91 **** static void gistBufferingBuildInsert(GISTBuildState *buildstate,
  						 IndexTuple itup);
  static bool gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
  				BlockNumber startblkno, int startlevel);
! static void gistbufferinginserttuples(GISTBuildState *buildstate,
  						  Buffer buffer, int level,
  						  IndexTuple *itup, int ntup, OffsetNumber oldoffnum,
  						  BlockNumber parentblk, OffsetNumber downlinkoffnum);
--- 85,91 ----
  						 IndexTuple itup);
  static bool gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
  				BlockNumber startblkno, int startlevel);
! static BlockNumber gistbufferinginserttuples(GISTBuildState *buildstate,
  						  Buffer buffer, int level,
  						  IndexTuple *itup, int ntup, OffsetNumber oldoffnum,
  						  BlockNumber parentblk, OffsetNumber downlinkoffnum);
***************
*** 621,629 **** gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
  		newtup = gistgetadjusted(indexrel, idxtuple, itup, giststate);
  		if (newtup)
  		{
! 			gistbufferinginserttuples(buildstate, buffer, level,
! 									  &newtup, 1, childoffnum,
! 									InvalidBlockNumber, InvalidOffsetNumber);
  			/* gistbufferinginserttuples() released the buffer */
  		}
  		else
--- 621,629 ----
  		newtup = gistgetadjusted(indexrel, idxtuple, itup, giststate);
  		if (newtup)
  		{
! 			blkno  = gistbufferinginserttuples(buildstate, buffer, level,
! 											   &newtup, 1, childoffnum,
! 									  InvalidBlockNumber, InvalidOffsetNumber);
  			/* gistbufferinginserttuples() released the buffer */
  		}
  		else
***************
*** 676,685 **** gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
   *
   * This is analogous with gistinserttuples() in the regular insertion code.
   *
   * Caller should hold a lock on 'buffer' on entry. This function will unlock
   * and unpin it.
   */
! static void
  gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
  						  IndexTuple *itup, int ntup, OffsetNumber oldoffnum,
  						  BlockNumber parentblk, OffsetNumber downlinkoffnum)
--- 676,689 ----
   *
   * This is analogous with gistinserttuples() in the regular insertion code.
   *
+  * Returns the block number of the page where the (first) new or updated tuple
+  * was inserted. Usually that's the original page, but might be a sibling page
+  * if the original page was split.
+  *
   * Caller should hold a lock on 'buffer' on entry. This function will unlock
   * and unpin it.
   */
! static BlockNumber
  gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
  						  IndexTuple *itup, int ntup, OffsetNumber oldoffnum,
  						  BlockNumber parentblk, OffsetNumber downlinkoffnum)
***************
*** 687,698 **** gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
  	GISTBuildBuffers *gfbb = buildstate->gfbb;
  	List	   *splitinfo;
  	bool		is_split;
  
  	is_split = gistplacetopage(buildstate->indexrel,
  							   buildstate->freespace,
  							   buildstate->giststate,
  							   buffer,
! 							   itup, ntup, oldoffnum,
  							   InvalidBuffer,
  							   &splitinfo,
  							   false);
--- 691,703 ----
  	GISTBuildBuffers *gfbb = buildstate->gfbb;
  	List	   *splitinfo;
  	bool		is_split;
+ 	BlockNumber	placed_to_blk = InvalidBlockNumber;
  
  	is_split = gistplacetopage(buildstate->indexrel,
  							   buildstate->freespace,
  							   buildstate->giststate,
  							   buffer,
! 							   itup, ntup, oldoffnum, &placed_to_blk,
  							   InvalidBuffer,
  							   &splitinfo,
  							   false);
***************
*** 823,828 **** gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer, int level,
--- 828,835 ----
  	}
  	else
  		UnlockReleaseBuffer(buffer);
+ 
+ 	return placed_to_blk;
  }
  
  /*
*** a/src/include/access/gist_private.h
--- b/src/include/access/gist_private.h
***************
*** 430,436 **** typedef struct
  
  extern bool gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
  				Buffer buffer,
! 				IndexTuple *itup, int ntup, OffsetNumber oldoffnum,
  				Buffer leftchildbuf,
  				List **splitinfo,
  				bool markleftchild);
--- 430,437 ----
  
  extern bool gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
  				Buffer buffer,
! 				IndexTuple *itup, int ntup,
! 				OffsetNumber oldoffnum, BlockNumber *newblkno,
  				Buffer leftchildbuf,
  				List **splitinfo,
  				bool markleftchild);
