diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c
index 9def3df7483b4d20018e820231eb752ebf9c43ba..7a7d204bf5ff6b39563eb17506324ed99c42bc6d 100644
--- a/src/backend/storage/freespace/freespace.c
+++ b/src/backend/storage/freespace/freespace.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.34 2004/08/29 05:06:47 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.35 2004/09/28 20:46:27 tgl Exp $
  *
  *
  * NOTES:
@@ -283,8 +283,8 @@ InitFreeSpaceMap(void)
 	info.hash = tag_hash;
 
 	FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash",
-										MaxFSMRelations / 10,
-										MaxFSMRelations,
+										MaxFSMRelations + 1,
+										MaxFSMRelations + 1,
 										&info,
 										(HASH_ELEM | HASH_FUNCTION));
 
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index d9cd8850395e95f56e69167040e6944a4d9604e4..29ef5413c89fa608f118e6743b010f095d6a048b 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.80 2004/08/29 05:06:48 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.81 2004/09/28 20:46:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -262,8 +262,17 @@ InitShmemIndex(void)
  *		shared memory hash table.
  *
  * We assume caller is doing some kind of synchronization
- * so that two people dont try to create/initialize the
+ * so that two people don't try to create/initialize the
  * table at once.
+ *
+ * max_size is the estimated maximum number of hashtable entries.  This is
+ * not a hard limit, but the access efficiency will degrade if it is
+ * exceeded substantially (since it's used to compute directory size and
+ * the hash table buckets will get overfull).
+ *
+ * init_size is the number of hashtable entries to preallocate.  For a table
+ * whose maximum size is certain, this should be equal to max_size; that
+ * ensures that no run-time out-of-shared-memory failures can occur.
  */
 HTAB *
 ShmemInitHash(const char *name, /* table string name for shmem index */
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index f90a3fd0e841198ca8a36640b4d954cb8033cb9c..9699469e6d3e56c9fbf2dc4bf2823a1656f28a74 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.140 2004/09/12 18:30:50 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.141 2004/09/28 20:46:32 tgl Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -241,7 +241,7 @@ LockMethodTableInit(const char *tabName,
 
 	/* Compute init/max size to request for lock hashtables */
 	max_table_size = NLOCKENTS(maxBackends);
-	init_table_size = max_table_size / 10;
+	init_table_size = max_table_size / 2;
 
 	/* Allocate a string for the shmem index table lookups. */
 	/* This is just temp space in this routine, so palloc is OK. */
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index c55bcf38aa549ebcfde025da42bda4c72ece523f..8078994ba55aafd55f9d0838d38602f0f0a7106e 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.53 2004/08/29 05:06:50 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/hash/dynahash.c,v 1.54 2004/09/28 20:46:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,7 @@
  */
 static void *DynaHashAlloc(Size size);
 static HASHSEGMENT seg_alloc(HTAB *hashp);
-static bool element_alloc(HTAB *hashp);
+static bool element_alloc(HTAB *hashp, int nelem);
 static bool dir_realloc(HTAB *hashp);
 static bool expand_table(HTAB *hashp);
 static bool hdefault(HTAB *hashp);
@@ -228,11 +228,26 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
 		CurrentDynaHashCxt = hashp->hcxt;
 	}
 
+	/* Build the hash directory structure */
 	if (!init_htab(hashp, nelem))
 	{
 		hash_destroy(hashp);
 		return NULL;
 	}
+
+	/*
+	 * For a shared hash table, preallocate the requested number of elements.
+	 * This reduces problems with run-time out-of-shared-memory conditions.
+	 */
+	if (flags & HASH_SHARED_MEM)
+	{
+		if (!element_alloc(hashp, (int) nelem))
+		{
+			hash_destroy(hashp);
+			return NULL;
+		}
+	}
+
 	return hashp;
 }
 
@@ -631,7 +646,7 @@ hash_search(HTAB *hashp,
 			if (currBucket == NULL)
 			{
 				/* no free elements.  allocate another chunk of buckets */
-				if (!element_alloc(hashp))
+				if (!element_alloc(hashp, HASHELEMENT_ALLOC_INCR))
 					return NULL;	/* out of memory */
 				currBucket = hctl->freeList;
 				Assert(currBucket != NULL);
@@ -898,7 +913,7 @@ seg_alloc(HTAB *hashp)
  * allocate some new elements and link them into the free list
  */
 static bool
-element_alloc(HTAB *hashp)
+element_alloc(HTAB *hashp, int nelem)
 {
 	HASHHDR    *hctl = hashp->hctl;
 	Size		elementSize;
@@ -910,13 +925,13 @@ element_alloc(HTAB *hashp)
 
 	CurrentDynaHashCxt = hashp->hcxt;
 	tmpElement = (HASHELEMENT *)
-		hashp->alloc(HASHELEMENT_ALLOC_INCR * elementSize);
+		hashp->alloc(nelem * elementSize);
 
 	if (!tmpElement)
 		return false;
 
 	/* link all the new entries into the freelist */
-	for (i = 0; i < HASHELEMENT_ALLOC_INCR; i++)
+	for (i = 0; i < nelem; i++)
 	{
 		tmpElement->link = hctl->freeList;
 		hctl->freeList = tmpElement;
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index b7a0d7b158c5243d638c36ba412032aa10a957eb..fe67be6ac28fe5c8cb8a21c15b79409c12b02b95 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.42 2004/08/29 04:13:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.43 2004/09/28 20:46:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,8 +73,8 @@ extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
 /* size constants for the shmem index table */
  /* max size of data structure string name */
 #define SHMEM_INDEX_KEYSIZE		 (48)
- /* maximum size of the shmem index table */
-#define SHMEM_INDEX_SIZE		 (100)
+ /* max size of the shmem index table (not a hard limit) */
+#define SHMEM_INDEX_SIZE		 (32)
 
 /* this is a hash bucket in the shmem index table */
 typedef struct
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index c19f662a6109e8b1b25ffec7acfa95d1644da6d1..43a86f7c169ca856086ab64d277972dfd7ee2e0e 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.32 2004/08/29 05:06:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/hsearch.h,v 1.33 2004/09/28 20:46:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -135,7 +135,7 @@ typedef struct HASHCTL
 #define HASH_FFACTOR	0x008	/* Set fill factor */
 #define HASH_FUNCTION	0x010	/* Set user defined hash function */
 #define HASH_ELEM		0x020	/* Set key/entry size */
-#define HASH_SHARED_MEM 0x040	/* Set shared mem const */
+#define HASH_SHARED_MEM 0x040	/* Hashtable is in shared memory */
 #define HASH_ATTACH		0x080	/* Do not initialize hctl */
 #define HASH_ALLOC		0x100	/* Set memory allocator */
 #define HASH_CONTEXT	0x200	/* Set explicit memory context */