diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index a39a98f..8f5fe4d 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -33,7 +33,7 @@ * specific parts are in the libpqwalreceiver module. It's loaded * dynamically to avoid linking the server with libpq. * - * Portions Copyright (c) 2010-2018, PostgreSQL Global Development Group + * Portions Copyright (c) 2010-2017, PostgreSQL Global Development Group * * * IDENTIFICATION @@ -944,6 +944,12 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr) { int startoff; int byteswritten; + static char *zbuffer = NULL; + static int lastfile = -1; + static int lastblock = -1; + + if (zbuffer == NULL) + zbuffer = palloc0(XLOG_BLCKSZ); while (nbytes > 0) { @@ -1040,6 +1046,36 @@ 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; + + 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; + } } /* @@ -1442,8 +1478,7 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) if (!is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS)) { /* - * Only superusers and members of pg_read_all_stats can see details. - * Other users only get the pid value + * Only superusers can see details. Other users only get the pid value * to know whether it is a WAL receiver, but no details. */ MemSet(&nulls[1], true, sizeof(bool) * (tupdesc->natts - 1));