Remove XLogFileInit() ability to skip ControlFileLock.
authorNoah Misch <[email protected]>
Tue, 29 Jun 2021 01:34:55 +0000 (18:34 -0700)
committerMichael Paquier <[email protected]>
Sun, 6 Apr 2025 05:12:12 +0000 (14:12 +0900)
Cold paths, initdb and end-of-recovery, used it.  Don't optimize them.

This commit has been applied as of c53c6b98d38a 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 1f95181b44c8, 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 <[email protected]>
Discussion: https://postgr.es/m/20210202151416[email protected]
Discussion: https://postgr.es/m/20250306193013[email protected]
Backpatch-through: 13

src/backend/access/transam/xlog.c
src/backend/replication/walreceiver.c
src/include/access/xlog.h

index 0334c2d3bba255ecbd675b1c082898f643daac06..20449820c7cb2c7390003c2371d94c064d6b1a84 100644 (file)
@@ -927,8 +927,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);
@@ -2520,7 +2519,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();
        }
 
@@ -3293,10 +3292,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
@@ -3305,7 +3300,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];
@@ -3465,8 +3460,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()
@@ -3623,7 +3617,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");
 }
 
@@ -3647,29 +3641,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)
    {
@@ -3684,8 +3669,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)++;
@@ -3696,14 +3680,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;
 }
@@ -3974,7 +3956,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++;
@@ -4251,7 +4233,7 @@ RemoveXlogFile(const char *segname, XLogSegNo recycleSegNo,
        *endlogSegNo <= recycleSegNo &&
        lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
        InstallXLogFileSegment(endlogSegNo, path,
-                              true, recycleSegNo, true))
+                              true, recycleSegNo))
    {
        ereport(DEBUG2,
                (errmsg_internal("recycled write-ahead log file \"%s\"",
@@ -5388,7 +5370,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
@@ -5697,7 +5679,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)
        {
index 4831a259c48afb9b7c5f0a737db4f5c50525ccf9..4ad20f12b61be8fd0cb12962b5ed6a36500a8aee 100644 (file)
@@ -894,7 +894,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;
        }
 
index ee3e369b79f3bb6eb41f902b2729ebc9f65f2ce9..596965d353d03f6167f682de4345ebccdae00d00 100644 (file)
@@ -296,7 +296,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);