diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index a39a98f..2393cb9 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -944,6 +944,9 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) { int startoff; int byteswritten; + static char *zbuffer = NULL; + static int lastfile = -1; + static int lastblock = -1; while (nbytes > 0) { @@ -1040,6 +1043,39 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) LogstreamResult.Write = recptr; } + + /* + * Zero-fill the remaining portion of the last block so that the XLOG reader won't get confused with the garbage left over from a recycled WAL segment. + * Remember the last zero-filled block to avoid filling the same block repeatedly. + */ + if (recvOff % XLOG_BLCKSZ != 0 && + !(recvFile == lastfile && recvOff / XLOG_BLCKSZ == lastblock)) + { + int bytestowrite; + + if (zbuffer == NULL) + zbuffer = palloc0(XLOG_BLCKSZ); + + bytestowrite = XLOG_BLCKSZ - recvOff % XLOG_BLCKSZ; + errno = 0; + byteswritten = write(recvFile, zbuffer, bytestowrite); + if (byteswritten != bytestowrite) + { + /* if write didn't set errno, assume no disk space */ + if (errno == 0) + errno = ENOSPC; + ereport(PANIC, + (errcode_for_file_access(), + errmsg("could not write to log segment %s " + "at offset %u, length %lu: %m", + XLogFileNameP(recvFileTLI, recvSegNo), + recvOff, (unsigned long) bytestowrite))); + } + + lastfile = recvFile; + lastblock = recvOff / XLOG_BLCKSZ; + recvOff += byteswritten; + } } /*