diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index beff1b9..9f2ec1f 100644
*** a/contrib/pgstattuple/pgstatindex.c
--- b/contrib/pgstattuple/pgstatindex.c
*************** pgstatindex(PG_FUNCTION_ARGS)
*** 95,100 ****
--- 95,101 ----
  	BlockNumber nblocks;
  	BlockNumber blkno;
  	BTIndexStat indexStat;
+  	BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
  
  	if (!superuser())
  		ereport(ERROR,
*************** pgstatindex(PG_FUNCTION_ARGS)
*** 122,128 ****
  	 * Read metapage
  	 */
  	{
! 		Buffer		buffer = ReadBuffer(rel, 0);
  		Page		page = BufferGetPage(buffer);
  		BTMetaPageData *metad = BTPageGetMeta(page);
  
--- 123,129 ----
  	 * Read metapage
  	 */
  	{
! 		Buffer		buffer = ReadBufferExtended(rel, MAIN_FORKNUM, 0, RBM_NORMAL, bstrategy);
  		Page		page = BufferGetPage(buffer);
  		BTMetaPageData *metad = BTPageGetMeta(page);
  
*************** pgstatindex(PG_FUNCTION_ARGS)
*** 159,165 ****
  		CHECK_FOR_INTERRUPTS();
  
  		/* Read and lock buffer */
! 		buffer = ReadBuffer(rel, blkno);
  		LockBuffer(buffer, BUFFER_LOCK_SHARE);
  
  		page = BufferGetPage(buffer);
--- 160,166 ----
  		CHECK_FOR_INTERRUPTS();
  
  		/* Read and lock buffer */
!  		buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
  		LockBuffer(buffer, BUFFER_LOCK_SHARE);
  
  		page = BufferGetPage(buffer);
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index e5ddd87..6bbc957 100644
*** a/contrib/pgstattuple/pgstattuple.c
--- b/contrib/pgstattuple/pgstattuple.c
***************
*** 24,33 ****
--- 24,35 ----
  
  #include "postgres.h"
  
+ #include "access/gin_private.h"
  #include "access/gist_private.h"
  #include "access/hash.h"
  #include "access/nbtree.h"
  #include "access/relscan.h"
+ #include "access/spgist_private.h"
  #include "catalog/namespace.h"
  #include "funcapi.h"
  #include "miscadmin.h"
*************** static void pgstat_hash_page(pgstattuple
*** 73,83 ****
--- 75,96 ----
  				 Relation rel, BlockNumber blkno);
  static void pgstat_gist_page(pgstattuple_type *stat,
  				 Relation rel, BlockNumber blkno);
+ static void pgstat_gin_page(pgstattuple_type *stat,
+ 				 Relation rel, BlockNumber blkno);
+ static void pgstat_spgist_page(pgstattuple_type *stat,
+ 				 Relation rel, BlockNumber blkno);
  static Datum pgstat_index(Relation rel, BlockNumber start,
  			 pgstat_page pagefn, FunctionCallInfo fcinfo);
  static void pgstat_index_page(pgstattuple_type *stat, Page page,
  				  OffsetNumber minoff, OffsetNumber maxoff);
  
+ /* 
+  * Buffer access strategy for reading relations, it's simpler to keep it
+  * global because pgstat_*_page() functions read one buffer at a time.
+  * pgstat_heap() and pgstat_index() should initialize it before use.
+  */
+ BufferAccessStrategy bstrategy;
+ 
  /*
   * build_pgstattuple_type -- build a pgstattuple_type tuple
   */
*************** pgstat_relation(Relation rel, FunctionCa
*** 229,235 ****
  					return pgstat_index(rel, GIST_ROOT_BLKNO + 1,
  										pgstat_gist_page, fcinfo);
  				case GIN_AM_OID:
! 					err = "gin index";
  					break;
  				default:
  					err = "unknown index";
--- 242,253 ----
  					return pgstat_index(rel, GIST_ROOT_BLKNO + 1,
  										pgstat_gist_page, fcinfo);
  				case GIN_AM_OID:
! 					return pgstat_index(rel, GIN_METAPAGE_BLKNO + 1,
! 										pgstat_gin_page, fcinfo);
! 					break;
! 				case SPGIST_AM_OID:
! 					return pgstat_index(rel, SPGIST_METAPAGE_BLKNO + 1,
! 										pgstat_spgist_page, fcinfo);
  					break;
  				default:
  					err = "unknown index";
*************** pgstat_heap(Relation rel, FunctionCallIn
*** 276,281 ****
--- 294,302 ----
  
  	nblocks = scan->rs_nblocks; /* # blocks to be scanned */
  
+ 	/* prepare access strategy for this table */
+ 	bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 
  	/* scan the relation */
  	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
  	{
*************** pgstat_heap(Relation rel, FunctionCallIn
*** 309,315 ****
  		{
  			CHECK_FOR_INTERRUPTS();
  
! 			buffer = ReadBuffer(rel, block);
  			LockBuffer(buffer, BUFFER_LOCK_SHARE);
  			stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer));
  			UnlockReleaseBuffer(buffer);
--- 330,336 ----
  		{
  			CHECK_FOR_INTERRUPTS();
  
! 			buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block, RBM_NORMAL, bstrategy);
  			LockBuffer(buffer, BUFFER_LOCK_SHARE);
  			stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer));
  			UnlockReleaseBuffer(buffer);
*************** pgstat_heap(Relation rel, FunctionCallIn
*** 322,328 ****
  	{
  		CHECK_FOR_INTERRUPTS();
  
! 		buffer = ReadBuffer(rel, block);
  		LockBuffer(buffer, BUFFER_LOCK_SHARE);
  		stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer));
  		UnlockReleaseBuffer(buffer);
--- 343,349 ----
  	{
  		CHECK_FOR_INTERRUPTS();
  
! 		buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block, RBM_NORMAL, bstrategy);
  		LockBuffer(buffer, BUFFER_LOCK_SHARE);
  		stat.free_space += PageGetHeapFreeSpace((Page) BufferGetPage(buffer));
  		UnlockReleaseBuffer(buffer);
*************** pgstat_btree_page(pgstattuple_type *stat
*** 345,351 ****
  	Buffer		buf;
  	Page		page;
  
! 	buf = ReadBuffer(rel, blkno);
  	LockBuffer(buf, BT_READ);
  	page = BufferGetPage(buf);
  
--- 366,372 ----
  	Buffer		buf;
  	Page		page;
  
! 	buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
  	LockBuffer(buf, BT_READ);
  	page = BufferGetPage(buf);
  
*************** pgstat_hash_page(pgstattuple_type *stat,
*** 389,395 ****
  	Page		page;
  
  	_hash_getlock(rel, blkno, HASH_SHARE);
! 	buf = _hash_getbuf(rel, blkno, HASH_READ, 0);
  	page = BufferGetPage(buf);
  
  	if (PageGetSpecialSize(page) == MAXALIGN(sizeof(HashPageOpaqueData)))
--- 410,416 ----
  	Page		page;
  
  	_hash_getlock(rel, blkno, HASH_SHARE);
! 	buf = _hash_getbuf_with_strategy(rel, blkno, HASH_READ, 0, bstrategy);
  	page = BufferGetPage(buf);
  
  	if (PageGetSpecialSize(page) == MAXALIGN(sizeof(HashPageOpaqueData)))
*************** pgstat_gist_page(pgstattuple_type *stat,
*** 431,437 ****
  	Buffer		buf;
  	Page		page;
  
! 	buf = ReadBuffer(rel, blkno);
  	LockBuffer(buf, GIST_SHARE);
  	gistcheckpage(rel, buf);
  	page = BufferGetPage(buf);
--- 452,458 ----
  	Buffer		buf;
  	Page		page;
  
! 	buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
  	LockBuffer(buf, GIST_SHARE);
  	gistcheckpage(rel, buf);
  	page = BufferGetPage(buf);
*************** pgstat_gist_page(pgstattuple_type *stat,
*** 450,455 ****
--- 471,538 ----
  }
  
  /*
+  * pgstat_gin_page -- check tuples in a gin page
+  */
+ static void
+ pgstat_gin_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno)
+ {
+ 	Buffer		buf;
+ 	Page		page;
+ 
+ 	buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 	LockBuffer(buf, GIN_SHARE);
+ 	page = BufferGetPage(buf);
+ 
+ 	if (GinPageIsDeleted(page))
+ 	{
+ 		/* recyclable page */
+ 		stat->free_space += BLCKSZ; 
+ 	}
+ 	else if (GinPageIsLeaf(page) || GinPageIsData(page))
+ 	{
+ 		pgstat_index_page(stat, page, FirstOffsetNumber,
+ 						  PageGetMaxOffsetNumber(page));
+ 	}
+ 	else
+ 	{
+ 		/* root or node */
+ 	}
+ 
+ 	UnlockReleaseBuffer(buf);
+ }
+ 
+ /*
+  * pgstat_spgist_page -- check tuples in a spgist page
+  */
+ static void
+ pgstat_spgist_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno)
+ {
+ 	Buffer		buf;
+ 	Page		page;
+ 
+ 	buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 	LockBuffer(buf, BUFFER_LOCK_SHARE);
+ 	page = BufferGetPage(buf);
+ 
+ 	if (SpGistPageIsDeleted(page))
+ 	{
+ 		/* recyclable page */
+ 	    stat->free_space += BLCKSZ;
+ 	}
+ 	else if (SpGistPageIsLeaf(page))
+ 	{
+ 		pgstat_index_page(stat, page, FirstOffsetNumber,
+ 						  PageGetMaxOffsetNumber(page));
+ 	}
+ 	else
+ 	{
+ 		/* root or node */
+ 	}
+ 
+ 	UnlockReleaseBuffer(buf);
+ }
+ 
+ /*
   * pgstat_index -- returns live/dead tuples info in a generic index
   */
  static Datum
*************** pgstat_index(Relation rel, BlockNumber s
*** 460,465 ****
--- 543,551 ----
  	BlockNumber blkno;
  	pgstattuple_type stat = {0};
  
+ 	/* prepare access strategy for this index */
+ 	bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 
  	blkno = start;
  	for (;;)
  	{
