Commit 728ceba9 authored by Tom Lane's avatar Tom Lane

Avoid leaking FDs after an fsync failure.

Fixes errors introduced in commit bc34223b, as detected by Coverity.

In passing, report ENOSPC for a short write while padding a new wal file in
open_walfile, make certain that close_walfile closes walfile in all cases,
and improve a couple of comments.

Michael Paquier and Tom Lane
parent 3b90e38c
...@@ -86,8 +86,11 @@ mark_file_as_archived(const char *basedir, const char *fname, bool do_sync) ...@@ -86,8 +86,11 @@ mark_file_as_archived(const char *basedir, const char *fname, bool do_sync)
/* /*
* Open a new WAL file in the specified directory. * Open a new WAL file in the specified directory.
* *
* The file will be padded to 16Mb with zeroes. The base filename (without * Returns true if OK; on failure, returns false after printing an error msg.
* partial_suffix) is stored in current_walfile_name. * On success, 'walfile' is set to the FD for the file, and the base filename
* (without partial_suffix) is stored in 'current_walfile_name'.
*
* The file will be padded to 16Mb with zeroes.
*/ */
static bool static bool
open_walfile(StreamCtl *stream, XLogRecPtr startpoint) open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
...@@ -127,18 +130,23 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint) ...@@ -127,18 +130,23 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
} }
if (statbuf.st_size == XLogSegSize) if (statbuf.st_size == XLogSegSize)
{ {
/* File is open and ready to use */
walfile = f;
/* /*
* fsync, in case of a previous crash between padding and fsyncing the * fsync, in case of a previous crash between padding and fsyncing the
* file. * file.
*/ */
if (stream->do_sync && fsync_fname(fn, false, progname) != 0) if (stream->do_sync)
return false; {
if (stream->do_sync && fsync_parent_path(fn, progname) != 0) if (fsync_fname(fn, false, progname) != 0 ||
fsync_parent_path(fn, progname) != 0)
{
/* error already printed */
close(f);
return false; return false;
}
}
/* File is open and ready to use */
walfile = f;
return true; return true;
} }
if (statbuf.st_size != 0) if (statbuf.st_size != 0)
...@@ -150,12 +158,20 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint) ...@@ -150,12 +158,20 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
return false; return false;
} }
/* New, empty, file. So pad it to 16Mb with zeroes */ /*
* New, empty, file. So pad it to 16Mb with zeroes. If we fail partway
* through padding, we should attempt to unlink the file on failure, so as
* not to leave behind a partially-filled file.
*/
zerobuf = pg_malloc0(XLOG_BLCKSZ); zerobuf = pg_malloc0(XLOG_BLCKSZ);
for (bytes = 0; bytes < XLogSegSize; bytes += XLOG_BLCKSZ) for (bytes = 0; bytes < XLogSegSize; bytes += XLOG_BLCKSZ)
{ {
errno = 0;
if (write(f, zerobuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) if (write(f, zerobuf, XLOG_BLCKSZ) != XLOG_BLCKSZ)
{ {
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
fprintf(stderr, fprintf(stderr,
_("%s: could not pad transaction log file \"%s\": %s\n"), _("%s: could not pad transaction log file \"%s\": %s\n"),
progname, fn, strerror(errno)); progname, fn, strerror(errno));
...@@ -173,10 +189,16 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint) ...@@ -173,10 +189,16 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
* using synchronous mode, where the file is modified and fsynced * using synchronous mode, where the file is modified and fsynced
* in-place, without a directory fsync. * in-place, without a directory fsync.
*/ */
if (stream->do_sync && fsync_fname(fn, false, progname) != 0) if (stream->do_sync)
return false; {
if (stream->do_sync && fsync_parent_path(fn, progname) != 0) if (fsync_fname(fn, false, progname) != 0 ||
fsync_parent_path(fn, progname) != 0)
{
/* error already printed */
close(f);
return false; return false;
}
}
if (lseek(f, SEEK_SET, 0) != 0) if (lseek(f, SEEK_SET, 0) != 0)
{ {
...@@ -186,6 +208,8 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint) ...@@ -186,6 +208,8 @@ open_walfile(StreamCtl *stream, XLogRecPtr startpoint)
close(f); close(f);
return false; return false;
} }
/* File is open and ready to use */
walfile = f; walfile = f;
return true; return true;
} }
...@@ -209,6 +233,8 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos) ...@@ -209,6 +233,8 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos)
fprintf(stderr, fprintf(stderr,
_("%s: could not determine seek position in file \"%s\": %s\n"), _("%s: could not determine seek position in file \"%s\": %s\n"),
progname, current_walfile_name, strerror(errno)); progname, current_walfile_name, strerror(errno));
close(walfile);
walfile = -1;
return false; return false;
} }
...@@ -216,6 +242,8 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos) ...@@ -216,6 +242,8 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos)
{ {
fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"), fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
progname, current_walfile_name, strerror(errno)); progname, current_walfile_name, strerror(errno));
close(walfile);
walfile = -1;
return false; return false;
} }
......
...@@ -273,6 +273,7 @@ fsync_fname(const char *fname, bool isdir, const char *progname) ...@@ -273,6 +273,7 @@ fsync_fname(const char *fname, bool isdir, const char *progname)
{ {
fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"), fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
progname, fname, strerror(errno)); progname, fname, strerror(errno));
(void) close(fd);
return -1; return -1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment