Retry short writes when flushing WAL.

We don't normally bother retrying when the number of bytes written by
write() is short of what was requested. It is generally assumed that a
write() to disk doesn't return short, unless you run out of disk space.
While writing the WAL, however, it seems prudent to try a bit harder,
because a failure leads to PANIC. The write() is also much larger than most
write()s in the backend (up to wal_buffers), so there's more room for
surprises.

Also retry on EINTR. All signals used in the backend are flagged SA_RESTART
nowadays, so it shouldn't happen, but better to be defensive.
This commit is contained in:
Heikki Linnakangas 2013-07-01 09:36:00 +03:00
parent 129759d6a5
commit 79ce29c734
1 changed files with 20 additions and 12 deletions

View File

@ -1606,6 +1606,8 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
{ {
char *from; char *from;
Size nbytes; Size nbytes;
Size nleft;
int written;
/* Need to seek in the file? */ /* Need to seek in the file? */
if (openLogOff != startoffset) if (openLogOff != startoffset)
@ -1622,19 +1624,25 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
/* OK to write the page(s) */ /* OK to write the page(s) */
from = XLogCtl->pages + startidx * (Size) XLOG_BLCKSZ; from = XLogCtl->pages + startidx * (Size) XLOG_BLCKSZ;
nbytes = npages * (Size) XLOG_BLCKSZ; nbytes = npages * (Size) XLOG_BLCKSZ;
errno = 0; nleft = nbytes;
if (write(openLogFile, from, nbytes) != nbytes) do
{ {
/* if write didn't set errno, assume no disk space */ errno = 0;
if (errno == 0) written = write(openLogFile, from, nleft);
errno = ENOSPC; if (written <= 0)
ereport(PANIC, {
(errcode_for_file_access(), if (errno == EINTR)
errmsg("could not write to log file %s " continue;
"at offset %u, length %lu: %m", ereport(PANIC,
XLogFileNameP(ThisTimeLineID, openLogSegNo), (errcode_for_file_access(),
openLogOff, (unsigned long) nbytes))); errmsg("could not write to log file %s "
} "at offset %u, length %lu: %m",
XLogFileNameP(ThisTimeLineID, openLogSegNo),
openLogOff, (unsigned long) nbytes)));
}
nleft -= written;
from += written;
} while (nleft > 0);
/* Update state for write */ /* Update state for write */
openLogOff += nbytes; openLogOff += nbytes;