Expose fsync_fname as a public API.

Andres Freund
This commit is contained in:
Robert Haas 2013-09-04 11:15:00 -04:00
parent 0c66a22377
commit cc52d5b33f
3 changed files with 57 additions and 59 deletions

View File

@ -27,9 +27,6 @@
#include "miscadmin.h"
static void fsync_fname(char *fname, bool isdir);
/*
* copydir: copy a directory
*
@ -207,59 +204,3 @@ copy_file(char *fromfile, char *tofile)
pfree(buffer);
}
/*
* fsync a file
*
* Try to fsync directories but ignore errors that indicate the OS
* just doesn't allow/require fsyncing directories.
*/
static void
fsync_fname(char *fname, bool isdir)
{
int fd;
int returncode;
/*
* Some OSs require directories to be opened read-only whereas other
* systems don't allow us to fsync files opened read-only; so we need both
* cases here
*/
if (!isdir)
fd = OpenTransientFile(fname,
O_RDWR | PG_BINARY,
S_IRUSR | S_IWUSR);
else
fd = OpenTransientFile(fname,
O_RDONLY | PG_BINARY,
S_IRUSR | S_IWUSR);
/*
* Some OSs don't allow us to open directories at all (Windows returns
* EACCES)
*/
if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
return;
else if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", fname)));
returncode = pg_fsync(fd);
/* Some OSs don't allow us to fsync directories at all */
if (returncode != 0 && isdir && errno == EBADF)
{
CloseTransientFile(fd);
return;
}
if (returncode != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", fname)));
CloseTransientFile(fd);
}

View File

@ -384,6 +384,62 @@ pg_flush_data(int fd, off_t offset, off_t amount)
}
/*
* fsync_fname -- fsync a file or directory, handling errors properly
*
* Try to fsync a file or directory. When doing the latter, ignore errors that
* indicate the OS just doesn't allow/require fsyncing directories.
*/
void
fsync_fname(char *fname, bool isdir)
{
int fd;
int returncode;
/*
* Some OSs require directories to be opened read-only whereas other
* systems don't allow us to fsync files opened read-only; so we need both
* cases here
*/
if (!isdir)
fd = OpenTransientFile(fname,
O_RDWR | PG_BINARY,
S_IRUSR | S_IWUSR);
else
fd = OpenTransientFile(fname,
O_RDONLY | PG_BINARY,
S_IRUSR | S_IWUSR);
/*
* Some OSs don't allow us to open directories at all (Windows returns
* EACCES)
*/
if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
return;
else if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", fname)));
returncode = pg_fsync(fd);
/* Some OSs don't allow us to fsync directories at all */
if (returncode != 0 && isdir && errno == EBADF)
{
CloseTransientFile(fd);
return;
}
if (returncode != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not fsync file \"%s\": %m", fname)));
CloseTransientFile(fd);
}
/*
* InitFileAccess --- initialize this module during backend startup
*

View File

@ -113,6 +113,7 @@ extern int pg_fsync_no_writethrough(int fd);
extern int pg_fsync_writethrough(int fd);
extern int pg_fdatasync(int fd);
extern int pg_flush_data(int fd, off_t offset, off_t amount);
extern void fsync_fname(char *fname, bool isdir);
/* Filename components for OpenTemporaryFile */
#define PG_TEMP_FILES_DIR "pgsql_tmp"