mirror of
https://github.com/postgres/postgres.git
synced 2025-08-18 12:22:09 +03:00
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.
This commit is contained in:
@@ -42,7 +42,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.23.4.1 2005/11/03 00:23:43 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.23.4.2 2006/01/21 04:38:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -112,7 +112,6 @@ typedef struct SlruFlushData
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SLRU_OPEN_FAILED,
|
SLRU_OPEN_FAILED,
|
||||||
SLRU_CREATE_FAILED,
|
|
||||||
SLRU_SEEK_FAILED,
|
SLRU_SEEK_FAILED,
|
||||||
SLRU_READ_FAILED,
|
SLRU_READ_FAILED,
|
||||||
SLRU_WRITE_FAILED,
|
SLRU_WRITE_FAILED,
|
||||||
@@ -546,26 +545,19 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
|
|||||||
* truncated from the commit log. Easiest way to deal with that is
|
* truncated from the commit log. Easiest way to deal with that is
|
||||||
* to accept references to nonexistent files here and in
|
* to accept references to nonexistent files here and in
|
||||||
* SlruPhysicalReadPage.)
|
* 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);
|
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 (fd < 0)
|
||||||
{
|
{
|
||||||
if (errno != ENOENT)
|
slru_errcause = SLRU_OPEN_FAILED;
|
||||||
{
|
slru_errno = errno;
|
||||||
slru_errcause = SLRU_OPEN_FAILED;
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fdata)
|
if (fdata)
|
||||||
@@ -646,13 +638,6 @@ SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid)
|
|||||||
errdetail("could not open file \"%s\": %m",
|
errdetail("could not open file \"%s\": %m",
|
||||||
path)));
|
path)));
|
||||||
break;
|
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:
|
case SLRU_SEEK_FAILED:
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode_for_file_access(),
|
(errcode_for_file_access(),
|
||||||
|
Reference in New Issue
Block a user