diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-01-21 04:38:21 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-01-21 04:38:21 +0000 |
commit | c89a0dd3bb2c1ab5d375335fee1af523e73f79cb (patch) | |
tree | 76a082fd64adcb063ad7cd76c4d7a66325c9a3c4 /src/backend/access/transam/slru.c | |
parent | 4789e9880148660c7126aef4fbaf5563be6ff167 (diff) | |
download | postgresql-c89a0dd3bb2c1ab5d375335fee1af523e73f79cb.tar.gz postgresql-c89a0dd3bb2c1ab5d375335fee1af523e73f79cb.zip |
Repair longstanding bug in slru/clog logic: it is possible for two backends
to try to create a log segment file concurrently, but the code erroneously
specified O_EXCL to open(), resulting in a needless failure. Before 7.4,
it was even a PANIC condition :-(. Correct code is actually simpler than
what we had, because we can just say O_CREAT to start with and not need a
second open() call. I believe this accounts for several recent reports of
hard-to-reproduce "could not create file ...: File exists" errors in both
pg_clog and pg_subtrans.
Diffstat (limited to 'src/backend/access/transam/slru.c')
-rw-r--r-- | src/backend/access/transam/slru.c | 35 |
1 files changed, 10 insertions, 25 deletions
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index d1bfd9570c1..2079d08b1e6 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -41,7 +41,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.33 2005/12/06 23:08:32 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.34 2006/01/21 04:38:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -128,7 +128,6 @@ typedef struct SlruFlushData typedef enum { SLRU_OPEN_FAILED, - SLRU_CREATE_FAILED, SLRU_SEEK_FAILED, SLRU_READ_FAILED, SLRU_WRITE_FAILED, @@ -652,26 +651,19 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) * transactions that have already been truncated from the commit log. * Easiest way to deal with that is to accept references to * nonexistent files here and in SlruPhysicalReadPage.) + * + * Note: it is possible for more than one backend to be executing + * this code simultaneously for different pages of the same file. + * Hence, don't use O_EXCL or O_TRUNC or anything like that. */ SlruFileName(ctl, path, segno); - fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR); + fd = BasicOpenFile(path, O_RDWR | O_CREAT | PG_BINARY, + S_IRUSR | S_IWUSR); if (fd < 0) { - if (errno != ENOENT) - { - slru_errcause = SLRU_OPEN_FAILED; - slru_errno = errno; - return false; - } - - fd = BasicOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, - S_IRUSR | S_IWUSR); - if (fd < 0) - { - slru_errcause = SLRU_CREATE_FAILED; - slru_errno = errno; - return false; - } + slru_errcause = SLRU_OPEN_FAILED; + slru_errno = errno; + return false; } if (fdata) @@ -763,13 +755,6 @@ SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid) errdetail("could not open file \"%s\": %m", path))); break; - case SLRU_CREATE_FAILED: - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not access status of transaction %u", xid), - errdetail("could not create file \"%s\": %m", - path))); - break; case SLRU_SEEK_FAILED: ereport(ERROR, (errcode_for_file_access(), |