aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2013-07-01 09:36:00 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2013-07-01 09:36:00 +0300
commit79ce29c734c6a652b2f7193bda537cff0c8eb8c1 (patch)
tree548fae00dfe0880e7d55a3506094ec6184c9dab2
parent129759d6a539059cde85d0dad19992ff45da3bb4 (diff)
downloadpostgresql-79ce29c734c6a652b2f7193bda537cff0c8eb8c1.tar.gz
postgresql-79ce29c734c6a652b2f7193bda537cff0c8eb8c1.zip
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.
-rw-r--r--src/backend/access/transam/xlog.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 66447033695..0ce661bf9f4 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -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;