diff --git a/contrib/pageinspect/Makefile b/contrib/pageinspect/Makefile
new file mode 100644
index 63fab95..f63b92f
*** a/contrib/pageinspect/Makefile
--- b/contrib/pageinspect/Makefile
***************
*** 1,7 ****
  # contrib/pageinspect/Makefile
  
  MODULE_big	= pageinspect
! OBJS		= rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o
  
  EXTENSION = pageinspect
  DATA = pageinspect--1.0.sql pageinspect--1.1.sql \
--- 1,7 ----
  # contrib/pageinspect/Makefile
  
  MODULE_big	= pageinspect
! OBJS		= rawpage.o heapfuncs.o btreefuncs.o idxfuncs.o fsmfuncs.o
  
  EXTENSION = pageinspect
  DATA = pageinspect--1.0.sql pageinspect--1.1.sql \
diff --git a/contrib/pageinspect/btreefuncs.c b/contrib/pageinspect/btreefuncs.c
new file mode 100644
index 9c0b0fb..b399b85
*** a/contrib/pageinspect/btreefuncs.c
--- b/contrib/pageinspect/btreefuncs.c
***************
*** 34,41 ****
  #include "utils/builtins.h"
  #include "utils/rel.h"
  
- #include "btreefuncs.h"
- 
  extern Datum bt_metap(PG_FUNCTION_ARGS);
  extern Datum bt_page_items(PG_FUNCTION_ARGS);
  extern Datum bt_page_stats(PG_FUNCTION_ARGS);
--- 34,39 ----
*************** GetBTPageStatistics(BlockNumber blkno, B
*** 156,216 ****
  		stat->avg_item_size = 0;
  }
  
- /*------------------------------------------------
-  * GetBTRelationFreeSpace
-  *
-  * Get the free space for a btree index.
-  * This is a helper function for relation_free_space()
-  *------------------------------------------------
-  */
- float4
- GetBTRelationFreeSpace(Relation rel)
- {
- 	BTPageStat stat;
- 
- 	Buffer		buffer;
- 	BlockNumber blkno;
- 	BlockNumber totalBlcksInRelation = RelationGetNumberOfBlocks(rel);
- 	BlockNumber totalBlcksCounted = 0;
- 	Size 		free_space = 0;
- 	double		free_percent = 0;
- 
-     BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
- 	
- 	/* Skip page 0 because it is a metapage */
- 	for (blkno = 1; blkno < totalBlcksInRelation; blkno++)
- 	{
- 		buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
- 		/* 
- 		 * get the statistics of the indexes and use that info
- 		 * to determine free space on the page
- 		 */
- 		GetBTPageStatistics(blkno, buffer, &stat);
- 		/* 
- 		 * Consider pages DELETED and HALF_DEAD as empty,
- 		 * besides those only consider LEAF pages
- 		 */
- 		if (stat.type == 'd' || stat.type == 'e')
- 		{
- 			free_space += stat.page_size;
- 			totalBlcksCounted++;
- 		}
- 		else if (stat.type == 'l')
- 		{
- 			free_space += stat.free_size;		
- 			totalBlcksCounted++;
- 		}
- 
- 		ReleaseBuffer(buffer);
- 	}
- 
- 	if (totalBlcksCounted > 0)
- 		free_percent = ((float4) free_space) / (totalBlcksCounted * BLCKSZ);
- 
- 	return free_percent;
- }
- 
- 
  /* -----------------------------------------------
   * bt_page()
   *
--- 154,159 ----
diff --git a/contrib/pageinspect/btreefuncs.h b/contrib/pageinspect/btreefuncs.h
new file mode .
index 549f878..e69de29
*** a/contrib/pageinspect/btreefuncs.h
--- b/contrib/pageinspect/btreefuncs.h
***************
*** 1,5 ****
- /*
-  * contrib/pageinspect/btreefuncs.h
-  */
- 
- float4 GetBTRelationFreeSpace(Relation);
--- 0 ----
diff --git a/contrib/pageinspect/idxfuncs.c b/contrib/pageinspect/idxfuncs.c
new file mode 100644
index ...6533429
*** a/contrib/pageinspect/idxfuncs.c
--- b/contrib/pageinspect/idxfuncs.c
***************
*** 0 ****
--- 1,313 ----
+ /*
+  * contrib/pageinspect/idxfuncs.c
+  *
+  *
+  * idxfuncs.c
+  *
+  * Permission to use, copy, modify, and distribute this software and
+  * its documentation for any purpose, without fee, and without a
+  * written agreement is hereby granted, provided that the above
+  * copyright notice and this paragraph and the following two
+  * paragraphs appear in all copies.
+  *
+  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+  * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+  * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
+  * OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  * A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
+  * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+  */
+ 
+ #include "postgres.h"
+ 
+ #include "access/gin_private.h"
+ #include "access/gist_private.h"
+ #include "access/hash.h"
+ #include "access/nbtree.h"
+ #include "access/spgist_private.h"
+ #include "funcapi.h"
+ #include "utils/rel.h"
+ 
+ #include "idxfuncs.h"
+ 
+ /*------------------------------------------------
+  * GetIndexRelationFreeSpace
+  *
+  * Look the type of the index and call the appropiate
+  * function to get the free space
+  *------------------------------------------------
+  */
+ float4
+ GetIndexRelationFreeSpace(Relation rel)
+ {
+ 	switch (rel->rd_rel->relam)
+ 	{
+ 		case BTREE_AM_OID:
+ 			return GetBTRelationFreeSpace(rel);
+ 		case HASH_AM_OID:
+ 			return GetHashRelationFreeSpace(rel);
+ 		case GIST_AM_OID:
+ 			return GetGistRelationFreeSpace(rel);
+ 		case GIN_AM_OID:
+ 			return GetGinRelationFreeSpace(rel);
+ 		case SPGIST_AM_OID:
+ 			return GetSpGistRelationFreeSpace(rel);
+ 		default:
+ 			elog(ERROR, "Unknown index type %d", rel->rd_rel->relam);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ /*------------------------------------------------
+  * GetBTRelationFreeSpace
+  *
+  * Get the free space for a btree index.
+  * This is a helper function for relation_free_space()
+  *------------------------------------------------
+  */
+ float4
+ GetBTRelationFreeSpace(Relation rel)
+ {
+ 	BlockNumber blkno;
+ 	BlockNumber totalBlcksInRelation = RelationGetNumberOfBlocks(rel);
+ 	BlockNumber totalBlcksCounted = 0;
+ 	Size 		free_space = 0;
+ 	double		free_percent = 0;
+ 
+     BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 	
+ 	/* Start just after the metapage */
+ 	for (blkno = BTREE_METAPAGE + 1; blkno < totalBlcksInRelation; blkno++)
+ 	{
+ 		Buffer buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 		Page page = BufferGetPage(buffer);
+ 		BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
+ 
+ 		/* 
+ 		 * Consider pages DELETED and HALF_DEAD as empty,
+ 		 * besides those only consider LEAF pages
+ 		 */
+ 		if (P_ISDELETED(opaque) || P_ISHALFDEAD(opaque))
+ 		{
+ 			free_space += PageGetPageSize(page);
+ 			totalBlcksCounted++;
+ 		}
+ 		else if (P_ISLEAF(opaque))
+ 		{
+ 			free_space += PageGetFreeSpace(page);	
+ 			totalBlcksCounted++;
+ 		}
+ 
+ 		ReleaseBuffer(buffer);
+ 	}
+ 
+ 	if (totalBlcksCounted > 0)
+ 		free_percent = ((float4) free_space) / (totalBlcksCounted * BLCKSZ);
+ 
+ 	return free_percent;
+ }
+ 
+ 
+ /*------------------------------------------------
+  * GetHashRelationFreeSpace
+  *
+  * Get the free space for a Hash index.
+  * This is a helper function for relation_free_space()
+  *------------------------------------------------
+  */
+ float4
+ GetHashRelationFreeSpace(Relation rel)
+ {
+ 	BlockNumber blkno;
+ 	BlockNumber totalBlcksInRelation = RelationGetNumberOfBlocks(rel);
+ 	BlockNumber totalBlcksCounted = 0;
+ 	Size 		free_space = 0;
+ 	double		free_percent = 0;
+ 
+     BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 	
+ 	/* Start just after the metapage */
+ 	for (blkno = HASH_METAPAGE + 1; blkno < totalBlcksInRelation; blkno++)
+ 	{
+ 		Buffer buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 		Page page = BufferGetPage(buffer);
+ 		HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page);
+ 
+ 		/* 
+ 		 * Consider pages LH_UNUSED_PAGE as empty,
+ 		 * besides that consider the free space in LH_OVERFLOW_PAGE and LH_BUCKET_PAGE pages
+ 		 */
+ 		if (opaque->hasho_flag == LH_UNUSED_PAGE)
+ 		{
+ 			free_space += PageGetPageSize(page);
+ 			totalBlcksCounted++;
+ 		}
+ 		else if (opaque->hasho_flag == LH_OVERFLOW_PAGE || opaque->hasho_flag == LH_BUCKET_PAGE)
+ 		{
+ 			free_space += PageGetFreeSpace(page);	
+ 			totalBlcksCounted++;
+ 		}
+ 
+ 		ReleaseBuffer(buffer);
+ 	}
+ 
+ 	if (totalBlcksCounted > 0)
+ 		free_percent = ((float4) free_space) / (totalBlcksCounted * BLCKSZ);
+ 
+ 	return free_percent;
+ }
+ 
+ /*------------------------------------------------
+  * GetGistRelationFreeSpace
+  *
+  * Get the free space for a Gist index.
+  * This is a helper function for relation_free_space()
+  *------------------------------------------------
+  */
+ float4
+ GetGistRelationFreeSpace(Relation rel)
+ {
+ 	BlockNumber blkno;
+ 	BlockNumber totalBlcksInRelation = RelationGetNumberOfBlocks(rel);
+ 	BlockNumber totalBlcksCounted = 0;
+ 	Size 		free_space = 0;
+ 	double		free_percent = 0;
+ 
+     BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 	
+ 	/* Start from the root */
+ 	for (blkno = GIST_ROOT_BLKNO; blkno < totalBlcksInRelation; blkno++)
+ 	{
+ 		Buffer buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 		Page page = BufferGetPage(buffer);
+ 
+ 		/* 
+ 		 * Consider pages LH_UNUSED_PAGE as empty,
+ 		 * besides that consider the free space in LH_OVERFLOW_PAGE and LH_BUCKET_PAGE pages
+ 		 */
+ 		if (GistPageIsDeleted(page))
+ 		{
+ 			free_space += PageGetPageSize(page);
+ 			totalBlcksCounted++;
+ 		}
+ 		else if (GistPageIsLeaf(page))
+ 		{
+ 			free_space += PageGetFreeSpace(page);	
+ 			totalBlcksCounted++;
+ 		}
+ 
+ 		ReleaseBuffer(buffer);
+ 	}
+ 
+ 	if (totalBlcksCounted > 0)
+ 		free_percent = ((float4) free_space) / (totalBlcksCounted * BLCKSZ);
+ 
+ 	return free_percent;
+ }
+ 
+ /*------------------------------------------------
+  * GetGinRelationFreeSpace
+  *
+  * Get the free space for a Gin index.
+  * This is a helper function for relation_free_space()
+  *------------------------------------------------
+  */
+ float4
+ GetGinRelationFreeSpace(Relation rel)
+ {
+ 	BlockNumber blkno;
+ 	BlockNumber totalBlcksInRelation = RelationGetNumberOfBlocks(rel);
+ 	BlockNumber totalBlcksCounted = 0;
+ 	Size 		free_space = 0;
+ 	double		free_percent = 0;
+ 
+     BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 	
+ 	/* Start just after the first root */
+ 	for (blkno = GIN_METAPAGE_BLKNO + 1; blkno < totalBlcksInRelation; blkno++)
+ 	{
+ 		Buffer buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 		Page page = BufferGetPage(buffer);
+ 
+ 		/* 
+ 		 * Consider pages GIN_DELETED as empty,
+ 		 * besides that consider the free space in GIN_DATA and GIN_LEAF pages
+ 		 */
+ 		if (GinPageIsDeleted(page))
+ 		{
+ 			free_space += PageGetPageSize(page);
+ 			totalBlcksCounted++;
+ 		}
+ 		else if (GinPageIsLeaf(page))
+ 		{
+ 			free_space += PageGetFreeSpace(page);	
+ 			totalBlcksCounted++;
+ 		}
+ 		else if (GinPageIsData(page))
+ 		{
+ 			free_space += GinDataPageGetFreeSpace(page);	
+ 			totalBlcksCounted++;
+ 		}
+ 
+ 		ReleaseBuffer(buffer);
+ 	}
+ 
+ 	if (totalBlcksCounted > 0)
+ 		free_percent = ((float4) free_space) / (totalBlcksCounted * BLCKSZ);
+ 
+ 	return free_percent;
+ }
+ 
+ /*------------------------------------------------
+  * GetSPGistRelationFreeSpace
+  *
+  * Get the free space for a SPGist index.
+  * This is a helper function for relation_free_space()
+  *------------------------------------------------
+  */
+ float4
+ GetSpGistRelationFreeSpace(Relation rel)
+ {
+ 	BlockNumber blkno;
+ 	BlockNumber totalBlcksInRelation = RelationGetNumberOfBlocks(rel);
+ 	BlockNumber totalBlcksCounted = 0;
+ 	Size 		free_space = 0;
+ 	double		free_percent = 0;
+ 
+     BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+ 	
+ 	/* Start just after the first root */
+ 	for (blkno = SPGIST_METAPAGE_BLKNO + 1; blkno < totalBlcksInRelation; blkno++)
+ 	{
+ 		Buffer buffer = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
+ 		Page page = BufferGetPage(buffer);
+ 
+ 		/* 
+ 		 * Consider pages GIN_DELETED as empty,
+ 		 * besides that consider the free space in GIN_DATA and GIN_LEAF pages
+ 		 */
+ 		if (SpGistPageIsDeleted(page))
+ 		{
+ 			free_space += PageGetPageSize(page);
+ 			totalBlcksCounted++;
+ 		}
+ 		else if (SpGistPageIsLeaf(page))
+ 		{
+ 			free_space += SpGistPageGetFreeSpace(page, 1);	
+ 			totalBlcksCounted++;
+ 		}
+ 
+ 		ReleaseBuffer(buffer);
+ 	}
+ 
+ 	if (totalBlcksCounted > 0)
+ 		free_percent = ((float4) free_space) / (totalBlcksCounted * BLCKSZ);
+ 
+ 	return free_percent;
+ }
diff --git a/contrib/pageinspect/idxfuncs.h b/contrib/pageinspect/idxfuncs.h
new file mode 100644
index ...788d920
*** a/contrib/pageinspect/idxfuncs.h
--- b/contrib/pageinspect/idxfuncs.h
***************
*** 0 ****
--- 1,10 ----
+ /*
+  * contrib/pageinspect/idxfuncs.h
+  */
+ 
+ float4 GetIndexRelationFreeSpace(Relation);
+ float4 GetBTRelationFreeSpace(Relation);
+ float4 GetHashRelationFreeSpace(Relation);
+ float4 GetGistRelationFreeSpace(Relation);
+ float4 GetGinRelationFreeSpace(Relation);
+ float4 GetSpGistRelationFreeSpace(Relation);
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
new file mode 100644
index 9a54744..99fccab
*** a/contrib/pageinspect/rawpage.c
--- b/contrib/pageinspect/rawpage.c
***************
*** 23,30 ****
  #include "utils/builtins.h"
  #include "utils/rel.h"
  
- #include "btreefuncs.h"
  #include "heapfuncs.h"
  
  PG_MODULE_MAGIC;
  
--- 23,30 ----
  #include "utils/builtins.h"
  #include "utils/rel.h"
  
  #include "heapfuncs.h"
+ #include "idxfuncs.h"
  
  PG_MODULE_MAGIC;
  
*************** relation_free_space(PG_FUNCTION_ARGS)
*** 276,282 ****
  			free_space = GetHeapRelationFreeSpace(rel);
  			break;
  		case RELKIND_INDEX: 
! 			free_space = GetBTRelationFreeSpace(rel);
  			break;
  	}
  	relation_close(rel, AccessShareLock);
--- 276,282 ----
  			free_space = GetHeapRelationFreeSpace(rel);
  			break;
  		case RELKIND_INDEX: 
! 			free_space = GetIndexRelationFreeSpace(rel);
  			break;
  	}
  	relation_close(rel, AccessShareLock);