Skip to content

Commit b494640

Browse files
nmischmichaelpq
authored andcommitted
Remove XLogFileInit() ability to unlink a pre-existing file.
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 421484f 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 1f95181, 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
1 parent 8967ddd commit b494640

File tree

3 files changed

+28
-39
lines changed

3 files changed

+28
-39
lines changed

src/backend/access/transam/xlog.c

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,7 +2452,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
24522452
bool ispartialpage;
24532453
bool last_iteration;
24542454
bool finishing_seg;
2455-
bool use_existent;
2455+
bool added;
24562456
int curridx;
24572457
int npages;
24582458
int startidx;
@@ -2518,8 +2518,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
25182518
wal_segment_size);
25192519

25202520
/* create/use new log file */
2521-
use_existent = true;
2522-
openLogFile = XLogFileInit(openLogSegNo, &use_existent);
2521+
openLogFile = XLogFileInit(openLogSegNo, &added);
25232522
ReserveExternalFD();
25242523
}
25252524

@@ -3288,9 +3287,7 @@ XLogNeedsFlush(XLogRecPtr record)
32883287
*
32893288
* logsegno: identify segment to be created/opened.
32903289
*
3291-
* *use_existent: if true, OK to use a pre-existing file (else, any
3292-
* pre-existing file will be deleted). On return, false iff this call added
3293-
* some segment on disk.
3290+
* *added: on return, true if this call raised the number of extant segments.
32943291
*
32953292
* Returns FD of opened file.
32963293
*
@@ -3300,7 +3297,7 @@ XLogNeedsFlush(XLogRecPtr record)
33003297
* in a critical section.
33013298
*/
33023299
int
3303-
XLogFileInit(XLogSegNo logsegno, bool *use_existent)
3300+
XLogFileInit(XLogSegNo logsegno, bool *added)
33043301
{
33053302
char path[MAXPGPATH];
33063303
char tmppath[MAXPGPATH];
@@ -3315,19 +3312,17 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent)
33153312
/*
33163313
* Try to use existent file (checkpoint maker may have created it already)
33173314
*/
3318-
if (*use_existent)
3315+
*added = false;
3316+
fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
3317+
if (fd < 0)
33193318
{
3320-
fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
3321-
if (fd < 0)
3322-
{
3323-
if (errno != ENOENT)
3324-
ereport(ERROR,
3325-
(errcode_for_file_access(),
3326-
errmsg("could not open file \"%s\": %m", path)));
3327-
}
3328-
else
3329-
return fd;
3319+
if (errno != ENOENT)
3320+
ereport(ERROR,
3321+
(errcode_for_file_access(),
3322+
errmsg("could not open file \"%s\": %m", path)));
33303323
}
3324+
else
3325+
return fd;
33313326

33323327
/*
33333328
* Initialize an empty (all zeroes) segment. NOTE: it is possible that
@@ -3440,12 +3435,9 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent)
34403435
errmsg("could not close file \"%s\": %m", tmppath)));
34413436

34423437
/*
3443-
* Now move the segment into place with its final name.
3444-
*
3445-
* If caller didn't want to use a pre-existing file, get rid of any
3446-
* pre-existing file. Otherwise, cope with possibility that someone else
3447-
* has created the file while we were filling ours: if so, use ours to
3448-
* pre-create a future log segment.
3438+
* Now move the segment into place with its final name. Cope with
3439+
* possibility that someone else has created the file while we were
3440+
* filling ours: if so, use ours to pre-create a future log segment.
34493441
*/
34503442
installed_segno = logsegno;
34513443

@@ -3459,9 +3451,8 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent)
34593451
* CheckPointSegments.
34603452
*/
34613453
max_segno = logsegno + CheckPointSegments;
3462-
if (InstallXLogFileSegment(&installed_segno, tmppath,
3463-
*use_existent, max_segno))
3464-
*use_existent = false;
3454+
if (InstallXLogFileSegment(&installed_segno, tmppath, true, max_segno))
3455+
*added = true;
34653456
else
34663457
{
34673458
/*
@@ -3946,18 +3937,17 @@ PreallocXlogFiles(XLogRecPtr endptr)
39463937
{
39473938
XLogSegNo _logSegNo;
39483939
int lf;
3949-
bool use_existent;
3940+
bool added;
39503941
uint64 offset;
39513942

39523943
XLByteToPrevSeg(endptr, _logSegNo, wal_segment_size);
39533944
offset = XLogSegmentOffset(endptr - 1, wal_segment_size);
39543945
if (offset >= (uint32) (0.75 * wal_segment_size))
39553946
{
39563947
_logSegNo++;
3957-
use_existent = true;
3958-
lf = XLogFileInit(_logSegNo, &use_existent);
3948+
lf = XLogFileInit(_logSegNo, &added);
39593949
close(lf);
3960-
if (!use_existent)
3950+
if (added)
39613951
CheckpointStats.ckpt_segs_added++;
39623952
}
39633953
}
@@ -5271,7 +5261,7 @@ BootStrapXLOG(void)
52715261
XLogLongPageHeader longpage;
52725262
XLogRecord *record;
52735263
char *recptr;
5274-
bool use_existent;
5264+
bool added;
52755265
uint64 sysidentifier;
52765266
struct timeval tv;
52775267
pg_crc32c crc;
@@ -5368,8 +5358,7 @@ BootStrapXLOG(void)
53685358
record->xl_crc = crc;
53695359

53705360
/* Create first XLOG segment file */
5371-
use_existent = false;
5372-
openLogFile = XLogFileInit(1, &use_existent);
5361+
openLogFile = XLogFileInit(1, &added);
53735362

53745363
/*
53755364
* We needn't bother with Reserve/ReleaseExternalFD here, since we'll
@@ -5675,10 +5664,10 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
56755664
* The switch happened at a segment boundary, so just create the next
56765665
* segment on the new timeline.
56775666
*/
5678-
bool use_existent = true;
5667+
bool added;
56795668
int fd;
56805669

5681-
fd = XLogFileInit(startLogSegNo, &use_existent);
5670+
fd = XLogFileInit(startLogSegNo, &added);
56825671

56835672
if (close(fd) != 0)
56845673
{

src/backend/replication/walreceiver.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,11 +890,11 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
890890

891891
if (recvFile < 0)
892892
{
893-
bool use_existent = true;
893+
bool added = true;
894894

895895
/* Create/use new log file */
896896
XLByteToSeg(recptr, recvSegNo, wal_segment_size);
897-
recvFile = XLogFileInit(recvSegNo, &use_existent);
897+
recvFile = XLogFileInit(recvSegNo, &added);
898898
recvFileTLI = ThisTimeLineID;
899899
}
900900

src/include/access/xlog.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ extern XLogRecPtr XLogInsertRecord(struct XLogRecData *rdata,
296296
extern void XLogFlush(XLogRecPtr RecPtr);
297297
extern bool XLogBackgroundFlush(void);
298298
extern bool XLogNeedsFlush(XLogRecPtr RecPtr);
299-
extern int XLogFileInit(XLogSegNo segno, bool *use_existent);
299+
extern int XLogFileInit(XLogSegNo segno, bool *added);
300300
extern int XLogFileOpen(XLogSegNo segno);
301301

302302
extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);

0 commit comments

Comments
 (0)