summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c62
-rw-r--r--src/backend/commands/user.c10
-rw-r--r--src/backend/storage/file/fd.c84
-rw-r--r--src/backend/storage/smgr/md.c7
-rw-r--r--src/include/storage/fd.h8
5 files changed, 72 insertions, 99 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b672cf2c7a9..07a8392c4e4 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 160fa5353be..04303a54b08 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 2a6c9466363..2d0d733a7c3 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:
*
@@ -203,6 +203,45 @@ pg_fsync(int fd)
}
/*
+ * 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
*/
static long
@@ -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 e4fd3120d2c..4c1cac54724 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 fb45e204564..5456f18372a 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);