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;
Size nbytes;
Size nleft;
int written;
/* Need to seek in the file? */
if (openLogOff != startoffset)
@ -1622,19 +1624,25 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible, bool xlog_switch)
/* OK to write the page(s) */
from = XLogCtl->pages + startidx * (Size) XLOG_BLCKSZ;
nbytes = npages * (Size) XLOG_BLCKSZ;
errno = 0;
if (write(openLogFile, from, nbytes) != nbytes)
nleft = nbytes;
do
{
/* 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 file %s "
"at offset %u, length %lu: %m",
XLogFileNameP(ThisTimeLineID, openLogSegNo),
openLogOff, (unsigned long) nbytes)));
}
errno = 0;
written = write(openLogFile, from, nleft);
if (written <= 0)
{
if (errno == EINTR)
continue;
ereport(PANIC,
(errcode_for_file_access(),
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 */
openLogOff += nbytes;