diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b672cf2c7a9621fbab60fa58ae37870be2e06718..07a8392c4e443905cc6f36378bf9ae89d9236d05 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.13 2000/04/12 17:14:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.14 2000/06/02 03:58:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,8 +44,6 @@ bool		StopIfError = false;
 SPINLOCK	ControlFileLockId;
 SPINLOCK	XidGenLockId;
 
-extern bool ReleaseDataFile(void);
-
 extern VariableCache ShmemVariableCache;
 
 #define MinXLOGbuffers	4
@@ -738,22 +736,13 @@ XLogFileInit(uint32 log, uint32 seg)
 	XLogFileName(path, log, seg);
 	unlink(path);
 
-tryAgain:
 #ifndef __CYGWIN__
-	fd = open(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+	fd = BasicOpenFile(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
 #else
-	fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
+	fd = BasicOpenFile(path, O_RDWR | O_CREAT | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
 #endif
-	if (fd < 0 && (errno == EMFILE || errno == ENFILE))
-	{
-		fd = errno;
-		if (!ReleaseDataFile())
-			elog(STOP, "Create(logfile %u seg %u) failed: %d (and no one data file can be closed)",
-				 logId, logSeg, fd);
-		goto tryAgain;
-	}
 	if (fd < 0)
-		elog(STOP, "Init(logfile %u seg %u) failed: %d",
+		elog(STOP, "Open(logfile %u seg %u) failed: %d",
 			 logId, logSeg, errno);
 
 	if (lseek(fd, XLogSegSize - 1, SEEK_SET) != (off_t) (XLogSegSize - 1))
@@ -783,20 +772,11 @@ XLogFileOpen(uint32 log, uint32 seg, bool econt)
 
 	XLogFileName(path, log, seg);
 
-tryAgain:
 #ifndef __CYGWIN__
-	fd = open(path, O_RDWR);
+	fd = BasicOpenFile(path, O_RDWR, S_IRUSR | S_IWUSR);
 #else
-	fd = open(path, O_RDWR | O_BINARY);
+	fd = BasicOpenFile(path, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
 #endif
-	if (fd < 0 && (errno == EMFILE || errno == ENFILE))
-	{
-		fd = errno;
-		if (!ReleaseDataFile())
-			elog(STOP, "Open(logfile %u seg %u) failed: %d (and no one data file can be closed)",
-				 logId, logSeg, fd);
-		goto tryAgain;
-	}
 	if (fd < 0)
 	{
 		if (econt && errno == ENOENT)
@@ -1102,20 +1082,11 @@ UpdateControlFile()
 {
 	int			fd;
 
-tryAgain:
 #ifndef __CYGWIN__
-	fd = open(ControlFilePath, O_RDWR);
+	fd = BasicOpenFile(ControlFilePath, O_RDWR, S_IRUSR | S_IWUSR);
 #else
-	fd = open(ControlFilePath, O_RDWR | O_BINARY);
+	fd = BasicOpenFile(ControlFilePath, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
 #endif
-	if (fd < 0 && (errno == EMFILE || errno == ENFILE))
-	{
-		fd = errno;
-		if (!ReleaseDataFile())
-			elog(STOP, "Open(cntlfile) failed: %d (and no one data file can be closed)",
-				 fd);
-		goto tryAgain;
-	}
 	if (fd < 0)
 		elog(STOP, "Open(cntlfile) failed: %d", errno);
 
@@ -1174,9 +1145,9 @@ BootStrapXLOG()
 #endif
 
 #ifndef __CYGWIN__
-	fd = open(ControlFilePath, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+	fd = BasicOpenFile(ControlFilePath, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
 #else
-	fd = open(ControlFilePath, O_RDWR | O_CREAT | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
+	fd = BasicOpenFile(ControlFilePath, O_RDWR | O_CREAT | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
 #endif
 	if (fd < 0)
 		elog(STOP, "BootStrapXLOG failed to create control file (%s): %d",
@@ -1288,20 +1259,11 @@ StartupXLOG()
 	/*
 	 * Open/read Control file
 	 */
-tryAgain:
 #ifndef __CYGWIN__
-	fd = open(ControlFilePath, O_RDWR);
+	fd = BasicOpenFile(ControlFilePath, O_RDWR, S_IRUSR | S_IWUSR);
 #else
-	fd = open(ControlFilePath, O_RDWR | O_BINARY);
+	fd = BasicOpenFile(ControlFilePath, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
 #endif
-	if (fd < 0 && (errno == EMFILE || errno == ENFILE))
-	{
-		fd = errno;
-		if (!ReleaseDataFile())
-			elog(STOP, "Open(\"%s\") failed: %d (and no one data file can be closed)",
-				 ControlFilePath, fd);
-		goto tryAgain;
-	}
 	if (fd < 0)
 		elog(STOP, "Open(\"%s\") failed: %d", ControlFilePath, errno);
 
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 160fa5353bedc334726f919ad8735302ae8e3312..04303a54b088cc70c2edd56a2e47d4bdf8ae4910 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.56 2000/05/30 00:49:44 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.57 2000/06/02 03:58:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -146,13 +146,13 @@ write_password_file(Relation rel)
 	/*
 	 * Create a flag file the postmaster will detect the next time it
 	 * tries to authenticate a user.  The postmaster will know to reload
-	 * the pg_pwd file contents.  Note: we used to elog(ERROR) if the
-	 * creat() call failed, but it's a little silly to abort the transaction
+	 * the pg_pwd file contents.  Note: we used to elog(ERROR) if the file
+	 * creation failed, but it's a little silly to abort the transaction
 	 * at this point, so let's just make it a NOTICE.
 	 */
 	filename = crypt_getpwdreloadfilename();
-	flagfd = creat(filename, S_IRUSR | S_IWUSR);
-	if (flagfd == -1)
+	flagfd = BasicOpenFile(filename, O_WRONLY | O_CREAT, 0600);
+	if (flagfd < 0)
 		elog(NOTICE, "%s: %m", filename);
 	else
 		close(flagfd);
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 2a6c9466363f0cb0150a61a4c3fdfa290d641475..2d0d733a7c321ad0e47b626b230a2db77466e2ad 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.57 2000/05/31 00:28:27 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.58 2000/06/02 03:58:32 tgl Exp $
  *
  * NOTES:
  *
@@ -202,6 +202,45 @@ pg_fsync(int fd)
 		return 0;
 }
 
+/*
+ * BasicOpenFile --- same as open(2) except can free other FDs if needed
+ *
+ * This is exported for use by places that really want a plain kernel FD,
+ * but need to be proof against running out of FDs.  Once an FD has been
+ * successfully returned, it is the caller's responsibility to ensure that
+ * it will not be leaked on elog()!  Most users should *not* call this
+ * routine directly, but instead use the VFD abstraction level, which
+ * provides protection against descriptor leaks as well as management of
+ * files that need to be open for more than a short period of time.
+ *
+ * Ideally this should be the *only* direct call of open() in the backend.
+ * In practice, the postmaster calls open() directly, and there are some
+ * direct open() calls done early in backend startup.  Those are OK since
+ * this module wouldn't have any open files to close at that point anyway.
+ */
+int
+BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
+{
+	int		fd;
+
+tryAgain:
+	fd = open(fileName, fileFlags, fileMode);
+
+	if (fd >= 0)
+		return fd;				/* success! */
+
+	if ((errno == EMFILE || errno == ENFILE) && nfile > 0)
+	{
+		DO_DB(elog(DEBUG, "BasicOpenFile: not enough descs, retry, er= %d",
+				   errno));
+		errno = 0;
+		ReleaseLruFile();
+		goto tryAgain;
+	}
+
+	return -1;					/* failure */
+}
+
 /*
  * pg_nofile: determine number of filedescriptors that fd.c is allowed to use
  */
@@ -348,7 +387,6 @@ LruInsert(File file)
 
 	if (FileIsNotOpen(file))
 	{
-
 		while (nfile + numAllocatedFiles >= pg_nofile())
 			ReleaseLruFile();
 
@@ -357,15 +395,8 @@ LruInsert(File file)
 		 * to overall system file table being full.  So, be prepared to
 		 * release another FD if necessary...
 		 */
-tryAgain:
-		vfdP->fd = open(vfdP->fileName, vfdP->fileFlags, vfdP->fileMode);
-		if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
-		{
-			errno = 0;
-			ReleaseLruFile();
-			goto tryAgain;
-		}
-
+		vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags,
+								 vfdP->fileMode);
 		if (vfdP->fd < 0)
 		{
 			DO_DB(elog(DEBUG, "RE_OPEN FAILED: %d",
@@ -411,22 +442,6 @@ ReleaseLruFile()
 	LruDelete(VfdCache[0].lruMoreRecently);
 }
 
-/*
- * Force one kernel file descriptor to be released (temporarily).
- */
-bool
-ReleaseDataFile()
-{
-	DO_DB(elog(DEBUG, "ReleaseDataFile. Opened %d", nfile));
-
-	if (nfile <= 0)
-		return (false);
-	Assert(VfdCache[0].lruMoreRecently != 0);
-	LruDelete(VfdCache[0].lruMoreRecently);
-
-	return (true);
-}
-
 static File
 AllocateVfd()
 {
@@ -617,16 +632,7 @@ fileNameOpenFile(FileName fileName,
 	while (nfile + numAllocatedFiles >= pg_nofile())
 		ReleaseLruFile();
 
-tryAgain:
-	vfdP->fd = open(fileName, fileFlags, fileMode);
-	if (vfdP->fd < 0 && (errno == EMFILE || errno == ENFILE))
-	{
-		DO_DB(elog(DEBUG, "fileNameOpenFile: not enough descs, retry, er= %d",
-				   errno));
-		errno = 0;
-		ReleaseLruFile();
-		goto tryAgain;
-	}
+	vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
 
 	if (vfdP->fd < 0)
 	{
@@ -990,6 +996,8 @@ FileMarkDirty(File file)
  * fd.c will automatically close all files opened with AllocateFile at
  * transaction commit or abort; this prevents FD leakage if a routine
  * that calls AllocateFile is terminated prematurely by elog(ERROR).
+ *
+ * Ideally this should be the *only* direct call of fopen() in the backend.
  */
 
 FILE *
@@ -1005,7 +1013,7 @@ AllocateFile(char *name, char *mode)
 TryAgain:
 	if ((file = fopen(name, mode)) == NULL)
 	{
-		if (errno == EMFILE || errno == ENFILE)
+		if ((errno == EMFILE || errno == ENFILE) && nfile > 0)
 		{
 			DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",
 					   errno));
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index e4fd3120d2ca74518421425a2e1409460c70ab21..4c1cac547249e8bed7701b39ed636cb88ce3334c 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.68 2000/05/25 23:30:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.69 2000/06/02 03:58:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1129,10 +1129,11 @@ _mdfd_blind_getseg(char *dbname, char *relname, Oid dbid, Oid relid,
 	}
 #endif
 
+	/* call fd.c to allow other FDs to be closed if needed */
 #ifndef __CYGWIN32__
-	fd = open(path, O_RDWR, 0600);
+	fd = BasicOpenFile(path, O_RDWR, 0600);
 #else
-	fd = open(path, O_RDWR | O_BINARY, 0600);
+	fd = BasicOpenFile(path, O_RDWR | O_BINARY, 0600);
 #endif
 
 	if (fd < 0)
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index fb45e204564aaff58f9212a99a712e5c71df30af..5456f18372af461f34d4e04dfbe9051467089d85 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fd.h,v 1.21 2000/04/12 17:16:51 momjian Exp $
+ * $Id: fd.h,v 1.22 2000/06/02 03:58:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,7 @@
  * Use them for all file activity...
  *
  *	File fd;
- *	fd = FilePathOpenFile("foo", O_RDONLY);
+ *	fd = FilePathOpenFile("foo", O_RDONLY, 0600);
  *
  *	AllocateFile();
  *	FreeFile();
@@ -64,8 +64,10 @@ extern void FileMarkDirty(File file);
 extern FILE *AllocateFile(char *name, char *mode);
 extern void FreeFile(FILE *);
 
+/* If you've really really gotta have a plain kernel FD, use this */
+extern int	BasicOpenFile(FileName fileName, int fileFlags, int fileMode);
+
 /* Miscellaneous support routines */
-extern bool ReleaseDataFile(void);
 extern void closeAllVfds(void);
 extern void AtEOXact_Files(void);
 extern int	pg_fsync(int fd);