1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Fix race condition if a file is removed while pg_basebackup is running.

If a relation file was removed when the server-side counterpart of
pg_basebackup was just about to open it to send it to the client, you'd
get a "could not open file" error. Fix that.

Backpatch to 9.1, this goes back to when pg_basebackup was introduced.
This commit is contained in:
Heikki Linnakangas
2012-12-21 15:29:49 +02:00
parent 17a71067d0
commit 14aa55df29

View File

@ -43,8 +43,8 @@ typedef struct
static int64 sendDir(char *path, int basepathlen, bool sizeonly);
static void sendFile(char *readfilename, char *tarfilename,
struct stat * statbuf);
static bool sendFile(char *readfilename, char *tarfilename,
struct stat * statbuf, bool missing_ok);
static void sendFileWithContent(const char *filename, const char *content);
static void _tarWriteHeader(const char *filename, const char *linktarget,
struct stat * statbuf);
@ -692,11 +692,18 @@ sendDir(char *path, int basepathlen, bool sizeonly)
}
else if (S_ISREG(statbuf.st_mode))
{
/* Add size, rounded up to 512byte block */
size += ((statbuf.st_size + 511) & ~511);
bool sent = false;
if (!sizeonly)
sendFile(pathbuf, pathbuf + basepathlen + 1, &statbuf);
size += 512; /* Size of the header of the file */
sent = sendFile(pathbuf, pathbuf + basepathlen + 1, &statbuf,
true);
if (sent || sizeonly)
{
/* Add size, rounded up to 512byte block */
size += ((statbuf.st_size + 511) & ~511);
size += 512; /* Size of the header of the file */
}
}
else
ereport(WARNING,
@ -756,9 +763,17 @@ _tarChecksum(char *header)
return sum;
}
/* Given the member, write the TAR header & send the file */
static void
sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
/*
* Given the member, write the TAR header & send the file.
*
* If 'missing_ok' is true, will not throw an error if the file is not found.
*
* Returns true if the file was successfully sent, false if 'missing_ok',
* and the file did not exist.
*/
static bool
sendFile(char *readfilename, char *tarfilename, struct stat *statbuf,
bool missing_ok)
{
FILE *fp;
char buf[TAR_SEND_SIZE];
@ -768,9 +783,13 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
fp = AllocateFile(readfilename, "rb");
if (fp == NULL)
{
if (errno == ENOENT && missing_ok)
return false;
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", readfilename)));
}
/*
* Some compilers will throw a warning knowing this test can never be true
@ -824,6 +843,8 @@ sendFile(char *readfilename, char *tarfilename, struct stat * statbuf)
}
FreeFile(fp);
return true;
}