1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

Remove XLogFileInit() ability to skip ControlFileLock.

Cold paths, initdb and end-of-recovery, used it.  Don't optimize them.

This commit has been applied as of c53c6b98d3 in v15 and newer
versions.  This is required on stable branches of v13 and v14 to fix a
regression reported by Noah Misch, introduced by 1f95181b44, causing
spurious failures in archive recovery (neither streaming nor archive
recovery) with concurrent restartpoints.  The backpatched versions of
the patches have been aligned on these branches by me, Noah Misch is the
author.  Tests have been conducted by the both of us.

Reported-by: Arun Thirupathi
Author: Noah Misch <noah@leadboat.com>
Discussion: https://postgr.es/m/20210202151416.GB3304930@rfd.leadboat.com
Discussion: https://postgr.es/m/20250306193013.36.nmisch@google.com
Backpatch-through: 13
This commit is contained in:
Noah Misch
2021-06-28 18:34:55 -07:00
committed by Michael Paquier
parent e276b58293
commit df8ec9634c
3 changed files with 16 additions and 34 deletions

View File

@ -917,8 +917,7 @@ static void AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic);
static bool XLogCheckpointNeeded(XLogSegNo new_segno);
static void XLogWrite(XLogwrtRqst WriteRqst, bool flexible);
static bool InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
bool find_free, XLogSegNo max_segno,
bool use_lock);
bool find_free, XLogSegNo max_segno);
static int XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
XLogSource source, bool notfoundOk);
static int XLogFileReadAnyTLI(XLogSegNo segno, int emode, XLogSource source);
@ -2509,7 +2508,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
/* create/use new log file */
use_existent = true;
openLogFile = XLogFileInit(openLogSegNo, &use_existent, true);
openLogFile = XLogFileInit(openLogSegNo, &use_existent);
ReserveExternalFD();
}
@ -3263,10 +3262,6 @@ XLogNeedsFlush(XLogRecPtr record)
* pre-existing file will be deleted). On return, true if a pre-existing
* file was used.
*
* use_lock: if true, acquire ControlFileLock while moving file into
* place. This should be true except during bootstrap log creation. The
* caller must *not* hold the lock at call.
*
* Returns FD of opened file.
*
* Note: errors here are ERROR not PANIC because we might or might not be
@ -3275,7 +3270,7 @@ XLogNeedsFlush(XLogRecPtr record)
* in a critical section.
*/
int
XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
XLogFileInit(XLogSegNo logsegno, bool *use_existent)
{
char path[MAXPGPATH];
char tmppath[MAXPGPATH];
@ -3420,8 +3415,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
*/
max_segno = logsegno + CheckPointSegments;
if (!InstallXLogFileSegment(&installed_segno, tmppath,
*use_existent, max_segno,
use_lock))
*use_existent, max_segno))
{
/*
* No need for any more future segments, or InstallXLogFileSegment()
@ -3578,7 +3572,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
/*
* Now move the segment into place with its final name.
*/
if (!InstallXLogFileSegment(&destsegno, tmppath, false, 0, false))
if (!InstallXLogFileSegment(&destsegno, tmppath, false, 0))
elog(ERROR, "InstallXLogFileSegment should not have failed");
}
@ -3602,29 +3596,20 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
* free slot is found between *segno and max_segno. (Ignored when find_free
* is false.)
*
* use_lock: if true, acquire ControlFileLock while moving file into
* place. This should be true except during bootstrap log creation. The
* caller must *not* hold the lock at call.
*
* Returns true if the file was installed successfully. false indicates that
* max_segno limit was exceeded, or an error occurred while renaming the
* file into place.
*/
static bool
InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
bool find_free, XLogSegNo max_segno,
bool use_lock)
bool find_free, XLogSegNo max_segno)
{
char path[MAXPGPATH];
struct stat stat_buf;
XLogFilePath(path, ThisTimeLineID, *segno, wal_segment_size);
/*
* We want to be sure that only one process does this at a time.
*/
if (use_lock)
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
if (!find_free)
{
@ -3639,8 +3624,7 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
if ((*segno) >= max_segno)
{
/* Failed to find a free slot within specified range */
if (use_lock)
LWLockRelease(ControlFileLock);
LWLockRelease(ControlFileLock);
return false;
}
(*segno)++;
@ -3651,14 +3635,12 @@ InstallXLogFileSegment(XLogSegNo *segno, char *tmppath,
Assert(access(path, F_OK) != 0 && errno == ENOENT);
if (durable_rename(tmppath, path, LOG) != 0)
{
if (use_lock)
LWLockRelease(ControlFileLock);
LWLockRelease(ControlFileLock);
/* durable_rename already emitted log message */
return false;
}
if (use_lock)
LWLockRelease(ControlFileLock);
LWLockRelease(ControlFileLock);
return true;
}
@ -3929,7 +3911,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
{
_logSegNo++;
use_existent = true;
lf = XLogFileInit(_logSegNo, &use_existent, true);
lf = XLogFileInit(_logSegNo, &use_existent);
close(lf);
if (!use_existent)
CheckpointStats.ckpt_segs_added++;
@ -4206,7 +4188,7 @@ RemoveXlogFile(const char *segname, XLogRecPtr lastredoptr, XLogRecPtr endptr)
endlogSegNo <= recycleSegNo &&
lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
InstallXLogFileSegment(&endlogSegNo, path,
true, recycleSegNo, true))
true, recycleSegNo))
{
ereport(DEBUG2,
(errmsg("recycled write-ahead log file \"%s\"",
@ -5342,7 +5324,7 @@ BootStrapXLOG(void)
/* Create first XLOG segment file */
use_existent = false;
openLogFile = XLogFileInit(1, &use_existent, false);
openLogFile = XLogFileInit(1, &use_existent);
/*
* We needn't bother with Reserve/ReleaseExternalFD here, since we'll
@ -5651,7 +5633,7 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
bool use_existent = true;
int fd;
fd = XLogFileInit(startLogSegNo, &use_existent, true);
fd = XLogFileInit(startLogSegNo, &use_existent);
if (close(fd) != 0)
{

View File

@ -922,7 +922,7 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
/* Create/use new log file */
XLByteToSeg(recptr, recvSegNo, wal_segment_size);
recvFile = XLogFileInit(recvSegNo, &use_existent, true);
recvFile = XLogFileInit(recvSegNo, &use_existent);
recvFileTLI = ThisTimeLineID;
}

View File

@ -286,7 +286,7 @@ extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
extern void XLogFlush(XLogRecPtr RecPtr);
extern bool XLogBackgroundFlush(void);
extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
extern int XLogFileInit(XLogSegNo segno, bool *use_existent, bool use_lock);
extern int XLogFileInit(XLogSegNo segno, bool *use_existent);
extern int XLogFileOpen(XLogSegNo segno);
extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);