Remove XLogFileInit() ability to unlink a pre-existing file.
authorNoah Misch <[email protected]>
Tue, 29 Jun 2021 01:34:56 +0000 (18:34 -0700)
committerMichael Paquier <[email protected]>
Sun, 6 Apr 2025 05:46:31 +0000 (14:46 +0900)
Only initdb used it.  initdb refuses to operate on a non-empty directory
and generally does not cope with pre-existing files of other kinds.
Hence, use the opportunity to simplify.

This commit has been applied as of 421484f79c0b 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 c9176eea68c4dcc5871b29191da125b0c0ce3c98..d862954709088b93e6f921a14176f562c4d92a1d 100644 (file)
@@ -2452,7 +2452,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
    bool        ispartialpage;
    bool        last_iteration;
    bool        finishing_seg;
-   bool        use_existent;
+   bool        added;
    int         curridx;
    int         npages;
    int         startidx;
@@ -2518,8 +2518,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
                            wal_segment_size);
 
            /* create/use new log file */
-           use_existent = true;
-           openLogFile = XLogFileInit(openLogSegNo, &use_existent);
+           openLogFile = XLogFileInit(openLogSegNo, &added);
            ReserveExternalFD();
        }
 
@@ -3288,9 +3287,7 @@ XLogNeedsFlush(XLogRecPtr record)
  *
  * logsegno: identify segment to be created/opened.
  *
- * *use_existent: if true, OK to use a pre-existing file (else, any
- * pre-existing file will be deleted).  On return, false iff this call added
- * some segment on disk.
+ * *added: on return, true if this call raised the number of extant segments.
  *
  * Returns FD of opened file.
  *
@@ -3300,7 +3297,7 @@ XLogNeedsFlush(XLogRecPtr record)
  * in a critical section.
  */
 int
-XLogFileInit(XLogSegNo logsegno, bool *use_existent)
+XLogFileInit(XLogSegNo logsegno, bool *added)
 {
    char        path[MAXPGPATH];
    char        tmppath[MAXPGPATH];
@@ -3315,19 +3312,17 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent)
    /*
     * Try to use existent file (checkpoint maker may have created it already)
     */
-   if (*use_existent)
+   *added = false;
+   fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
+   if (fd < 0)
    {
-       fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
-       if (fd < 0)
-       {
-           if (errno != ENOENT)
-               ereport(ERROR,
-                       (errcode_for_file_access(),
-                        errmsg("could not open file \"%s\": %m", path)));
-       }
-       else
-           return fd;
+       if (errno != ENOENT)
+           ereport(ERROR,
+                   (errcode_for_file_access(),
+                    errmsg("could not open file \"%s\": %m", path)));
    }
+   else
+       return fd;
 
    /*
     * Initialize an empty (all zeroes) segment.  NOTE: it is possible that
@@ -3440,12 +3435,9 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent)
                 errmsg("could not close file \"%s\": %m", tmppath)));
 
    /*
-    * Now move the segment into place with its final name.
-    *
-    * If caller didn't want to use a pre-existing file, get rid of any
-    * pre-existing file.  Otherwise, cope with possibility that someone else
-    * has created the file while we were filling ours: if so, use ours to
-    * pre-create a future log segment.
+    * Now move the segment into place with its final name.  Cope with
+    * possibility that someone else has created the file while we were
+    * filling ours: if so, use ours to pre-create a future log segment.
     */
    installed_segno = logsegno;
 
@@ -3459,9 +3451,8 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent)
     * CheckPointSegments.
     */
    max_segno = logsegno + CheckPointSegments;
-   if (InstallXLogFileSegment(&installed_segno, tmppath,
-                              *use_existent, max_segno))
-       *use_existent = false;
+   if (InstallXLogFileSegment(&installed_segno, tmppath, true, max_segno))
+       *added = true;
    else
    {
        /*
@@ -3946,7 +3937,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
 {
    XLogSegNo   _logSegNo;
    int         lf;
-   bool        use_existent;
+   bool        added;
    uint64      offset;
 
    XLByteToPrevSeg(endptr, _logSegNo, wal_segment_size);
@@ -3954,10 +3945,9 @@ PreallocXlogFiles(XLogRecPtr endptr)
    if (offset >= (uint32) (0.75 * wal_segment_size))
    {
        _logSegNo++;
-       use_existent = true;
-       lf = XLogFileInit(_logSegNo, &use_existent);
+       lf = XLogFileInit(_logSegNo, &added);
        close(lf);
-       if (!use_existent)
+       if (added)
            CheckpointStats.ckpt_segs_added++;
    }
 }
@@ -5271,7 +5261,7 @@ BootStrapXLOG(void)
    XLogLongPageHeader longpage;
    XLogRecord *record;
    char       *recptr;
-   bool        use_existent;
+   bool        added;
    uint64      sysidentifier;
    struct timeval tv;
    pg_crc32c   crc;
@@ -5368,8 +5358,7 @@ BootStrapXLOG(void)
    record->xl_crc = crc;
 
    /* Create first XLOG segment file */
-   use_existent = false;
-   openLogFile = XLogFileInit(1, &use_existent);
+   openLogFile = XLogFileInit(1, &added);
 
    /*
     * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
@@ -5675,10 +5664,10 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
         * The switch happened at a segment boundary, so just create the next
         * segment on the new timeline.
         */
-       bool        use_existent = true;
+       bool        added;
        int         fd;
 
-       fd = XLogFileInit(startLogSegNo, &use_existent);
+       fd = XLogFileInit(startLogSegNo, &added);
 
        if (close(fd) != 0)
        {
index 4ad20f12b61be8fd0cb12962b5ed6a36500a8aee..b6f07ab81f1d6c3a857cbea4e723a6b95bbf3d83 100644 (file)
@@ -890,11 +890,11 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
 
        if (recvFile < 0)
        {
-           bool        use_existent = true;
+           bool        added = true;
 
            /* Create/use new log file */
            XLByteToSeg(recptr, recvSegNo, wal_segment_size);
-           recvFile = XLogFileInit(recvSegNo, &use_existent);
+           recvFile = XLogFileInit(recvSegNo, &added);
            recvFileTLI = ThisTimeLineID;
        }
 
index 596965d353d03f6167f682de4345ebccdae00d00..1860107f9a2e5db4708ac7995b818fb56800e228 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);
+extern int XLogFileInit(XLogSegNo segno, bool *added);
 extern int XLogFileOpen(XLogSegNo segno);
 
 extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);