aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-01-21 04:38:27 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-01-21 04:38:27 +0000
commit16582d38348e1d9ed14269c9a6a2b9c4255436ad (patch)
tree25908ce53560b8001cfbc7947dab6b0a305b040f
parent4977c2b31b26f5a738f5f85dd03c5275ad3ce058 (diff)
downloadpostgresql-16582d38348e1d9ed14269c9a6a2b9c4255436ad.tar.gz
postgresql-16582d38348e1d9ed14269c9a6a2b9c4255436ad.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.
-rw-r--r--src/backend/access/transam/slru.c35
1 files changed, 10 insertions, 25 deletions
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index 041c6cf84e0..b750b555f2e 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -42,7 +42,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.29.2.1 2005/11/22 18:23:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.29.2.2 2006/01/21 04:38:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -112,7 +112,6 @@ typedef struct SlruFlushData
typedef enum
{
SLRU_OPEN_FAILED,
- SLRU_CREATE_FAILED,
SLRU_SEEK_FAILED,
SLRU_READ_FAILED,
SLRU_WRITE_FAILED,
@@ -546,26 +545,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)
@@ -646,13 +638,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(),