diff --git a/src/bin/pg_basebackup/walmethods.c b/src/bin/pg_basebackup/walmethods.c
index 5cc10c6eba..fe6b034637 100644
--- a/src/bin/pg_basebackup/walmethods.c
+++ b/src/bin/pg_basebackup/walmethods.c
@@ -27,6 +27,7 @@
 
 #include "common/file_perm.h"
 #include "common/file_utils.h"
+#include "common/logging.h"
 #include "pgtar.h"
 #include "receivelog.h"
 #include "streamutil.h"
@@ -51,6 +52,8 @@ typedef struct DirectoryMethodData
 	WalCompressionMethod compression_method;
 	int			compression_level;
 	bool		sync;
+	const char *lasterrstring;	/* if set, takes precedence over lasterrno */
+	int			lasterrno;
 } DirectoryMethodData;
 static DirectoryMethodData *dir_data = NULL;
 
@@ -74,11 +77,17 @@ typedef struct DirectoryMethodFile
 #endif
 } DirectoryMethodFile;
 
+#define dir_clear_error() \
+	(dir_data->lasterrstring = NULL, dir_data->lasterrno = 0)
+#define dir_set_error(msg) \
+	(dir_data->lasterrstring = _(msg))
+
 static const char *
 dir_getlasterror(void)
 {
-	/* Directory method always sets errno, so just use strerror */
-	return strerror(errno);
+	if (dir_data->lasterrstring)
+		return dir_data->lasterrstring;
+	return strerror(dir_data->lasterrno);
 }
 
 static char *
@@ -98,7 +107,7 @@ dir_get_file_name(const char *pathname, const char *temp_suffix)
 static Walfile
 dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_size)
 {
-	static char tmppath[MAXPGPATH];
+	char		tmppath[MAXPGPATH];
 	char	   *filename;
 	int			fd;
 	DirectoryMethodFile *f;
@@ -111,6 +120,8 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 	void	   *lz4buf = NULL;
 #endif
 
+	dir_clear_error();
+
 	filename = dir_get_file_name(pathname, temp_suffix);
 	snprintf(tmppath, sizeof(tmppath), "%s/%s",
 			 dir_data->basedir, filename);
@@ -124,7 +135,10 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 	 */
 	fd = open(tmppath, O_WRONLY | O_CREAT | PG_BINARY, pg_file_create_mode);
 	if (fd < 0)
+	{
+		dir_data->lasterrno = errno;
 		return NULL;
+	}
 
 #ifdef HAVE_LIBZ
 	if (dir_data->compression_method == COMPRESSION_GZIP)
@@ -132,6 +146,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		gzfp = gzdopen(fd, "wb");
 		if (gzfp == NULL)
 		{
+			dir_data->lasterrno = errno;
 			close(fd);
 			return NULL;
 		}
@@ -139,6 +154,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		if (gzsetparams(gzfp, dir_data->compression_level,
 						Z_DEFAULT_STRATEGY) != Z_OK)
 		{
+			dir_data->lasterrno = errno;
 			gzclose(gzfp);
 			return NULL;
 		}
@@ -153,6 +169,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		ctx_out = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
 		if (LZ4F_isError(ctx_out))
 		{
+			dir_data->lasterrstring = LZ4F_getErrorName(ctx_out);
 			close(fd);
 			return NULL;
 		}
@@ -164,6 +181,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		header_size = LZ4F_compressBegin(ctx, lz4buf, lz4bufsize, NULL);
 		if (LZ4F_isError(header_size))
 		{
+			dir_data->lasterrstring = LZ4F_getErrorName(header_size);
 			(void) LZ4F_freeCompressionContext(ctx);
 			pg_free(lz4buf);
 			close(fd);
@@ -173,17 +191,12 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		errno = 0;
 		if (write(fd, lz4buf, header_size) != header_size)
 		{
-			int			save_errno = errno;
-
+			/* If write didn't set errno, assume problem is no disk space */
+			dir_data->lasterrno = errno ? errno : ENOSPC;
 			(void) LZ4F_compressEnd(ctx, lz4buf, lz4bufsize, NULL);
 			(void) LZ4F_freeCompressionContext(ctx);
 			pg_free(lz4buf);
 			close(fd);
-
-			/*
-			 * If write didn't set errno, assume problem is no disk space.
-			 */
-			errno = save_errno ? save_errno : ENOSPC;
 			return NULL;
 		}
 	}
@@ -201,24 +214,17 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 			errno = 0;
 			if (write(fd, zerobuf.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
 			{
-				int			save_errno = errno;
-
+				/* If write didn't set errno, assume problem is no disk space */
+				dir_data->lasterrno = errno ? errno : ENOSPC;
 				close(fd);
-
-				/*
-				 * If write didn't set errno, assume problem is no disk space.
-				 */
-				errno = save_errno ? save_errno : ENOSPC;
 				return NULL;
 			}
 		}
 
 		if (lseek(fd, 0, SEEK_SET) != 0)
 		{
-			int			save_errno = errno;
-
+			dir_data->lasterrno = errno;
 			close(fd);
-			errno = save_errno;
 			return NULL;
 		}
 	}
@@ -234,6 +240,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		if (fsync_fname(tmppath, false) != 0 ||
 			fsync_parent_path(tmppath) != 0)
 		{
+			dir_data->lasterrno = errno;
 #ifdef HAVE_LIBZ
 			if (dir_data->compression_method == COMPRESSION_GZIP)
 				gzclose(gzfp);
@@ -285,10 +292,19 @@ dir_write(Walfile f, const void *buf, size_t count)
 	DirectoryMethodFile *df = (DirectoryMethodFile *) f;
 
 	Assert(f != NULL);
+	dir_clear_error();
 
 #ifdef HAVE_LIBZ
 	if (dir_data->compression_method == COMPRESSION_GZIP)
+	{
+		errno = 0;
 		r = (ssize_t) gzwrite(df->gzfp, buf, count);
+		if (r != count)
+		{
+			/* If write didn't set errno, assume problem is no disk space */
+			dir_data->lasterrno = errno ? errno : ENOSPC;
+		}
+	}
 	else
 #endif
 #ifdef HAVE_LIBLZ4
@@ -315,10 +331,18 @@ dir_write(Walfile f, const void *buf, size_t count)
 											 NULL);
 
 			if (LZ4F_isError(compressed))
+			{
+				dir_data->lasterrstring = LZ4F_getErrorName(compressed);
 				return -1;
+			}
 
+			errno = 0;
 			if (write(df->fd, df->lz4buf, compressed) != compressed)
+			{
+				/* If write didn't set errno, assume problem is no disk space */
+				dir_data->lasterrno = errno ? errno : ENOSPC;
 				return -1;
+			}
 
 			inbuf = ((char *) inbuf) + chunk;
 		}
@@ -328,7 +352,15 @@ dir_write(Walfile f, const void *buf, size_t count)
 	}
 	else
 #endif
+	{
+		errno = 0;
 		r = write(df->fd, buf, count);
+		if (r != count)
+		{
+			/* If write didn't set errno, assume problem is no disk space */
+			dir_data->lasterrno = errno ? errno : ENOSPC;
+		}
+	}
 	if (r > 0)
 		df->currpos += r;
 	return r;
@@ -338,6 +370,7 @@ static off_t
 dir_get_current_pos(Walfile f)
 {
 	Assert(f != NULL);
+	dir_clear_error();
 
 	/* Use a cached value to prevent lots of reseeks */
 	return ((DirectoryMethodFile *) f)->currpos;
@@ -348,10 +381,11 @@ dir_close(Walfile f, WalCloseMethod method)
 {
 	int			r;
 	DirectoryMethodFile *df = (DirectoryMethodFile *) f;
-	static char tmppath[MAXPGPATH];
-	static char tmppath2[MAXPGPATH];
+	char		tmppath[MAXPGPATH];
+	char		tmppath2[MAXPGPATH];
 
 	Assert(f != NULL);
+	dir_clear_error();
 
 #ifdef HAVE_LIBZ
 	if (dir_data->compression_method == COMPRESSION_GZIP)
@@ -371,10 +405,18 @@ dir_close(Walfile f, WalCloseMethod method)
 									  NULL);
 
 		if (LZ4F_isError(compressed))
+		{
+			dir_data->lasterrstring = LZ4F_getErrorName(compressed);
 			return -1;
+		}
 
+		errno = 0;
 		if (write(df->fd, df->lz4buf, compressed) != compressed)
+		{
+			/* If write didn't set errno, assume problem is no disk space */
+			dir_data->lasterrno = errno ? errno : ENOSPC;
 			return -1;
+		}
 
 		r = close(df->fd);
 	}
@@ -433,6 +475,9 @@ dir_close(Walfile f, WalCloseMethod method)
 		}
 	}
 
+	if (r != 0)
+		dir_data->lasterrno = errno;
+
 #ifdef HAVE_LIBLZ4
 	pg_free(df->lz4buf);
 	/* supports free on NULL */
@@ -451,7 +496,10 @@ dir_close(Walfile f, WalCloseMethod method)
 static int
 dir_sync(Walfile f)
 {
+	int			r;
+
 	Assert(f != NULL);
+	dir_clear_error();
 
 	if (!dir_data->sync)
 		return 0;
@@ -460,7 +508,10 @@ dir_sync(Walfile f)
 	if (dir_data->compression_method == COMPRESSION_GZIP)
 	{
 		if (gzflush(((DirectoryMethodFile *) f)->gzfp, Z_SYNC_FLUSH) != Z_OK)
+		{
+			dir_data->lasterrno = errno;
 			return -1;
+		}
 	}
 #endif
 #ifdef HAVE_LIBLZ4
@@ -472,27 +523,41 @@ dir_sync(Walfile f)
 		/* Flush any internal buffers */
 		compressed = LZ4F_flush(df->ctx, df->lz4buf, df->lz4bufsize, NULL);
 		if (LZ4F_isError(compressed))
+		{
+			dir_data->lasterrstring = LZ4F_getErrorName(compressed);
 			return -1;
+		}
 
+		errno = 0;
 		if (write(df->fd, df->lz4buf, compressed) != compressed)
+		{
+			/* If write didn't set errno, assume problem is no disk space */
+			dir_data->lasterrno = errno ? errno : ENOSPC;
 			return -1;
+		}
 	}
 #endif
 
-	return fsync(((DirectoryMethodFile *) f)->fd);
+	r = fsync(((DirectoryMethodFile *) f)->fd);
+	if (r < 0)
+		dir_data->lasterrno = errno;
+	return r;
 }
 
 static ssize_t
 dir_get_file_size(const char *pathname)
 {
 	struct stat statbuf;
-	static char tmppath[MAXPGPATH];
+	char		tmppath[MAXPGPATH];
 
 	snprintf(tmppath, sizeof(tmppath), "%s/%s",
 			 dir_data->basedir, pathname);
 
 	if (stat(tmppath, &statbuf) != 0)
+	{
+		dir_data->lasterrno = errno;
 		return -1;
+	}
 
 	return statbuf.st_size;
 }
@@ -506,9 +571,11 @@ dir_compression_method(void)
 static bool
 dir_existsfile(const char *pathname)
 {
-	static char tmppath[MAXPGPATH];
+	char		tmppath[MAXPGPATH];
 	int			fd;
 
+	dir_clear_error();
+
 	snprintf(tmppath, sizeof(tmppath), "%s/%s",
 			 dir_data->basedir, pathname);
 
@@ -522,6 +589,8 @@ dir_existsfile(const char *pathname)
 static bool
 dir_finish(void)
 {
+	dir_clear_error();
+
 	if (dir_data->sync)
 	{
 		/*
@@ -529,7 +598,10 @@ dir_finish(void)
 		 * directory entry here as well.
 		 */
 		if (fsync_fname(dir_data->basedir, true) != 0)
+		{
+			dir_data->lasterrno = errno;
 			return false;
+		}
 	}
 	return true;
 }
@@ -569,6 +641,7 @@ FreeWalDirectoryMethod(void)
 {
 	pg_free(dir_data->basedir);
 	pg_free(dir_data);
+	dir_data = NULL;
 }
 
 
@@ -594,7 +667,8 @@ typedef struct TarMethodData
 	int			compression_level;
 	bool		sync;
 	TarMethodFile *currentfile;
-	char		lasterror[1024];
+	const char *lasterrstring;	/* if set, takes precedence over lasterrno */
+	int			lasterrno;
 #ifdef HAVE_LIBZ
 	z_streamp	zp;
 	void	   *zlibOut;
@@ -602,19 +676,17 @@ typedef struct TarMethodData
 } TarMethodData;
 static TarMethodData *tar_data = NULL;
 
-#define tar_clear_error() tar_data->lasterror[0] = '\0'
-#define tar_set_error(msg) strlcpy(tar_data->lasterror, _(msg), sizeof(tar_data->lasterror))
+#define tar_clear_error() \
+	(tar_data->lasterrstring = NULL, tar_data->lasterrno = 0)
+#define tar_set_error(msg) \
+	(tar_data->lasterrstring = _(msg))
 
 static const char *
 tar_getlasterror(void)
 {
-	/*
-	 * If a custom error is set, return that one. Otherwise, assume errno is
-	 * set and return that one.
-	 */
-	if (tar_data->lasterror[0])
-		return tar_data->lasterror;
-	return strerror(errno);
+	if (tar_data->lasterrstring)
+		return tar_data->lasterrstring;
+	return strerror(tar_data->lasterrno);
 }
 
 #ifdef HAVE_LIBZ
@@ -642,11 +714,8 @@ tar_write_compressed_data(void *buf, size_t count, bool flush)
 			errno = 0;
 			if (write(tar_data->fd, tar_data->zlibOut, len) != len)
 			{
-				/*
-				 * If write didn't set errno, assume problem is no disk space.
-				 */
-				if (errno == 0)
-					errno = ENOSPC;
+				/* If write didn't set errno, assume problem is no disk space */
+				tar_data->lasterrno = errno ? errno : ENOSPC;
 				return false;
 			}
 
@@ -683,9 +752,15 @@ tar_write(Walfile f, const void *buf, size_t count)
 	/* Tarfile will always be positioned at the end */
 	if (!tar_data->compression_level)
 	{
+		errno = 0;
 		r = write(tar_data->fd, buf, count);
-		if (r > 0)
-			((TarMethodFile *) f)->currpos += r;
+		if (r != count)
+		{
+			/* If write didn't set errno, assume problem is no disk space */
+			tar_data->lasterrno = errno ? errno : ENOSPC;
+			return -1;
+		}
+		((TarMethodFile *) f)->currpos += r;
 		return r;
 	}
 #ifdef HAVE_LIBZ
@@ -698,8 +773,11 @@ tar_write(Walfile f, const void *buf, size_t count)
 	}
 #else
 	else
+	{
 		/* Can't happen - compression enabled with no libz */
+		tar_data->lasterrno = ENOSYS;
 		return -1;
+	}
 #endif
 }
 
@@ -737,7 +815,6 @@ tar_get_file_name(const char *pathname, const char *temp_suffix)
 static Walfile
 tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_size)
 {
-	int			save_errno;
 	char	   *tmppath;
 
 	tar_clear_error();
@@ -751,7 +828,10 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 							O_WRONLY | O_CREAT | PG_BINARY,
 							pg_file_create_mode);
 		if (tar_data->fd < 0)
+		{
+			tar_data->lasterrno = errno;
 			return NULL;
+		}
 
 #ifdef HAVE_LIBZ
 		if (tar_data->compression_level)
@@ -782,7 +862,6 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		/* There's no tar header itself, the file starts with regular files */
 	}
 
-	Assert(tar_data->currentfile == NULL);
 	if (tar_data->currentfile != NULL)
 	{
 		tar_set_error("implementation error: tar files can't have more than one open file");
@@ -824,10 +903,9 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 	tar_data->currentfile->ofs_start = lseek(tar_data->fd, 0, SEEK_CUR);
 	if (tar_data->currentfile->ofs_start == -1)
 	{
-		save_errno = errno;
+		tar_data->lasterrno = errno;
 		pg_free(tar_data->currentfile);
 		tar_data->currentfile = NULL;
-		errno = save_errno;
 		return NULL;
 	}
 	tar_data->currentfile->currpos = 0;
@@ -838,11 +916,10 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		if (write(tar_data->fd, tar_data->currentfile->header,
 				  TAR_BLOCK_SIZE) != TAR_BLOCK_SIZE)
 		{
-			save_errno = errno;
+			/* If write didn't set errno, assume problem is no disk space */
+			tar_data->lasterrno = errno ? errno : ENOSPC;
 			pg_free(tar_data->currentfile);
 			tar_data->currentfile = NULL;
-			/* if write didn't set errno, assume problem is no disk space */
-			errno = save_errno ? save_errno : ENOSPC;
 			return NULL;
 		}
 	}
@@ -875,12 +952,16 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
 		if (!tar_data->compression_level)
 		{
 			/* Uncompressed, so pad now */
-			tar_write_padding_data(tar_data->currentfile, pad_to_size);
+			if (!tar_write_padding_data(tar_data->currentfile, pad_to_size))
+				return NULL;
 			/* Seek back to start */
 			if (lseek(tar_data->fd,
 					  tar_data->currentfile->ofs_start + TAR_BLOCK_SIZE,
 					  SEEK_SET) != tar_data->currentfile->ofs_start + TAR_BLOCK_SIZE)
+			{
+				tar_data->lasterrno = errno;
 				return NULL;
+			}
 
 			tar_data->currentfile->currpos = 0;
 		}
@@ -895,7 +976,7 @@ tar_get_file_size(const char *pathname)
 	tar_clear_error();
 
 	/* Currently not used, so not supported */
-	errno = ENOSYS;
+	tar_data->lasterrno = ENOSYS;
 	return -1;
 }
 
@@ -917,6 +998,8 @@ tar_get_current_pos(Walfile f)
 static int
 tar_sync(Walfile f)
 {
+	int			r;
+
 	Assert(f != NULL);
 	tar_clear_error();
 
@@ -930,7 +1013,10 @@ tar_sync(Walfile f)
 	if (tar_data->compression_level)
 		return 0;
 
-	return fsync(tar_data->fd);
+	r = fsync(tar_data->fd);
+	if (r < 0)
+		tar_data->lasterrno = errno;
+	return r;
 }
 
 static int
@@ -957,7 +1043,10 @@ tar_close(Walfile f, WalCloseMethod method)
 		 * allow writing of the very last file.
 		 */
 		if (ftruncate(tar_data->fd, tf->ofs_start) != 0)
+		{
+			tar_data->lasterrno = errno;
 			return -1;
+		}
 
 		pg_free(tf->pathname);
 		pg_free(tf);
@@ -1018,10 +1107,7 @@ tar_close(Walfile f, WalCloseMethod method)
 	{
 		/* Flush the current buffer */
 		if (!tar_write_compressed_data(NULL, 0, true))
-		{
-			errno = EINVAL;
 			return -1;
-		}
 	}
 #endif
 
@@ -1042,15 +1128,17 @@ tar_close(Walfile f, WalCloseMethod method)
 
 	print_tar_number(&(tf->header[148]), 8, tarChecksum(((TarMethodFile *) f)->header));
 	if (lseek(tar_data->fd, tf->ofs_start, SEEK_SET) != ((TarMethodFile *) f)->ofs_start)
+	{
+		tar_data->lasterrno = errno;
 		return -1;
+	}
 	if (!tar_data->compression_level)
 	{
 		errno = 0;
 		if (write(tar_data->fd, tf->header, TAR_BLOCK_SIZE) != TAR_BLOCK_SIZE)
 		{
-			/* if write didn't set errno, assume problem is no disk space */
-			if (errno == 0)
-				errno = ENOSPC;
+			/* If write didn't set errno, assume problem is no disk space */
+			tar_data->lasterrno = errno ? errno : ENOSPC;
 			return -1;
 		}
 	}
@@ -1080,11 +1168,19 @@ tar_close(Walfile f, WalCloseMethod method)
 
 	/* Move file pointer back down to end, so we can write the next file */
 	if (lseek(tar_data->fd, 0, SEEK_END) < 0)
+	{
+		tar_data->lasterrno = errno;
 		return -1;
+	}
 
 	/* Always fsync on close, so the padding gets fsynced */
 	if (tar_sync(f) < 0)
+	{
+		/* XXX this seems pretty bogus; why is only this case fatal? */
+		pg_log_fatal("could not fsync file \"%s\": %s",
+					 tf->pathname, tar_getlasterror());
 		exit(1);
+	}
 
 	/* Clean up and done */
 	pg_free(tf->pathname);
@@ -1122,9 +1218,8 @@ tar_finish(void)
 		errno = 0;
 		if (write(tar_data->fd, zerobuf, sizeof(zerobuf)) != sizeof(zerobuf))
 		{
-			/* if write didn't set errno, assume problem is no disk space */
-			if (errno == 0)
-				errno = ENOSPC;
+			/* If write didn't set errno, assume problem is no disk space */
+			tar_data->lasterrno = errno ? errno : ENOSPC;
 			return false;
 		}
 	}
@@ -1159,8 +1254,7 @@ tar_finish(void)
 					 * If write didn't set errno, assume problem is no disk
 					 * space.
 					 */
-					if (errno == 0)
-						errno = ENOSPC;
+					tar_data->lasterrno = errno ? errno : ENOSPC;
 					return false;
 				}
 			}
@@ -1180,20 +1274,28 @@ tar_finish(void)
 	if (tar_data->sync)
 	{
 		if (fsync(tar_data->fd) != 0)
+		{
+			tar_data->lasterrno = errno;
 			return false;
+		}
 	}
 
 	if (close(tar_data->fd) != 0)
+	{
+		tar_data->lasterrno = errno;
 		return false;
+	}
 
 	tar_data->fd = -1;
 
 	if (tar_data->sync)
 	{
-		if (fsync_fname(tar_data->tarfilename, false) != 0)
-			return false;
-		if (fsync_parent_path(tar_data->tarfilename) != 0)
+		if (fsync_fname(tar_data->tarfilename, false) != 0 ||
+			fsync_parent_path(tar_data->tarfilename) != 0)
+		{
+			tar_data->lasterrno = errno;
 			return false;
+		}
 	}
 
 	return true;
@@ -1250,4 +1352,5 @@ FreeWalTarMethod(void)
 		pg_free(tar_data->zlibOut);
 #endif
 	pg_free(tar_data);
+	tar_data = NULL;
 }
